Processors - XInclude

Introduction

XInclude 1.0 is a simple language for XML inclusions. It's main use is to specify that content from a target XML document must be included at a certain place within a source XML document.

By default, XInclude processing is not automatic in Orbeon Forms, and must be enabled explicitly, except in a few cases described below.

Explicit XInclude handling

There are two ways to use XInclude explicitly in Orbeon Forms:

At parsing time

The XML parser included with Orbeon Forms is able to process XInclude instructions when an XML file is being parsed (i.e. loaded) into Orbeon Forms. This is usually controlled with the URL generator. Example:

<p:processor name="oxf:url-generator">
<p:input name="config">
<config>
<url>oxf:/some-document.xml</url>
<handle-xinclude>true</handle-xinclude>
</config>
</p:input>
<p:output name="data" id="processed-document"/>
</p:processor>

With the XInclude processor

The processor documented here allows to explicitly control the use of XInclude instructions in any XML document, including documents that are not loaded with the URL generator, but dynamically generated. Example:

<p:processor name="oxf:xinclude">
<p:input name="config" href="oxf:/some-document.xml"/>
<p:output name="data" id="processed-document"/>
</p:processor>

This example is equivalent to the example using the URL generator.

NOTE: The correct namespace to use for XInclude 1.0 is http://www.w3.org/2001/XInclude. When using XInclude to perform inclusions, with the XInclude processor or during parsing, be sure to use this correct namespace instead of the older http://www.w3.org/2003/XInclude, which is used by some XML parsers (see next entry). Note that the correct version has the older year, 2001, instead of the newer year, 2003.

Implicit XInclude handling

XInclude processing is implicit in the following cases:

  • Page Flow Controller (PFC) components. PFC page models, page views, and actions automatically go through XInclude processing. This in particular allows for using XInclude in static XHTML or dynamic XSLT page views. In this case, XInclude can make use of the special URIs input:data and input:instance to access data and instance documents fed to the page view.
  • XPL processor definitions. Processor definitions (usually stored in a file called processors.xml) may use XInclude.
  • Logging configuration. Logging configuration (usually stored in a file called log4j.xml) may use XInclude.

Note that, in particular, XInclude processing is not implicit in the following cases:

  • XPL href attribute. In the following example:

    <p:input name="my-input-name" href="some-document.xml"/>

    In this case, the content of some-document.xml will not be processed by XInclude before being sent to the my-input-name input.

  • XPL schema-href attribute. Similarly, XML schemas do not go through XInclude processing.

XInclude processor

Inputs and outputs

Type Name Purpose Mandatory
Input config XML document with XInclude elements. Yes
 Input attributes Configuration attributes [SINCE: 2011-03-10]  No
Input User-defined inputs User-defined inputs accessible with URLs of the form input:custom-input. No
Output data The result of the transformation. Yes

Config input

The config input receives an XML document which may contain XInclude elements. If it doesn't contain any XInclude elements, the content of the document will be produced without modifications on the XInclude processor's data output.

The main XInclude element is xi:include. The prefix, usually xi, must be bound to the namespace http://www.w3.org/2001/XInclude. xi:include takes a mandatory href attribute, which must contain an URL such as an oxf:, file: or http: URL. In addition, URIs of the form input:* are supported, to allow access to user-defined inputs connected to the XInclude processor.

This is a fragment of an XForms page using XInclude, in a resource named view.xhtml:

<xhtml:html xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xxforms="http://orbeon.org/oxf/xml/xforms" xmlns:xi="http://www.w3.org/2001/XInclude">
<xhtml:head>
<xhtml:title>XForms Text Controls</xhtml:title>
<xforms:model id="main-model">
<xforms:instance id="instance">
<!-- This is where the inclusion is performed -->
<xi:include href="main-xforms-instance.xml"/>
</xforms:instance>
</xforms:model>
</xhtml:head>
...
</xhtml:html>

With the example above, the resource main-xforms-instance.xml can contain:

<instance>
<age>35</age>
<secret>42</secret>
<textarea>The world is but a canvas for the imagination.</textarea>
<label>Hello, World!</label>
<date>2004-01-07</date>
...
</instance>

The processor is configured as follows:

<p:processor name="oxf:xinclude">
<p:input name="config" href="view.xhtml"/>
<p:output name="data" id="result"/>
</p:processor>

The result of the inclusion on the data output is:

<xhtml:html xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xxforms="http://orbeon.org/oxf/xml/xforms" xmlns:xi="http://www.w3.org/2001/XInclude-doc">
<xhtml:head>
<xhtml:title>XForms Text Controls</xhtml:title>
<xforms:model id="main-model">
<xforms:instance id="instance">
<instance xml:base="oxf:/examples/xforms/xforms-controls/main-xforms-instance.xml">
<age>35</age>
<secret>42</secret>
<textarea>The world is but a canvas for the imagination.</textarea>
<label>Hello, World!</label>
<date>2004-01-07</date>
...
</instance>
</xforms:instance>
</xforms:model>
</xhtml:head>
...
</xhtml:html>

Notice how the xi:include element has been replaced with the entire content of the included file. In addition, a new xml:base attribute has been added, as per the XInclude specification. It specifies the base URI that must be used to resolve relative URIs in the included document.

