Tuesday, October 4, 2011

Composing XML is easy

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.

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>
    <p><xi:include href="license.txt" parse="text"/></p>

- XSLT transformation: identity.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
  <xi:include href="copy_template.xml" parse="xml" />


- 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

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:apply-templates select="child::node()" />

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 \

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


1 comment: