Several options.
- An XML DOM (document object model). The org.w3c.Document provided by java would suffice. Then you need to write much code to write every element to EDI. Error prone, easy to forget things and tedious.
- Model classes in java. Java classes that mirror the XML elements. Loaded and saved with JAXB. You can use annotations for XML element and attribute names.
- Transforming the XML into another text format with XSLT. Is only a good fit, when there is an almost one-to-one correspondence between XML and EDI. The advantage is that it is totally declarative. The disadvantage that in XSL it is not easy to develop fast.
Maybe a pragmatic solution would be to use XSLT to transform XML to EDI records plus extra control info, and post-process this output to the final EDI. This would give readable text, for a first raw translation, which in a second phas might be finalized.
For the programmer's heart, you might define some java functions in XSLT, like converting constants to EDI codes.
In XSLT:
I use the example of wikipedia which yields one EDI record.
Usage
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();
}
The XSLT style sheet:
<?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>
The strict usage of xsl:text instead of immediate text causes that the whitespace of the xsl is not outputted.
There are several ways of using XSL. This one tries to follow an EDIFACT grammar of explicitly saying which child elements to pick up. Above I have used D_XXXX
as a not provided optional element. With a test one even can output an EDI value, where XML is missing (***
).
A last remark:
XSLT can be very frustrating at times and one almost hesitates to tell someone to use XSLT.
But the given stylesheet demonstrates that it need not be unreadable (despite the XML verbosity), and as a small language it contains much functionality.