An included document may in turn use further xi:include elements to perform nested inclusions.

It is possible to tell the XInclude processor not to produce xml:base on an inclusion by using the xxi:omit-xml-base extension attribute (the XInclude errata now allow such a feature to be provided by implementations). The attribute takes value false (the default) or true, and the namespace must be mapped for example using xmlns:xxi="http://orbeon.org/oxf/xml/xinclude". Example:

<xhtml:html xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xxi="http://orbeon.org/oxf/xml/xinclude" xmlns:xi="http://www.w3.org/2001/XInclude">
<xhtml:head>
<xhtml:title>XForms Text Controls</xhtml:title>
<xforms:model id="main-model">
<xforms:instance id="instance">
<!-- This is where the inclusion is performed -->
<xi:include href="main-xforms-instance.xml" xxi:omit-xml-base="true"/>
</xforms:instance>
</xforms:model>
</xhtml:head>
...
</xhtml:html>

This produces:

<xhtml:html xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xxforms="http://orbeon.org/oxf/xml/xforms" xmlns:xi="http://www.w3.org/2001/XInclude-doc">
<xhtml:head>
<xhtml:title>XForms Text Controls</xhtml:title>
<xforms:model id="main-model">
<xforms:instance id="instance">
<instance>
<age>35</age>
<secret>42</secret>
<textarea>The world is but a canvas for the imagination.</textarea>
<label>Hello, World!</label>
<date>2004-01-07</date>
...
</instance>
</xforms:instance>
</xforms:model>
</xhtml:head>
...
</xhtml:html>

Notice how there is no longer an xml:base attribute at the point of inclusion. This can be quite useful when performing schema validation on the result, or when xml:base resolution on the result must be performed relative to the URL base of the including document.

NOTE: The XInclude processor only supports xi:include with the href attribute and an optional parse attribute set to the constant xml. Other features of XInclude such as the xpointer, encoding, accept or accept-language attributes, and xi:fallback are not supported. It is planned to enhance the XInclude processor over time to support those features.

User-defined inputs

User-defined inputs allow the XInclude processor do include dynamically generated XML documents. For example, connecting the XInclude processor as follows:

<p:processor name="oxf:xinclude">
<p:input name="config" href="view.xhtml"/>
<p:input name="my-dynamic-content" href="#some-dynamic-content"/>
<p:output name="data" id="result"/>
</p:processor>

It is possible to include the XML document available on the custom my-dynamic-content input by using input:* URIs, for example with the following document as the config input:

<xhtml:html xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xxforms="http://orbeon.org/oxf/xml/xforms" xmlns:xi="http://www.w3.org/2001/XInclude">
<xhtml:head>
<xhtml:title>XForms Text Controls</xhtml:title>
<xforms:model id="main-model">
<xforms:instance id="instance">
<!-- This is where the inclusion is performed -->
<xi:include href="input:my-dynamic-content"/>
</xforms:instance>
</xforms:model>
</xhtml:head>
...
</xhtml:html>

This makes the XInclude processor very versatile as a simple template processor.

The xpointer attribute

[SINCE: 2011-03-10]

The <xi:include> element supports the xpointer attribute with the xpath() scheme.

This allows fine-grained control of what exactly, in the included document, gets inserted into the final document. You simply provide an XPath 2.0 expression within the xpath() scheme:


<xi:include href="included.xml" xpointer="xpath(/*/items/item)"/>

NOTE: When the xpointer attribute is provided, the included document is first entirely loaded into memory before the XPath expression is applied. This can have a negative performance impact.

XML external entities

XML external entities are a relatively rarely used feature of XML, which allows you to specify, at the top of your XML document, a mapping between a name and a file. For example:

<!DOCTYPE foo [
    <!ENTITY bar SYSTEM "bar.xml">
]>

<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xhtml:body>
        &bar;
    </xhtml:body>
</xhtml:html>

Here, anytime you write &bar;, the content of the bar.xml file is loaded and replaces the occurrence of &bar;. This allows you to perform inclusions, but without the use of XInclude.

By default, XML documents loaded by the XInclude processor process XML external entities.

You can configure the XInclude processor to ignore external entities by using the optional attributes input:
<p:processor name="oxf:xinclude">
<p:input name="config" href="view.xhtml"/>
<p:input name="attributes"> <attributes xmlns:xs="http://www.w3.org/2001/XMLSchema"> <attribute as="xs:boolean" name="external-entities" value="false"/> </attributes> </p:input>
<p:output name="data" id="result"/>
</p:processor>
NOTE: This setting does not apply to the config input, which, when it reaches the XInclude processor, has already been parsed.

XML external entities or XPointer?

Both XML external entities or the xpointer attribute allow doing more than simply include a full XML document into another. Processing is done by different pieces of software:
  • the XML parser processes external entities
  • the XInclude processor processes the xpointer attribute
Use XPointer when:
  • the document to include is a well-formed XML document
  • you need to extract parts of a document only
  • it is ok to load the entire document to include in memory first
Use external entities when:
  • the document to include is not a well-formed XML document
  • you need to include the document as-is
  • the document to include is pretty large and it is better not to load it entirely in memory first
Whenever possible, we recommend using XInclude rather than external entities.

Comments