Pages

Wednesday, August 17, 2005

XML and XSL Reuse: Leveraging XML XInclude with Xerces and Xalan

XInclude is a recommended XML specification from the W3C. It essentially provides an alternative to DTDs external entity references. A good overview of the differences is provided on Elliote Harold's blog. The most appealing reason for using XInclude is that XML includes are fully well-formed documents that can be processed individually.

Let's take a simple example. Let's assume that we have a ContactInfo.xml document:
<?xml version="1.0" encoding="UTF-8"?>
<hrxml:ContactInfo xml:lang="EN"
xmlns:hrxml="http://ns.hr-xml.org/2004-08-02"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../schemas/hrxmlResume-2.3.xsd"
xmlns:xi="http://www.w3.org/2001/XInclude">

<xi:include href="contactinfo/PersonName.xml"/>
</hrxml:ContactInfo>
which includes a PersonName.xml:
<?xml version="1.0" encoding="UTF-8"?>
<hrxml:PersonName xml:lang="EN"
xmlns:hrxml="http://ns.hr-xml.org/2004-08-02"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../schemas/hrxmlResume-2.3.xsd"
xmlns:xi="http://www.w3.org/2001/XInclude">

<hrxml:GivenName>David</hrxml:GivenName>
<hrxml:FamilyName>Le Strat</hrxml:FamilyName>
</hrxml:PersonName>
Each document is fully well-formed and can be transformed individually. In this example, we can create a htmlPersonName.xslt stylesheet to format a person name:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:hrxml="http://ns.hr-xml.org/2004-08-02"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<xsl:template match="hrxml:PersonName">
<xsl:value-of select="hrxml:GivenName" />
<xsl:text> </xsl:text>
<xsl:value-of select="hrxml:FamilyName" />
</xsl:template>
</xsl:stylesheet>
Leveraging Xalan (2.7.0), we can apply the stylesheet to the well-formed PersonName.xml document.

To do so, we can leverage the Xalan command line utility. In this particular example, we invoke the utility through an ant script as described below:
<java classname="org.apache.xalan.xslt.Process" fork="true" dir="." >
<jvmarg value="-Djavax.xml.parsers.DocumentBuilderFactory=
org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"/>
<jvmarg value="-Djavax.xml.parsers.SAXParserFactory=
org.apache.xerces.jaxp.SAXParserFactoryImpl"/>
<jvmarg value="-Dorg.apache.xerces.xni.parser.XMLParserConfiguration=
org.apache.xerces.parsers.XIncludeParserConfiguration"/>
<arg value="-IN"/>
<arg value="${home.dir}/components/contactinfo/${xml.name}.xml"/>
<arg value="-XSL"/>
<arg value="${home.dir}/styles/html${xml.name}.xslt"/>
<arg value="-OUT"/>
<arg value="${home.dir}/output/${xml.name}.html"/>
<arg value="-HTML"/>
<classpath>
...Your classpath...
</classpath>
</java>
The jvmarg are of particular interest as they enable the processing of XML XInclude with the Xerces parser.

In addition, for rendering the ContactInfo.xml, we can leverage XSL include as follow:
<?xml version="1.0" encoding="UTF-8"?<
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:hrxml="http://ns.hr-xml.org/2004-08-02"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<xsl:include href="htmlPersonName.xslt" />

<xsl:template match="hrxml:ContactInfo">
<xsl:apply-templates select="hrxml:PersonName" />
</xsl:template>
</xsl:stylesheet>
And voila, we have achieved a high level of reusability of both presentation and data components!

No comments: