# XInclude processing

## About XInclude

XML Inclusions (XInclude) is a W3C Recommendation that provides XML document authors with a robust way of supporting document modularity via the use of transclusions (inclusions by reference). Such modularity would otherwise require using references to external entities declared in a DTD, a system which has various limitations inherited from SGML.

Unlike XML's built-in entity-reference system, the processing of XIncludes is, fundamentally, an XML Infoset transformation, not strictly an operation performed on the serialized (textual) form of a document. Therefore, there is no requirement for when and where XInclude processing should occur; it could happen at parse time if the parser supports it, or could occur on an already-parsed document.

XInclude references consist of two special elements that are placed in the XML document into which external content is to be included: `<include>` and `<fallback>`, both in the namespace `http://www.w3.org/2001/XInclude`. When processed, these elements are replaced with the content they reference, which can be XML or any other text.

## XInclude support in 4Suite

4Suite supports XInclude processing only at parse time, as an optional feature of the Domlette readers. It is turned on by default, so if you want to suppress it, you must use the full parsing API — not the `Ft.Xml.Parse` and `Ft.Xml.CreateInputSource` convenience functions — and set the parameter `processIncludes` to `False` either when creating an `InputSource` or when calling the `parseString`, `parseUri`, or `parseStream` method of the Domlette reader.

## Examples

The following example includes one section stub into a larger article but has to use the fallback for the second section stub, where resolution fails. lists the contents of the file `article.xml`, which references two sections using XInclude and provides a fallback for each in case they fail to load. lists the contents of `section1.xml`, but this example purposefully does not provide a `section2.xml` in order to illustrate the fallback behaviour. lists the Python code used to parse and print this document; note that XInclude processing is done automatically by default.

### Document using XInclude

    <article>
      <title>My important article</title>
      <xi:include href="section1.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <xi:fallback><!-- Section 1 failed to load! --></xi:fallback>
      </xi:include>
      <xi:include href="section2.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <xi:fallback><!-- Section 2 failed to load! --></xi:fallback>
      </xi:include>
    </article>

### Section to be included

    <section>
      <title>Section 1</title>
      <!-- Write me! -->
    </section>

### Loading the document

    from Ft.Xml import Parse
    from Ft.Xml.Domlette import PrettyPrint
    doc = Parse("article.xml")
    PrettyPrint(doc)

is very similar to the above example, only this version is self-contained; the resources are stored in Python strings and resolved using a custom resolver.

### Self-contained example

    article = """<article><title>My important article</title>
    <xi:include href="ex:section" xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:fallback><!-- Section 1 failed to load! --></xi:fallback>
    </xi:include>
    <xi:include href="ex:section2" xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:fallback><!-- Section 2 failed to load! --></xi:fallback>
    </xi:include>
    </article>"""

    section = "<section><title>Section 1</title><!-- Write me! --></section>"

    from Ft.Lib.Uri import FtUriResolver, Absolutize
    from Ft.Lib import UriException
    from cStringIO import StringIO
    class MyResolver (FtUriResolver):
      def normalize(self, uriRef, baseUri):
        return Absolutize(uriRef, baseUri)
      def resolve(self, uri):
        if uri == "ex:article":
          return StringIO(article)
        elif uri == "ex:section":
          return StringIO(section)
        else:
          raise UriException(UriException.RESOURCE_ERROR,
                             loc=uri, msg="not found, sorry")

    myResolver = MyResolver()

    from Ft.Xml.InputSource import InputSourceFactory
    from Ft.Xml.Domlette import NonvalidatingReader, PrettyPrint
    factory = InputSourceFactory(resolver=myResolver)
    isrc = factory.fromUri("ex:article")
    doc = NonvalidatingReader.parse(isrc)
    PrettyPrint(doc)

To turn off XInclude behavior in , replace the last three lines with these three lines:

    isrc = factory.fromUri("ex:article", processIncludes=False)
    doc = NonvalidatingReader.parse(isrc)
    PrettyPrint(doc)

uses the "super simple" parsing API; we need to use the full parsing API in order to disable XInclude expansion (which, paradoxically, takes one less line):

    from Ft.Xml.Domlette import NonvalidatingReader, PrettyPrint
    doc = NonvalidatingReader.parseStream(file("article.xml"), processIncludes=False)
    PrettyPrint(doc)