Tuesday, October 4, 2011

Composing XML is easy

Intro
Sometimes we want to "modularize" some XML archive in some independent parts for a matter of clearness and manageability of simple documents instead of huge ones, lets say XHTML pages, XSLT, XSD, etc.

Many people don't know how to compose, in a generic manner, multiple XML (a no XML also) documents into a big one. It's easier to do, and the answer is XInclude.  Many XInclude examples reflect what I said: Its easy to use!

XInclude It's not a new invention at all, but surprisingly a bunch colleagues of mine don't know about its existence.

Example
Lets stop talking. I going to show you how you can freely merge varios XML (or text) documents into a more complex XML document with XInclude during a XSLT transformation. The example is very straightforward:

- input file: demoxi.html

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude">
  <head>Some title</head>
  <body>
    <p><xi:include href="license.txt" parse="text"/></p>
  </body>
</html>


- XSLT transformation: identity.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:xi="http://www.w3.org/2001/XInclude">
   
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
 
  <xi:include href="copy_template.xml" parse="xml" />

</xsl:stylesheet>

- a text file to include: license.txt

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation Version 3 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See GNU General Public License <http://www.gnu.org/licenses/>.
- a XML file to include in the XSLT: copy_template.xml

<xsl:template match="*" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:element name="{fn:name(.)}" namespace="{fn:namespace-uri(.)}">
        <!-- copy attributes -->
        <xsl:for-each select="@*">
            <xsl:attribute name="{fn:node-name(.)}" select="." />
        </xsl:for-each>
        <xsl:apply-templates select="child::node()" />
    </xsl:element>
</xsl:template>

What's next?


Call an XSLT processor like Saxon in a XInclude aware manner.

$ exec java \
    -classpath saxon.jar \
    -Dorg.apache.xerces.xni.parser.XMLParserConfiguration=org.apache.xerces.parsers.XIncludeParserConfiguration \
    net.sf.saxon.Transform \
    -xi:on \

    -s:demoxi.html \
    -xsl:indentity.xsl

I provide this script to make things more easy. Enjoy it!

References:

1 comment: