几个选项。
- XML DOM(文档对象模型)。 java提供的org.w3c.Document就足够了。然后您需要编写大量代码将每个元素写入 EDI。容易出错,容易忘记而且乏味。
- java 中的模型类。反映 XML 元素的 Java 类。使用 JAXB 加载和保存。您可以对 XML 元素和属性名称使用注释。
- 使用 XSLT 将 XML 转换为另一种文本格式。只有在 XML 和 EDI 之间几乎一一对应的情况下才合适。优点是它完全是声明性的。缺点是在 XSL 中不容易快速开发。
也许一个实用的解决方案是使用 XSLT 将 XML 转换为 EDI 记录加上额外的控制信息,并将此输出后处理到最终的 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);
}
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 很冗长),而且作为一种小语言,它包含很多功能。