需要帮助将XML / Java转换为edi(834)文档

时间:2014-09-08 12:13:54

标签: java xml edi

我们有许多java库,将edi解析为XML,例如Smooks,ediParser等。

我的用例有点不同。我需要将XML转换为edi文件。我没有找到任何将XML转换为Java的开源。

Smooks文档描述了这种支持(xml-> edi)(http://www.smooks.org/mediawiki/index.php?title=Main_Page),但没有解释。

请指导我如何将xml转换为edi。

1 个答案:

答案 0 :(得分:1)

有几种选择。

  • XML DOM(文档对象模型)。 java提供的 org.w3c.Document 就足够了。然后你需要编写很多代码来将每个元素写入EDI。容易出错,容易忘记和繁琐。
  • java中的模型类。镜像XML元素的Java类。使用 JAXB 加载并保存。您可以对XML元素和属性名称使用注释。
  • 使用 XSLT 将XML转换为另一种文本格式。当XML和EDI之间几乎一一对应时,这只是一个很好的选择。优点是它完全是声明性的。缺点是在XSL中不容易快速开发。

也许一个实用的解决方案是使用XSLT将XML转换为EDI记录 plus 额外的控制信息,并将此输出后处理到最终的EDI。这将为第一个原始翻译提供可读文本,在第二阶段可能最终确定。

对于程序员来说,你可以在XSLT中定义一些java函数,比如将常量转换为EDI代码。


在XSLT中:

我使用wikipedia的例子,它产生一条EDI记录。

<强> 用法

    XmlToEdi xmlToEdi = new XmlToEdi();

    String xml = "<S_NAD>\n" +
        "  <D_3035>BY</D_3035>\n" +
        "  <C_C082><D_3039>CST9955</D_3039><D_3055>91</D_3055></C_C082>\n" +
        "  <C_C080><D_3036>Candy Inc</D_3036></C_C080>\n" +
        "  <C_C059><D_3042>Sirup street 15</D_3042></C_C059>\n" +
        "  <D_3164>Sugar Town</D_3164>\n" +
        "  <D_3251>55555</D_3251>\n" +
        "</S_NAD>";
    String expectedEdi =
            "NAD+BY+CST9955::91++Candy Inc+Sirup street 15+Sugar Town++55555";

    try {
        String edi = xmlToEdi.convert(xml);
        System.out.println(xml);
        System.out.println(edi);
        System.out.println(expectedEdi);
        System.out.println(edi.equals(expectedEdi));
    } catch (TransformerException ex) {
        Logger.getLogger(XmlToEdi.class.getName()).log(Level.SEVERE, null, ex);
    }

Class XmlToEdi:

publicString convert(String xml) throws TransformerConfigurationException,
            TransformerException {
    StringReader xmlFile = new StringReader(xml);
    String xsltFile = getClass().getResource("/workbench2/edi.xsl").toExternalForm();

    Source xmlSource = new StreamSource(xmlFile);
    Source xsltSource = new StreamSource(xsltFile);

    StringWriter edi = new StringWriter();
    Result result = new StreamResult(edi);

    TransformerFactory transFact = TransformerFactory.newInstance();
    Transformer trans = transFact.newTransformer(xsltSource);
    trans.transform(xmlSource, result);
    return edi.toString();
}

XSLT样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
    <!--xsl:strip-space elements="*"/-->

    <xsl:template match="/S_NAD"><xsl:text>NAD</xsl:text>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./D_3035"/><xsl:if test="not(D_3035)">***</xsl:if>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./C_C082"/>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./C_C080"/>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./C_C059"/>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./D_3164"/><xsl:if test="not(D_3164)">***</xsl:if>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./D_XXXX"/><xsl:if test="not(D_XXXX)"></xsl:if>
        <xsl:text>+</xsl:text><xsl:apply-templates select="./D_3251"/><xsl:if test="not(D_3251)">***</xsl:if>
    </xsl:template>

    <xsl:template match="C_C082">
        <xsl:apply-templates select="D_3039"/>
        <xsl:text>:</xsl:text><xsl:apply-templates select="D_XXXX"/>
        <xsl:text>:</xsl:text><xsl:apply-templates select="D_3055"/>
    </xsl:template>

    <xsl:template match="C_C080">
        <xsl:text>+</xsl:text><xsl:apply-templates select="D_XXXX"/>
        <xsl:apply-templates select="D_3036"/>
    </xsl:template>

    <xsl:template match="C_C059">
        <xsl:value-of select="D_3042"/>
    </xsl:template>

</xsl:stylesheet>

严格使用xsl:text而不是立即文本会导致不输出xsl的空格。

有几种使用XSL的方法。这个尝试遵循EDIFACT语法明确说明要拾取哪些子元素。上面我使用D_XXXX作为未提供的可选元素。通过测试,甚至可以输出EDI值,其中缺少XML(***)。

最后一句话:

XSLT有时会非常令人沮丧,而且人们几乎不愿意告诉别人使用XSLT。 但是给定的样式表表明它不需要是不可读的(尽管XML冗长),并且作为一种小语言,它包含很多功能。

相关问题