By Michael Fitzgerald
Price: $34.95 USD
£24.95 GBP
Cover | Table of Contents | Colophon
http://www.docbook.org)
to XHTMLhttp://www.w3.org/TR/REC-xml.html.http://www.w3.org/TR/xsl/). XSL-FO is a
language for applying styles and formatting to XML documents. It is
similar to Cascading Style Sheets (CSS), but it is written in XML and
is somewhat more extensive. (http://www.oreilly.com/catalog/learnxslt/learningxslt.zip.
All example files mentioned in a particular chapter are in the
examples directory of the archive, under the
subdirectory for that chapter (such as
examples/ch01,
examples/ch02, and so forth). Throughout the
book, I assume that these examples are installed at
C:\LearningXSLT\examples on Windows or in
something like /usr/mike/learningxslt/examples
on a Unix machine.<msg/>
msg is the document
element
. The document element is sometimes
called the root element
, but this is not to be confused with
the root node, which will be explained later in
this chapter. The first element in any well-formed XML document is
always considered the document element, as long as it also contains
all other elements in the document (if it has any other elements in
it). In order for XML to be
well-formed
, it must follow the syntax rules laid out
in the XML specification. I'll highlight
well-formedness rules throughout this book, when appropriate.
Found it! onto the browser's
canvas or rendering space.template element is
apply-templates. Because
apply-templates
is contained in
template, it is called a child
element
of template. In
XSLT, apply-templates is also termed an
instruction
element
. An instruction element in XSLT is
always contained within something called a
template
.
A template is a series of transformation instructions that usually
appear within a template element, but not always.
A few other elements can contain instructions, as you will see later
on. XSLT 1.0 has a number of instruction elements that will
eventually be explained and discussed in this book.apply-templates element triggers the
processing of the children of the
node
in the source document that the template matches. These children
(child nodes)
can be elements, attributes, text, comments, and processing
instructions. If the apply-templates element has a
select attribute, the XSLT processor searches
exclusively for other nodes that match the value of the
select attribute. These nodes are then subject to
being processed by other templates in the stylesheet that match those
nodes.apply-templates works in the next chapter.apply-templates works, first
take a look at the document message.xml in
examples/ch01:<?xml version="1.0"?> <message priority="low">Hey, XSLT isn't so hard after all!</message>
message element in
message.xml has an attribute in its start tag:
the priority attribute with a value of
low. Also, this element is not empty; it holds the
string Hey, XSLT
isn't
so
hard
after
all! In the terminology of XML, this text is
called parsed character
data
, and in the terminology of XPath, this
text is called a text, element,
attribute, attribute-set,
comment, and
processing-instruction elements. In addition,
you'll get your first encounter with attribute value
templates, which provide a way to define templates inside attribute
values.<?xml version="1.0"?> <message>You can easily add text to your output.</message>
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
<output method="text"/>
<template match="/">Message: <apply-templates/></template>
</stylesheet>
/), the beginning point of
the source document.message.<?xml version="1.0"?> <message>You can easily add text to your output.</message>
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
<output method="text"/>
<template match="/">Message: <apply-templates/></template>
</stylesheet>
/), the beginning point of
the source document.message.apply-templates processes the text child node of a
message using the built-in template for text.xalan text.xml txt.xsl
Message: You can easily add text to your output.
msg literal result element from a different
namespace:<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"> <output method="xml" indent="yes"/> <template match="/"> <msg xmlns="http://www.wyeast.net/msg"> <apply-templates xmlns="http://www.w3.org/1999/XSL/Transform"/> </msg> </template> </stylesheet>
<?xml version="1.0"?> <message>You can use literal result elements in stylesheets.</message>
xalan literal.xml tedious.xsl
<?xml version="1.0" encoding="UTF-8"?> <msg xmlns="http://www.wyeast.net/msg">You can use literal result elements in stylesheets.</msg>
msg
element has its own namespace
declaration. This is because the XSLT processor would reject the
stylesheet if it did not have a namespace declaration. The
apply-templates element that follows must also
redeclare the XSLT namespace because the processor will produce
unexpected results without it. (Try it and you'll
see.)element
. The following document,
element.xml, is similar to
literal.xml, which you saw earlier in this
chapter:<?xml version="1.0"?> <message>You can use the element element to create elements on the result tree. </message>
element
instead of a literal result element to create a new element in the
output:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="message">
<xsl:element name="{concat('my', name( ))}"><xsl:apply-templates/></xsl:element>
</xsl:template>
</xsl:stylesheet>
element has three attributes. The
name attribute is required as it obviously
specifies a name for the element. In this example, the
name attribute uses an attribute value template to
compute a name for the element. In other words, the name of the
element is computed by using the concat(
)
and name(
)
functions to contrive a new name based on the name of the current
node. This is useful when you don't have the name of
a node until you actually perform the transformation (at runtime).name—you could use any legal
XML name you want in the value. Computing the name, however, is one
justification for using element. Another
justification is using attribute sets, which you'll
learn about presently. Otherwise, you might as well use a literal
result element, but the choice remains yours.element
has two other attributes beside
name: namespace and
use-attribute-sets, which are optional.
I'll discuss namespace here, and
I'll explain how to work with
use-attribute-sets in Section 2.4.1, a little later in this
chapter.namespace attribute identifies a namespace
name to associate with the element. If
paragraph
in a result tree, all you have to do is add an XSLT
attribute element as a child of
element. The stylesheet
attribute.xsl does just that:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="paragraph">
<xsl:attribute name="priority">medium</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
element, attribute can
have name and namespace
attributes. Again, the name attribute, which
specifies the name of an attribute for the result tree, is required,
while namespace is not. The
namespace attribute works pretty much like it does
in element. The values of both
name and namespace can be
computed by using an attribute value template, just as in
element.xalan attribute.xml attribute.xsl
priority attribute:<?xml version="1.0" encoding="UTF-8"?> <paragraph priority="medium">You can use the attribute element to create attributes on the result tree.</paragraph>
paragraph for a total of three
attributes. One of the additional attributes will have a namespace,
and one will not:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:element name="paragraph"> <xsl:attribute name="priority">medium</xsl:attribute> <xsl:attribute name="date">2003-09-23</xsl:attribute> <xsl:attribute name="doc:style" namespace="http://www.example.com/documents">classic</xsl:attribute> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet>
xalan attribute.xml attributes.xsl
< and &.
XML comments are formed like this:<!-- This element holds the current date & time -->
--
), as this pair
of characters signals the end of a comment. Other than that, you are
free to use any legal XML character in a comment. (Again, to check on
what characters are legal in XML, and where they are legal, see
Sections 2.2 through 2.4 of the XML specification.)comment, as demonstrated in
the comment.xsl stylesheet:<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:comment> comment & msg element </xsl:comment>
<msg><xsl:apply-templates/></msg>
</xsl:template>
</xsl:stylesheet>
&) in the stylesheet.processing-instruction element. This element
is formed like this:<xsl:processing-instruction name="xml-stylesheet">href="new.css" type="text/css"</xsl:processing-instruction>
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.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}
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.<?xml version="1.0"?> <message>You can add processing instructions to a document with the <courier> processing-instruction</courier> element.</message>
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 <?xml version="1.0"?> <message>You can add processing instructions to a document with the <courier> processing-instruction</courier> element.</message>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:attribute-set name="atts"> <xsl:attribute name="noteworthy">true</xsl:attribute> <xsl:attribute name="priority">medium</xsl:attribute> </xsl:attribute-set> <xsl:template match="/"> <xsl:processing-instruction name="xml-stylesheet">href="final.css" type="text/css" </xsl:processing-instruction> <xsl:comment> final.xml as processed with final.xsl </xsl:comment> <doc> <heading>Final Summary</heading> <paragraph>Following is a summary of how you can build documents with XSLT: </paragraph> <paragraph>You can add text either literally or with the <code>text</code> element. </paragraph> <paragraph>You can use literal result elements in stylesheets.</paragraph> <xsl:element name="paragraph">You can use <xsl:element name="code">element </xsl:element> elements in stylesheets.</xsl:element> <xsl:comment> you can add a line break & some spaces with the text element </xsl:comment> <xsl:text> </xsl:text> <xsl:element name="paragraph"><xsl:attribute name="noteworthy">true</xsl:attribute> You can add attributes to elements with the <xsl:element name="code">attribute </xsl:element> element.</xsl:element> <xsl:element name="paragraph" use-attribute-sets="atts">You can even add sets of attributes to elements with the <xsl:element name="code">attribute-set</ xsl:element> top-level element.</xsl:element> <paragraph>You can add comments with the <code>comment</code> element.</paragraph> <xsl:element name="paragraph"><xsl:text>And last but not least: </xsl:text> <xsl:apply-templates select="message"/></xsl:element> </doc> </xsl:template> <xsl:template match="courier"> <xsl:element name="code"><xsl:apply-templates/></xsl:element> </xsl:template> </xsl:stylesheet>
text,
element, attribute,
attribute-set, comment, and
processing-instruction. You also learned about
XHTML's relationship to HTML, and came to grips with
some of the fundamentals of how template rules are evaluated and
processed (more to come on that topic). You are now ready to explore
ways that you can finely tune a result tree with the
output element. You'll find out
how in Chapter 3.output. You have seen the
output
element in previous examples, but I have only discussed 2 of
output's 10 attributes so far.
I'll talk about each of
output's attributes in this
chapter.output element. There are models in which the XSLT
processor has no control over the final serialization of the output
because the output values are overridden. You will
see an example of this type of model when you use the Moxie
processor, discussed in Chapter 17.output
element has a method attribute. This attribute
indicates explicitly the kind of output you want the XSLT processor
to produce, namely, XML, HTML, or plain text. These three
amigos—the attribute values output
element has a method attribute. This attribute
indicates explicitly the kind of output you want the XSLT processor
to produce, namely, XML, HTML, or plain text. These three
amigos—the attribute values xml,
html, and text—should
always be lowercase when used as values for
method. (Again, XSLT 2.0 will also support the
xhtml output method.)method, you get a default output method depending
on what a stylesheet produces. The default output method for XSLT is
XML unless the document element in the result is
html. In such a case, the default output method is
HTML. The tag name html can be in uppercase,
lowercase, or mixed case, but it must not have a namespace URI
associated with it (no xmlns attribute).<name> <last>Churchill</last> <first>Winston</first> </name>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="name"> <html> <body> <p><xsl:apply-templates select="last"/></p> <p><xsl:apply-templates select="first"/></p> </body> </html> </xsl:template> </xsl:stylesheet>
output element in
default-html.xsl to tell the processor
explicitly what the output method is. Apply this stylesheet to
name.xml with Xalan:xalan -m name.xml default-html.xsl
<html> <head> </head> <body> <p>Churchill</p> <p>Winston</p> </body> </html>
-m command-line option suppresses the
META tag that
Xalan would normally produce. The
result does not have an XML declaration because Xalan evaluated the
result as HTML, as it should. The result is also indented (line
breaks at start tags, but zero space) because if the output method is
HTML, a default value of output element helps you to control a number
of features relating XML output, including the XML declaration,
document type declarations, and CDATA sections, all of which are
discussed in the sections that follow.output element. With
output, you can keep XML declarations from being
written to output, change version information, control the encoding
declaration, and monitor the stand- alone declaration.
I'll cover all of these features step-by-step in the
sections that follow.output's
omit-xml-declaration attribute a value of
yes; by default, the value is
no when the attribute is not present. The
omit-xml-declaration attribute is used in
omit.xsl
:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="name">
<name>
<family><xsl:apply-templates select="last"/></family>
<given><xsl:apply-templates select="first"/></given>
</name>
</xsl:template>
</xsl:stylesheet><?xml version="1.0"?> <!-- names of persons acknowledged as current and past members of the W3C XML Working Group at the time of the publication of the first edition of the XML specification on 1998-02-10 --> <names> <name> <last>Angerstein</last> <first>Paula</first> </name> <name> <last>Bosak</last> <first>Jon</first> </name> <name> <last>Bray</last> <first>Tim</first> </name> <name> <last>Clark</last> <first>James</first> </name> <name> <last>Connolly</last> <first>Dan</first> </name> <name> <last>DeRose</last> <first>Steve</first> </name> <name> <last>Hollander</last> <first>Dave</first> </name> <name> <last>Kimber</last> <first>Eliot</first> </name> <name> <last>Magliery</last> <first>Tom</first> </name> <name> <last>Maler</last> <first>Eve</first> </name> <name> <last>Maloney</last> <first>Murray</first> </name> <name> <last>Murata</last> <first>Makoto</first> </name> <name> <last>Nava</last> <first>Joel</first> </name> <name> <last>O'Connell</last> <first>Conleth</first> </name> <name> <last>Paoli</last> <first>Jean</first> </name> <name> <last>Sharpe</last> <first>Peter</first> </name> <name> <last>Sperberg-McQueen</last> <first>C. M.</first> </name> <name> <last>Tigue</last> <first>John</first> </name> </names>
last and
first fit Western-oriented names, which admittedly
is a problem when you are dealing with international names. In other
examples in this chapter, text
output method lets an XSLT processor
know that you intend to output plain text to the result. You have
already seen simple examples that do this previously in the book.
This example shows you how to output programming language text using
the text method. If you are not a programmer, this
section may be a little tough to follow. You can skip it if
programming makes you queasy or if you aren't
interested in .NET, although the same approach can be used to
generate Java, VisualBasic, COBOL, or the language of your choice.<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="name"> using System; using System.Xml; class Name { static void Main( ) { XmlTextWriter w = new XmlTextWriter(Console.Out); w.Formatting = Formatting.Indented; w.Indentation = 1; w.WriteStartDocument( ); w.WriteStartElement("<xsl:value-of select="name( )"/>"); w.WriteAttributeString("title", "Mr."); w.WriteElementString("family", "<xsl:value-of select="last"/>"); w.WriteElementString("given", "<xsl:value-of select="first"/>"); w.WriteEndElement( ); w.Close( ); } } </xsl:template> </xsl:stylesheet>
value-of instruction elements
to grab string values from the source tree. The first occurrence of
value-of uses the XPath function name(
) to grab the name of the element that the template
matches. The template actually matches not just the name of an
element node, but a node-set, that is, the set
of nodes including the element name and its
children. The value-of element, however, returns
only the string value of the first node of this node-set. The next
two occurrences of value-of capture the text node
children of the last and first elements in the source tree,
respectively. (You'll learn more about nodes and
node-sets in Chapter 4.)xml, html, and
text output methods. You can also use a QName for
a value of the method attribute. But
there's a catch: if you use a QName, it must be
supported as an extension by the XSLT processor that you use with it.
(This mechanism allows you to invoke a user-written serializer, such
as with a SAX ContentHandler.) This can be useful if you want to
produce non-XML formats as your output.method
attribute by way of extension. One of them is
jd:empty.method must be a QName, not an
NCName. Any value other than xml,
html, or text is considered an
extension and must be qualified with a namespace.jd:empty output method, when used together
with the jd.xslt processor, produces a result tree but
doesn't serialize it. This is useful when you are
interested only in measuring the performance of the processor with a
given stylesheet. The stylesheet empty.xsl uses
output with a method of
jd:empty:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="jd:empty" xmlns:jd="http://www.aztecrider.com/xslt"/>
<xsl:template match="name">
<name>
<family><xsl:apply-templates select="last"/></family>
<given><xsl:apply-templates select="first"/></given>
</name>
</xsl:template>
</xsl:stylesheet>
jd:empty is associated with the
namespace name http://www.aztecrider.com/xslt. You can
process empty.xsl against the document
name.xml with jd.xslt to see what happens. (For
details of how to download, install, and run jd.xslt, see the
appendix.) To run it, enter the following at a command or shell
prompt using the -verbose switch:java -jar jdxslt.jar -verbose name.xml empty.xsl
jd.xslt processor version 1.4.0 java vm = Sun Microsystems Inc., 1.4.1_01 parser = org.apache.crimson.parser.XMLReaderImpl modelbuilder factory = jd.xml.xpath.model.build.ModelBuilderFactory read stylesheet = file:C:/LearningXSLT/examples/ch03/empty.xsl prepare stylesheet = 180 ms read xml input = 10 ms (using normal tree model) transform input = 10 ms max memory usage = 1.937 MB
media-type
. This attribute
allows you to set the media type for the result. Media types are also
sometimes called MIME types (MIME is short for
Multipurpose Internet Mail Extensions), but since the types apply to
more than just email, the term media
type is more encompassing.application/xml may be specified in an
output element like this:<xsl:output output="xml" media-type="application/xml"/>
Content-Type field of an HTTP header. This was
probably the intent of this obscure attribute.|
Method
|
Default media type
|
|---|---|
|
XML
|
text/xml |
|
HTML
|
text/html |
|
Text
|
text/plain |
http://www.w3.org/TR/xpath.