External code files

You may want to insert external program files into your DocBook documents to use as examples. That way you don't have to type them into your document and maintain them there. It would also be nice if you didn't have to escape the special XML characters such as < and & which are used in programming languages.

This can be done in two ways: with an XSLT extension in Saxon or Xalan, or with XInclude for xsltproc.

The stylesheets come with an XSLT extension function to insert text from a file and escape the XML markup characters. Such extension functions are available for Saxon and Xalan, but not currently for xsltproc. To enable this extension, you have to set two parameters, either in your customization layer or on the command line. The parameters are use.extensions=1 and textinsert.extension=1. Both must be set for it to work. You must also make sure the appropriate DocBook extensions file is included in your Java CLASSPATH. See the Saxon or Xalan section in the section “Installing an XSLT processor” for more on setting the CLASSPATH.

Once the parameters and CLASSPATH are properly set, then you can use markup like this to insert an external text file:

<example><title>My program listing</title>
  <programlisting><textobject><textdata  
     fileref="mycode.c" /></textobject></programlisting>
</example>

You can also use entityref instead of fileref so that you are referencing a system entity instead of a file pathname. Using a system entity provides one level of indirection, enabling you to change the declaration of the system entity in the DTD without having to edit the reference to it in the document. The system entity declaration must indicate the NDATA type as linespecific (which is declared in the DTD), so the processor knows it is a text file. The following is an example of declaring a system entity and then referencing it.

<!DOCTYPE book SYSTEM "docbook.dtd" [
<!ENTITY code3 SYSTEM "codesamples/mycode.c" NDATA linespecific>
]>
<book>
...
<example><title>My program listing</title>
  <programlisting><textobject><textdata  
     entityref="code3" /></textobject></programlisting>
</example>

If for some reason the entity reference does not resolve, then your programlisting will be blank.

Note

If your DTD is earlier than version 4.2, then you can't put a textobject directly inside a programlisting. You have to use an imageobject element inside a inlinemediaobject element. And you must add a format="linespecific" attribute to its imagedata element, as in the following example.

For DocBook 4.1.2 DTD and earlier:
<programlisting><inlinemediaobject><imageobject><imagedata  
    fileref="mycode.c"  
    format="linespecific"/></imageobject></inlinemediaobject>
<programlisting>

Notice that the elements inside these programlisting examples have no space or line breaks between elements, only between attributes. That's because spaces and line breaks between elements are always preserved inside programlisting, so this style avoids introducing extraneous spaces in the output. You can break a line between attributes within an element's start tag.

Missing text

If your output does not have the included text, then you need to check for these problems:

  • If instead of the code text you get an xlink element in your output, then the two extension parameters described above have not been properly set.

  • If the two parameters are properly set, and you get a message about "No insertfile extension available.", then either you need to use Saxon or Xalan, or the CLASSPATH does not include the Saxon or Xalan extension file.

  • If you get a message "Cannot read file:...", then the textinsert extension is working, but the pathname is not resolving, or the file is unreadable by the process.

Using XInclude for text inclusions

If you are using an XInclude-enabled processor such as xsltproc, then you can use an XInclude element instead of a textobject element. The following is an example that accomplishes the same as the previous example:

<example><title>My program listing</title>
  <programlisting><xi:include  href="mycode.c"  parse="text"  
      xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>
</example>

The parse="text" attribute ensures that any characters that might be misinterpreted as XML are properly escaped when the text is included. But using parse="text" also means you cannot select part of the external file with XPointer syntax, because the file is not treated as XML (even if it happens to be XML).

Since the xi:include element is not part of the standard DocBook DTD, you will get validation errors when you try to validate a document with such a programlisting. However, you can add xi:include to the DTD, as described in the section “DTD customizations for XIncludes”, to avoid such errors.