Remember how Xalan's -i option lets you set the exact number of spaces to indent child elements in the result tree? Saxon offers the same ability, but through an extension attribute, which goes in the stylesheet, rather than as a command-line option. As I walk you through this first extension example, I'll point out the basic requirements for getting a vendor extension to work. Example 15-1, the sloppily indented document keywords.xml, in examples/ch15, contains a nonalphabetical list of keywords from Version 2.3 of the Python programming language. Example 15-1. Python keywords in XML<?xml version="1.0"?> <python version="2.3"> <keyword>while</keyword> <keyword>continue</keyword> <keyword>def</keyword> <keyword>elif</keyword> <keyword>except</keyword> <keyword>from</keyword> <keyword>del</keyword> <keyword>break</keyword> <keyword>print</keyword> <keyword>exec</keyword> <keyword>raise</keyword> <keyword>finally</keyword> <keyword>global</keyword> <keyword>if</keyword> <keyword>and</keyword> <keyword>is</keyword> <keyword>else</keyword> <keyword>import</keyword> <keyword>in</keyword> <keyword>lambda</keyword> <keyword>not</keyword> <keyword>for</keyword> <keyword>class</keyword> <keyword>pass</keyword> <keyword>return</keyword> <keyword>try</keyword> <keyword>yield</keyword> <keyword>or</keyword> <keyword>assert</keyword> </python> Example 15-2, the stylesheet indent.xsl, aims to clean this document to make it more presentable. To do part of the job, it uses Saxon's extension attribute saxon:indent-spaces that was mentioned in Table 15-2. Example 15-2. A stylesheet using a Saxon extension function<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon"> <xsl:output method="xml" saxon:indent-spaces="2" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="python"> <xsl:copy> <xsl:attribute name="version"><xsl:value-of select="@version"/></xsl:attribute> <xsl:apply-templates> <xsl:sort/> </xsl:apply-templates> </xsl:copy> </xsl:template> <xsl:template match="keyword"> <xsl:copy-of select="."/> </xsl:template> </xsl:stylesheet> There are two things you need to know before you can get saxon:indent-spaces to work:
You are already familiar with the first step. The namespace name or URI http://icl.com/saxon is associated with the prefix saxon. You can use whatever prefix you want, but saxon is commonly used probably because it appears in the Saxon documentation. The namespace URI is important, too. This URI http://icl.com/saxon works with Instant Saxon Version 6.5.3. (Later versions of Saxon use http://saxon .sf.net/, but it won't work with Instant Saxon.)
The second step is new to you, or at least I haven't mentioned it yet: you must notify the processor of those namespaces that are used for extension elements (not attributes or functions) by supplying one or more whitespace-separated prefixes in the value of the extension-element-prefixes attribute. Once you have taken care of these two steps, you can start using extensions in your stylesheet and have confidence that they will be recognized as such. The saxon:indent-spaces attribute appears on the output element. This attribute accepts an integer value, which represents the number of space characters that will be used to indent child elements in a result tree. In order to work correctly, the indent attribute must also be specified on output with a value of yes. When you process keywords.xml with this stylesheet: saxon keywords.xml indent.xsl the output, shown in Example 15-3, is nicely indented by two spaces, thanks to Saxon's extension attribute. Example 15-3. Formatted results produced by the saxon:indent-spaces attribute<?xml version="1.0" encoding="utf-8"?> <python version="2.3"> <keyword>and</keyword> <keyword>assert</keyword> <keyword>break</keyword> <keyword>class</keyword> <keyword>continue</keyword> <keyword>def</keyword> <keyword>del</keyword> <keyword>elif</keyword> <keyword>else</keyword> <keyword>except</keyword> <keyword>exec</keyword> <keyword>finally</keyword> <keyword>for</keyword> <keyword>from</keyword> <keyword>global</keyword> <keyword>if</keyword> <keyword>import</keyword> <keyword>in</keyword> <keyword>is</keyword> <keyword>lambda</keyword> <keyword>not</keyword> <keyword>or</keyword> <keyword>pass</keyword> <keyword>print</keyword> <keyword>raise</keyword> <keyword>return</keyword> <keyword>try</keyword> <keyword>while</keyword> <keyword>yield</keyword> </python> The keyword elements are also sorted alphabetically, so the result is certainly more attractive than the source.
|