XInclude is a very simple but sorely needed "import" facility for XML documents. Like XPath, the ability to use the XInclude standard from Java just arrived in Java 5.0. With the XInclude directive, you can easily include one XML document in another either as XML or as plain (and escaped) text. This means that you can break down your documents into as many files as you see fit and reference the pieces in a simple, standard way. We should note that it has been possible to do this in the past, in a way, using XML entity declarations, but they were fraught with problems. XInclude is simpler and does what its name implies, including the specified document at the current location; you just have to declare the proper namespace for the new <include> element. Here is an example:
<Book xmlns:xi="http://www.w3.org/2001/XInclude"> <Title>Learning Java</Title> <xi:include href="chapter1.xml"/> <xi:include href="chapter2.xml"/> <xi:include href="chapter3.xml"/> ... </Book>
We've used the namespace identifier xi to qualify the <include> elements that we use to import the chapters of our book. By default, the file is imported as XML content, which means that the parser incorporates the included document as part of our document. The resulting DOM or SAX view will show the merged documents as one. Alternatively, we can use the parse attribute to specify that we want the target included as text only. In this case, the text is automatically escaped for us like a CDATA section. For example, we could use it to include an XML example in our book without danger of corrupting our file:
<Example> <Title>The Zoo Inventory Example</Title> <xi:include parse="text " href="zooinventory.xml"/> </Example>
Here, the entire zooinventory.xml file will be included as nicely escaped text for us (not added to our document as XML).
XInclude also allows for "fallback" content to be specified using a nested fallback element. The fallback element may point to another file or simply hold XML to be used if the included file can't be found. For example:
<xi:include parse="text " href="zooinventory.xml"> <xi:fallback href="filenotfound.xml"/> </xi:include> <xi:include parse="text" href="example.xml"> <xi:fallback>This example is missing...</xi:fallback> </xi:include>
In the first case, if zooinventory.xml is not found, the filenotfound.xml file will be included. In the second case, the "missing" text will be included instead of the file. If there is no fallback specified, a parse-time fatal error occurs. An empty fallback element can be used to suppress any error. Fallbacks may also be nested within fallbacks to combine these behaviors.
24.6.1. Enabling XInclude
Getting XInclude to work for us requires simply turning on a couple of flags before we begin parsing our file. First, since the XInclude facility uses namespaces, we have to turn on namespace processing in our parser factory. Second, we have to explicitly tell the parser to interpret the include directives. To modify our PrintDOM example to perform the includes before printing the result, we turn on these flags on the factory, before creating a DocumentBuilder instance:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance( ); // enable XInclude processing factory.setNamespaceAware( true ); factory.setXIncludeAware( true ); DocumentBuilder parser = factory.newDocumentBuilder( ); Document document = parser.parse( input );
We should also mention before we move on that XInclude can make use of XPath expressions (via an API called XPointer) in order to include just selected parts of an XML document.