Transclusion is the inclusion of all or part of a resource within another one. The name and earliest implementations, like the name and earliest implementations of hypertext, came from Ted Nelson.
XML’s original way to do this, external general entities, could only transclude entire documents, and its SGML-rooted syntax scared some people off. I’ve written of a way to implement transclusion with XSLT, which does let you insert a subtree of another document by specifying that subtree with an XPath expression, but it’s a bit kludgy. The best way to perform transclusion in XML is XInclude, for several reasons:
- It’s a W3C specification designed to complement the others. Many agree
that XML 1.0 DTDs had too many jobs to do, and transclusion was pretty far outside of the general responsibilities of validation. Simple
utilities that perform transclusion well and don’t try to do anything else fit
well with the growing popularity of the pipelining approach to XML processing. - By using the W3C XPointer specification, XInclude lets you be much more granular than even XPath in specifying a portion of another document to include. You can specify a subtree easily enough, but you can also grab a text range of the document being retrieved for insertion into the host document.
(See Elliotte Rusty Harold’s July 2002 introduction to XInclude in XML.com for more background.) There was a good deal of talk (in addition to Eliot Kimber’s presentation) about XInclude at XML Europe, and with good reason: the W3C spec for it became a Candidate Recommendation the week before, and more and more implementations are available. Not all implement the W3C XPointer spec, but libxml does. This was my first exposure to real hands-on XPointer use, and it’s fun.
I love how, if you set the include/@parse attribute to “text” and point the include element at an XML file, the XInclude processor will escape the < and & characters. This will be so useful to me as I write about XML or code that I’ll probably write an Emacs macro to insert <pre><xi:include href=”" parse=”text”/></pre> into documents with one keystroke.
XInclude also makes polling of URI collections very simple. This makes it great for RDF applications, because a key strength of RDF is its ability to store data in geographically distributed locations to be aggregated as needed. If you run libxml’s xmllint utility with the -xinclude option on the following file, you can pipe the output to a program that parses RDF/XML and loads the triples right into a triplestore:
<foafs xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include xi:href="http://www.snee.com/bob/foaf.rdf"/> <xi:include xi:href="http://norman.walsh.name/foaf"/> <xi:include xi:href="http://heddley.com/edd/foaf.rdf"/> <xi:include xi:href="http://simonstl.com/foaf.rdf"/> </foafs>
Or if you want to just pull the rdf:RDF element out of a larger document, your xi:include instruction could follow this model, which takes advantage of XPointer:
<xi:include xi:href="http://www.example.com/some/path/somefile.xml"
xpointer="xmlns(rdf=http://www.w3.org/1999/02/22-rdf-syntax-ns#)
xpointer(//rdf:RDF)"/>
A REST implementation of XInclude that lets us pass a URL to it and then sends an XInclude-processed version back would be a big step forward for transclusion, the web, and for two little-noticed but valuable W3C specs.
Have you used XInclude at all? How about XPointer with or without XInclude?


XInclude example
Aaron Straup Cope has pointed out a tasty example of XInclude use at http://eatdrinkfeelgood.org/examples/1.1/xhtml/styled/ . (See also
http://eatdrinkfeelgood.org/tools/xsl/.)