我们有许多java库,将edi解析为XML,例如Smooks,ediParser等。
我的用例有点不同。我需要将XML转换为edi文件。我没有找到任何将XML转换为Java的开源。
Smooks文档描述了这种支持(xml-> edi)(http://www.smooks.org/mediawiki/index.php?title=Main_Page),但没有解释。
请指导我如何将xml转换为edi。
答案 0 :(得分:1)
有几种选择。
也许一个实用的解决方案是使用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冗长),并且作为一种小语言,它包含很多功能。