<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: xinclude.xml 18710 2013-07-15 21:19:17Z dizzzz $ --><book xmlns:xi="http://www.w3.org/2001/XInclude"><bookinfo><style href="styles/default-style.css"/><title>eXist-db – Open Source XML Database</title><author><firstname>Wolfgang M.</firstname><surname>Meier</surname><affiliation><address format="linespecific"><email>wolfgang at exist-db.org</email></address></affiliation></author></bookinfo><chapter><title>XInclude Examples</title><para>eXist-db comes with partial support for the XInclude standard. As default, eXist-db's XML
            serializer will scan all XML fragments for XInclude tags. The XInclude processor is
            implemented as a filter which sits between the serializer's output event stream and the
            receiver. If it finds an XInclude element, it will try to expand it. The current element
            in the stream is replaced by the result of the XInclude operation. XInclude processing
            is thus applied whenever eXist-db serializes an XML fragment, be it a document, the result
            of an XQuery or an XSLT stylesheet.</para><para>eXist-db's support for XInclude is not complete. You cannot directly include raw text, only XML.
            XPointers are restricted to XPath; the additional features defined in the XPointer spec
            (points and locations) are not supported by eXist-db (in fact, no applications support these at the present time), 
            though with eXist-db one can use XPath functions to partly substitute for XPointer's important string-range() function.
        </para><para>eXist-db expands XIncludes at serialization time, which means that the query engine will
            see the XInclude tags <emphasis>before</emphasis> they are expanded. You therefore
            cannot query across XIncludes - unless you create your own code (e.g. an XQuery
            function) for it. We would certainly like to support queries over xincluded content in
            the future though.</para><para>DTD entity declarations can be used for some of the things that XInclude can be used for; 
            in general, however, XInclude is more powerful (except that entity declarations are able include raw text).
        </para><para>
            The following sections present some examples of how XInclude can be used in eXist-db.</para><note><para>In order to see the live effect of most of the
                examples below, install the Demo app via 
                the <ulink url="{dashboard}">Package Manager</ulink> in the <ulink url="{dashboard}">Dashboard</ulink>. 
                You are probably reading this through the Documentation app, but if you are not, you should install this as well.</para></note><section><title>Including an Entire Document</title><para>To include an entire document, just specify its path in the <option>href</option>
                attribute of an <sgmltag>xi:include</sgmltag> tag. 
                For example, one can include a standard disclaimer, stored in the file short-disclaimer.xml, as follows:</para><synopsis language="xml">
                    &lt;xi:include href="/db/apps/doc/data/disclaimer-short.xml"/&gt;</synopsis><para>The result is included below:</para><synopsis language="xml"><xi:include href="/db/apps/doc/data/disclaimer-short.xml"><xi:fallback><p>For this XInclude example to work, you need to install
			the Documentation application. 
			See the Package Manager in the Dashboard.</p></xi:fallback></xi:include></synopsis><para>Please note that you have to provide the correct namespace for
                XInclude, e.g. in the root element of the document. The official namespace is: </para><synopsis>http://www.w3.org/2001/XInclude</synopsis></section><section><title>Error Handling</title><para>An error will be generated if you try to xinclude a resource which does not
                exist. You can specify a fallback to avoid the error. The result of the XInclude
                will be the content of the <sgmltag>xi:fallback</sgmltag> element:</para><synopsis language="xml">
                    &lt;xi:include href="I-do-not exist.xml"&gt;
                        &lt;xi:fallback&gt;&lt;p&gt;The included document was not found!&lt;/p&gt;&lt;/xi:fallback&gt;
                    &lt;xi:include&gt;</synopsis><para>See the result below:</para><synopsis language="xml"><xi:include href="I-do-not exist.xml"><xi:fallback><p>The included document was not found!</p></xi:fallback></xi:include></synopsis><para>Note that a fallback element cannot contain an XInclude.</para></section><section><title>Selection by ID</title><para>The <option>xpointer</option> attribute is used to identify a portion of the
                resource to include. If the xpointer contains the value of an
                attribute of type ID, it will select the element of the target document that has a matching
                attribute of type ID. For example, the following XInclude selects
                the p element from file <filename>disclaimer.xml</filename>, which has an ID
                attribute with value "statement".</para><synopsis language="xml">
                    &lt;xi:include href="disclaimer.xml" xpointer="p"/&gt;</synopsis><para>The result of the XInclude is displayed below:</para><synopsis language="xml"><xi:include href="disclaimer.xml" xpointer="statement"><xi:fallback><p>For this XInclude example to work, you need to install
			the Documentation application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis><para>Note that in case there are several instances of the same ID attribute,
                only the first instance will be selcted.</para></section><section><title>Selecting a Fragment by an XPath Expression</title><para>We may also use an XPath expression to select fragments. The
                <option>xpointer</option> attribute contains an XPointer, which consists of so
                called "schemes". An XPath expression can be passed to the
                <command>xpointer()</command> XPointer scheme. The results of the expression will be
                included in place of the <sgmltag>xi:include</sgmltag> element. The following
                expression includes the first stage direction in Shakespeare's Macbeth:</para><synopsis language="xml">&lt;xi:include href="/db/apps/demo/data/macbeth.xml"
            xpointer="xpointer(//PLAY/ACT[1]/SCENE[1]/STAGEDIR[1])"/&gt;</synopsis><para>As before, the results are included below:</para><synopsis language="xml"><xi:include href="/db/apps/demo/data/macbeth.xml" xpointer="xpointer(//PLAY/ACT[1]/SCENE[1]/STAGEDIR[1])"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis></section><section><title>Selecting a Fragment by a Search Expression</title><para>XIncludes can perform searches, e.g. using full-text search.</para><synopsis language="xml">&lt;xi:include href="/db/apps/demo/data/hamlet.xml" 
                xpointer="xpointer(//SPEECH[ft:query(., '"slings and arrows"')/LINE[1])"/&gt;</synopsis><para>As before, the results are included below:</para><synopsis language="xml"><xi:include href="/db/apps/demo/data/hamlet.xml" xpointer="xpointer(//SPEECH[ft:query(., '&#34;slings and arrows&#34;')]/LINE[1])"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis><para>Note that only the first hit is retrieved – one cannot in this way list all the instances 
                of the word "love" in Romeo and Juliet.</para><para>An XPath expression will be applied to the entire collection if the path in href
                points to a collection and not a single document:</para><synopsis language="xml">&lt;xi:include href="/db/apps/demo/data" 
                xpointer="xpointer(//SPEECH[ft:query(., '"cursed spite"')]/LINE[1])"/&gt;</synopsis><synopsis language="xml"><xi:include href="/db/apps/demo/data" xpointer="xpointer(//SPEECH[ft:query(., '&#34;cursed spite&#34;')]/LINE[1])"><xi:fallback><p>For this XInclude example to work, you need to install the
						Demo application. See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis></section><section><title>Namespaces</title><para>All namespace/prefix mappings declared in the source
                document are passed to the query context. Alternatively, you may declare mappings
                with xmlns().</para><synopsis language="xml">&lt;xi:include href="disclaimer.xml" 
                xpointer="xpointer(//comment:comment)
                xmlns(comment=http://test.org)"/&gt;</synopsis><synopsis language="xml"><xi:include href="disclaimer.xml" xpointer="xpointer(//comment:comment)xmlns(t=http://nop.com)xmlns(comment=http://test.org)"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo app.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis></section><section><title>Transforming XInclude Results</title><para>
                XPath functions can be used to transform the result of an XInclude.
                This can be done for presentation: if a sequence of elements are returned, 
                one might want to render them on separate lines.
            </para><synopsis language="xml">&lt;xi:include href="/db/apps/demo/data" 
                xpointer="xpointer(string-join(
                    //SPEECH[ft:query(., '"cursed spite"')]/LINE
                , '&amp;#xA;'))"/&gt;</synopsis><synopsis language="xml"><xi:include href="/db/apps/demo/data" xpointer="xpointer(string-join(//SPEECH[ft:query(., '&#34;cursed spite&#34;')]/LINE, '&#xA;'))"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis></section><section><title>Implementing XPointer string-range()</title><para>One reason why the XPointer spec has hardly seen any implementation is that 
                it operates with "points" and "locations" which can have no meaning in the XQuery/XPath Data Model.
                However, a major use case for the XPointer specification is to allow pointing at 
                a range of characters inside an element and this is possible using the XPath functions string-join() and substring().</para><para>Here a range of characters in the text node of a LINE element are extracted which is 20 characters long and starts with the 22nd character.</para><synopsis language="xml">&lt;xi:include href="/db/apps/demo/data" 
                xpointer="xpointer(
                substring(string-join(
                //PLAY/ACT[3]/SCENE[1]/SPEECH[19]/LINE[1]
                ,''), 22, 20)
                )"/&gt;</synopsis><synopsis language="xml"><xi:include href="/db/apps/demo/data/hamlet.xml" xpointer="xpointer(substring(string-join(//PLAY/ACT[3]/SCENE[1]/SPEECH[19]/LINE[1],''), 22, 20))"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis><para>Since only the string contents is involved, such ranges may also straddle text nodes belonging to different elements. 
                In the following, the parts of succeeding lines are extracted from the SPEECH element. 
            </para><synopsis language="xml">&lt;xi:include href="/db/apps/demo/data" 
                xpointer="xpointer(
                substring(string-join(
                //PLAY/ACT[3]/SCENE[1]/SPEECH[19]
                ,''), 202, 24)
                )"/&gt;</synopsis><synopsis language="xml"><xi:include href="/db/apps/demo/data/hamlet.xml" xpointer="xpointer(substring(string-join(//PLAY/ACT[3]/SCENE[1]/SPEECH[19],''), 202, 24))"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis></section><section><title>Including the Results of a Stored XQuery</title><para>Another powerful feature is to include the result of a stored XQuery. 
                If the target of an XInclude reference points to an
                XQuery resource stored in the database (i.e. a binary resource with mime-type
                "application/xquery"), the XInclude processor will attempt to compile and execute this
                query. The root element included will be the root element returned by the XQuery
                script. For example:</para><synopsis language="xml">&lt;xi:include href="display-collection.xq"/&gt;</synopsis><para>Calls a query without parameters. The result is shown below:</para><synopsis language="xml"><xi:include href="display-collection.xq"><xi:fallback><p>For this XInclude example to work, you need to install
			the Documentation app.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis><para>The XInclude processor declares two variables in the XQuery's static context:</para><variablelist><varlistentry><term>$xinclude:current-doc</term><listitem><para>the name of the document which xincludes the query (without the collection path)</para></listitem></varlistentry><varlistentry><term>$xinclude:current-collection</term><listitem><para>the collection in which the current document resides</para></listitem></varlistentry></variablelist><para>The example above calls these functions. </para><para>However, we can also pass explicit parameters to the XQuery:</para><synopsis language="xml">&lt;xi:include href="testvars.xq?var1=Hello&amp;var2=World"/&gt;</synopsis><para>The parameters <parameter>var1</parameter> and <parameter>var2</parameter> will be
                available to the XQuery as an external global variable. However, the XQuery needs to
                declare them or an error will be thrown:</para><synopsis language="xquery">declare variable $var1 external;
declare variable $var2 external;</synopsis><para>The result of the call is included below:</para><synopsis language="xml"><xi:include href="testvars.xq?var1=Hello&amp;var2=World"><xi:fallback><p>For this XInclude example to work, you need to install
			the Demo application.
			See the Package Reposistory in the Admin panel.</p></xi:fallback></xi:include></synopsis></section><section><title>Including resources from external URIs or the file system</title><para>If the URI in the href attribute specifies 
			a known scheme (like http: or file:), eXist-db will try to load it as an external 
			resource. For example:</para><synopsis language="xml">&lt;xi:include href="http://localhost:8080/exist/rest/db/apps/doc/data/disclaimer-short.xml"/&gt;</synopsis><para>Should load "disclaimer-short.xml" via HTTP (assuming that the URL is correct
			and you are using the default eXist-db setup):</para><synopsis language="xml"><xi:include href="http://localhost:8080/exist/rest/db/apps/doc/data/disclaimer-short.xml"><xi:fallback><p>Included url not found! Example assumes eXist-db is running at
					http://localhost:8080/exist/</p></xi:fallback></xi:include></synopsis><para>If no scheme is specified, the XInclude processor will first try to load
			the referenced document from the database (relative to the current collection),
			and if that fails, from the file system.</para><para>If the document that contains the XInclude has been constructed in an XQuery,
			relative file system paths will be resolved relative to the main XQuery module 
			source file.</para><para>You can also use XPointers on external resources:</para><synopsis language="xml">
				&lt;xi:include href="http://exist-db.org/exist/index.xml" xpointer="xpointer(//blockquote)"/&gt;
			</synopsis><para>The output of this is shown below:</para><synopsis language="xml"><xi:include href="http://exist-db.org/exist/index.xml" xpointer="xpointer(//blockquote)">
                    <!--<xi:include href="http://demo.exist-db.org/exist/xinclude.xml" xpointer="xpointer(//)xmlns(comment=http://test.org)">--><xi:fallback><p>Lookup failed! Are you sure you have an internet connection? Or is the server down?</p></xi:fallback></xi:include></synopsis></section></chapter></book>