home movie radio music chord lyrics book game Dictionary clip
[ Team LiB ] Previous Section Next Section

2.6 Outputting Processing Instructions

It must come as no surprise that you can add processing instructions, or PIs, to the result tree with the processing-instruction element. This element is formed like this:

<xsl:processing-instruction name="xml-stylesheet">href="new.css"

A processing-instruction element requires one attribute, name, which identifies the target name for the PI. The value of this attribute must be an NCName, and, as such, must not be a QName and cannot contain a colon. In other words, you can't qualify a target name with a namespace.

The content of the processing-instruction element contains the pair of pseudo-attributes href and type that are necessary to apply the CSS stylesheet processing.css to the resulting XML document:

paragraph {font-size: 24pt; font-family: serif}
code {font-family: monospace}

These rules will apply to the paragraph and code elements in the result tree. Provided that you view the result tree in a browser, any paragraph elements will be rendered with a best-fit serif font, in 24-point type, while any code elements will be rendered in a monospace font. (Courier is an example of a monospace font.) You'll get a chance to see the effects of these style rules later on in this section.

In the example that follows, I'll discuss more than just PIs. I'll also talk about a different kind of content in an XML document, and why you have to use more than one template to get at it. Consider for a moment the following XML document, processing.xml, which contains mixed content:

<?xml version="1.0"?>
<message>You can add processing instructions to a document with the <courier>
processing-instruction</courier> element.</message>

2.6.1 Mixed Content

The message element in processing.xml contains mixed content. Mixed content freely mixes character data and element content together. That's why you see tags for the courier element mixed with text in message. Any elements that appear in mixed content are allowed to appear in any order, although they, of course, must also be well-formed. In this context, well-formed elements must either have both start and end tags or must be empty element tags, and the characters used for text and names must follow XML 1.0 rules. (See Section 3.2.2 of the XML specification for more details about mixed content.)

processing.xsl handles the mixed content in processing.xml:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
 <xsl:processing-instruction name="xml-stylesheet">href="processing.css" type="text/css"</xsl:processing-instruction>
 <xsl:element name="doc">
  <xsl:element name="paragraph"><xsl:apply-templates/></xsl:element>
<xsl:template match="courier">
 <xsl:element name="code"><xsl:apply-templates/></xsl:element>

2.6.2 Using Multiple Template Rules

For the first time in this book, you are seeing a stylesheet (processing.xsl) that has more than one template rule. (Remember, a template rule consists of a pattern to match and a constructor telling the processor what to do when the pattern is matched.) The way you design your templates tells the XSLT processor what to look for in a document, and then what to do if and when it finds what you've asked it to find.

In the stylesheet processing.xsl, the first template matches the root node in the document using /. When the processor encounters apply-templates in this template, it matches any children of the root node in the source. When applied to processing.xml, the built-in templates for elements and text match the message element and its child text content.

The next template rule is invoked whenever it encounters a courier element in the source tree. There is only one courier element in processing.xml, so it is only invoked once. If there were more courier elements, it would be invoked for each occurrence of courier. This template also has an apply-templates child, which uses the built-in templates to find the text content of courier (you could try value-of here with the same outcome). As a result, the processor surrounds the character content of courier with code elements, and returns control to the template that invoked it.

The original template, seeing nothing else to do, picks up where the other template left off and takes care of its other work. With the processor holding onto the work that the other template did in a temporary tree, the built-in template for text nodes yanks the character data out of message and surrounds it with paragraph tags.

Somewhere along the way, it surrounds all the elements with the new root element doc. It creates a new PI, too, based on the instructions given by the processing-instruction element. Once that work is done, and the XSLT processor sees that there is nothing left to do, it writes its work out to the result tree, pulls down the shades, locks the door, and calls it quits. What can go in a template rule?

It's obvious that the template element can hold a template rule, but other XSLT elements can hold templates as well. Generally speaking, a template consists of one or more XSLT elements that can create a result tree. These templates are not template rules per se because they don't have to match a pattern—they just contain sequence constructors. Literal result elements and literal text, as well as the apply-templates, attribute, element, comment, processing-instruction, and text elements can all be contained in templates.

The 15 elements that can contain templates (but don't match patterns) are:

  • attribute

  • for-each

  • processing-instruction

  • comment

  • if

  • template

  • copy

  • message

  • variable

  • element

  • otherwise

  • when

  • fallback

  • param

  • with-param

A lot of elements in this list are probably new to you. It would consume pages to tell you what elements can go where in all possible templates, so for now please take this discussion of what templates are on faith. The concept of template rules and templates will continue to unfold throughout the book, all in due time. Meanwhile, Appendix A of Doug Tidwell's XSLT, also published by O'Reilly, provides an excellent XSLT reference and lists in detail what elements can contain, including those that follow in the template category.

2.6.3 Creating the PI and Putting It to Work

Now you can run the processor and see for yourself what the result actually is:

xalan -o proc.xml processing.xml processing.xsl

Here is what proc.xml looks like:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="processing.css" type="text/css"?>
<paragraph>You can add processing instructions to a document with the <code>
processing-instruction</code> element.</paragraph>

Xalan placed the XML stylesheet PI in the document prolog (before the document element doc) because of where the processing-instruction element was placed in the first template. PIs can go anywhere in an XML document except inside other markup, so you can move the processing-instruction element to the second template if you want, and see where it comes out in the output.

The problem is, if the stylesheet PI does not appear in the prolog, the rendering engine (a browser in this case) won't apply the processing.css stylesheet. The point is that the order of templates, and the order of the content of templates, matters in regard to the output of those templates.

Figure 2-3 shows proc.xml displayed in IE.

Figure 2-3. The document proc.xml displayed in IE using processing.css
    [ Team LiB ] Previous Section Next Section