2.2 Literal Result Elements

A literal result element is any XML element that is represented literally in a template, is not in the XSLT namespace, and is written literally onto the result tree when processed. Such elements must be well-formed within the stylesheet, according to the rules in XML 1.0.

The example stylesheet tedious.xsl, which produces XML output, contains an instance of the 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>

Here is literal.xml:

<?xml version="1.0"?>    <message>You can use literal result elements in stylesheets.</message>

If you apply this stylesheet to literal.xml:

xalan literal.xml tedious.xsl

you will get this output:

<?xml version="1.0" encoding="UTF-8"?> <msg xmlns="http://www.wyeast.net/msg">You can use literal result elements in stylesheets.</msg>

Because this stylesheet uses the XML output method, XML declaration was written to the result tree. The literal result element, along with its namespace declaration, was also written.

2.2.1 Adding a Namespace Prefix

In tedious.xsl, the 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.)

Ok, ok. This is getting a little confusing. If you had to add a namespace declaration to every literal element and then to following XSLT elements, that would add up to a lot of error-prone typing. So, it's time to start using a prefix with the XSLT namespace.

The conventional prefix for XSLT is xsl, but you can choose another one if you like. Here is a rewrite of tedious.xsl that uses the xsl prefix with the XSLT namespace declaration. It's called notsotedious.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/>    <xsl:template match="/">  <msg>   <xsl:apply-templates/>  </msg> </xsl:template>    </xsl:stylesheet>

This version of the stylesheet drops the namespace declaration for msg because it's no longer required to have one. Likewise, you don't have to redeclare the XSLT namespace for apply-templates either.

If you apply notsotedious.xsl to literal.xml:

xalan literal.xml notsotedious.xsl

it produces:

<?xml version="1.0" encoding="UTF-8"?> <msg>You can use literal result elements in stylesheets.</msg>

When you use a prefix with a namespace declaration on the XSLT document element stylesheet, as in notsotedious.xsl, you don't have to repeat the declaration on any other element in the document that uses the same prefix you only have to declare it once. Throughout the rest of the book, I'll usually use an xsl prefix in a stylesheet.

QNames and NCNames

An element or attribute name that is qualified by a namespace is called a qualified name, or QName for short. In normal XSLT, two examples of QNames are stylesheet or xsl:stylesheet. Both are (or should be) qualified by the namespace name http://www.w3.org/1999/XSL/Transform. A QName may have a prefix, such as xsl, which is separated by a colon from its local part or local name, as in stylesheet. A QName may also consist only of a local part. If a local part is qualified with a namespace, and there is no prefix, it should be qualified by a default namespace declaration. You'll learn about default declarations in Section 2.2.3.2, later in this chapter.

An element or attribute name that is not qualified with a namespace is unofficially called a non-colonized name, or, officially, an NCName. As spelled out in XML 1.0, a colon was allowed in XML names, even as the first character of a name. For example, names like doc:type or even :type were and still are legal, even if they are not qualified with a namespace. But there was little notion of namespaces in early 1998 when XML 1.0 came out, so if a colon occurred in a name, it was considered a legal name character. Nevertheless, XML names with colons that are not namespace-qualified are undefined in XSLT and don't work. Avoid them and be happier!

The XML namespaces specification created the term NCName. It is an XML name minus the colon, and it makes way for the special treatment of the colon in XML namespace-aware processing. If an XML processor is not up to date and does not support namespaces (most do so now), colons will not be treated specially in names. You can read more about QNames and NCNames in Sections 3 and 4 of the XML namespaces specification.

If namespaces sound somewhat confusing to you, you are in good company. Namespaces in XML are here to stay, but they are admittedly befuddling and difficult to explain.


Here is another simple example of a literal result element, expanded with a few more details. The template in the stylesheet literal.xsl contains a literal result element paragraph:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/">  <paragraph><xsl:apply-templates/></paragraph> </xsl:template>    </xsl:stylesheet>

The output element specifies the xml output method, instead of the text method, and turns indentation on (indent="yes"). When the xml output method is set, XSLT processors will write an XML declaration on the first line of the result tree (as you saw earlier).

When the output element's indent attribute has a value of yes, the processor will add some indentation to make the output more human-readable. The amount of indentation will vary from processor to processor because the XSLT specification states only that, in regard to indentation, an "XSLT processor may add additional whitespace when outputting the result tree" (see Section 16). The modal may add gives implementers some free rein on how they put indentation into practice. Some implementers, in fact, don't implement indentation at all, although they are allowed to do so.

Apply literal.xsl to literal.xml with the command:

xalan literal.xml literal.xsl

and you will see the following results:

<?xml version="1.0" encoding="UTF-8"?> <paragraph>You can use literal result elements in stylesheets.</paragraph>

Using the stylesheet, the processor replaced the document element message from the source tree with the literal result element paragraph in the result tree. In its output, Xalan also included an encoding declaration in the XML declaration.

The encoding declaration takes the form of an attribute specification (encoding="UTF-8"). The encoding declaration provides an encoding name, such as UTF-8, that indicates the intended character encoding for the document. The encoding name is not case sensitive; for example, both UTF-8 or utf-8 work fine. Xalan uses uppercase when outputting an encoding declaration, while Saxon uses lowercase. You'll learn more about encoding declarations and character encoding in Chapter 3.

2.2.2 Literal Result Elements for HTML

Taking this a few steps further, the stylesheet html.xsl produces HTML output using literal result elements:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/">  <html>   <head>    <title>HTML Output</title>   </head>   <body>    <p><xsl:apply-templates/></p>   </body>  </html> </xsl:template>    </xsl:stylesheet>

The output method is now html, so no XML declaration will be written to the output. Indentation is the default for the html method, though it is shown explicitly in the output element (indent="yes"). The tags for the resulting document are probably familiar to you, and they are near the minimum necessary for an HTML document to display anything. For reference, you can find the current W3C specification for HTML Version 4.01 at http://www.w3.org/TR/html401/.

Now, use Xalan to apply the stylesheet to literal.xml, and save the result in a file:

xalan -o literal.html literal.xml html.xsl

This transformation will construct the following result tree and save it to the file literal.html:

<html> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HTML Output</title> </head> <body> <p>You can use literal result elements in stylesheets.</p> </body> </html>

By default, Xalan's indentation depth is zero, but as a general rule, start tags begin on new lines. Saxon's default indentation depth is three spaces, with start tags on new lines as well.

2.2.2.1 The META tag

Xalan automatically adds a META tag to the head element. This META tag is an apparent attempt to get Hypertext Transfer Protocol (HTTP) to bind or override the value of the META tag's content attribute (text/html; charset=UTF-8) to the Content-Type field of its response header. In other words, if you request this document with HTTP, such as with a web browser, the server that hosts the document will issue an HTTP response header, and one of the fields or lines in that header should be labeled Content-Type, as shown here:

HTTP/1.1 200 OK Date: Thu, 01 Jan 2003 00:00:01 GMT Server: Apache/1.3.27 Last-Modified: Thu, 31 Dec 2002 23:59:59 GMT ETag: "8b6172-c7-3e3878a8" Accept-Ranges: bytes Content-Length: 199 Connection: close Content-Type: text/html; charset=UTF-8

I cannot guarantee that the content of the META tag will wind up in the Content-Type header field, though that's what it logically seems to be trying to do. You can tell Xalan to not output the META tag by using the -m option on the command line. For example, the command:

xalan -m literal.xml html.xsl

will produce HTML output without the META tag:

<html> <head> <title>HTML Output</title> </head> <body> <p>You can use literal result elements in stylesheets.</p> </body> </html>

The apply-templates element in html.xsl brought the content of message from literal.xml into the content of the p element in the resulting HTML. If you open the document literal.html in the Mozilla Firebird web browser, it should look like Figure 2-1. (Firebird is a leaner and faster branch of Mozilla.)

Figure 2-1. Displaying literal.html in Mozilla Firebird
figs/lxsl_0201.gif

2.2.3 XHTML Literal Result Elements

The XML document doc.xml uses a minimal set of elements to express a rather simple document structure:

<?xml version="1.0"?>    <doc styletype="text/css">    <css>  h1 {font-family: sans-serif; font-size: 24pt}  p {font-size: 16pt} </css>    <title>Using Literal Result Elements</title>    <heading>What Is a Literal Result Element?</heading>    <paragraph>You can use literal result elements in stylesheets. A literal result element is any non-XSLT element, including any attributes, that can be written literally in a template, and that will be pushed literally onto the result tree when processed.</paragraph>    </doc>

The document element doc in doc.xml is the container, so to speak, for the whole document. This element has a single attribute, styletype, that ostensibly provides a content type for a CSS stylesheet. The css element holds a few CSS rules, which don't apply to any elements in doc.xml, but they'll come in handy later when you move to XHTML. The title, heading, and paragraph elements that follow have fairly obvious roles. Now look at the stylesheet doc.xsl, which you can use to transform doc.xml into XHTML:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/>     <xsl:template match="doc">   <html xmlns="http://www.w3.org/1999/xhtml">   <head>    <title><xsl:apply-templates select="title"/></title>    <style type="{@styletype}">     <xsl:apply-templates select="css"/>    </style>   </head>   <body>    <h1><xsl:apply-templates select="heading"/></h1>    <p><xsl:apply-templates select="paragraph"/></p>   </body>   </html>  </xsl:template>    </xsl:stylesheet>

The output method is XML again, because XHTML is really a vocabulary of XML. (XSLT 1.0 does not support a specific xhtml output method, but XSLT 2.0 does.) With indentation on (yes), the output will be more readable. The literal result element for html has a namespace declaration for XHTML 1.0.

As a vocabulary of XML, XHTML 1.0 has requirements that go beyond those of HTML, an SGML vocabulary. For example, all XHTML tags must be in lowercase, and must be closed properly, either with an end tag or in the form of an empty element tag. Attribute values must be enclosed in matching double or single quotes. In other words, because XHTML is XML, it must be well-formed.

Looking back at doc.xsl, what about the braces in the value of style's type attribute? That's called an attribute value template in XSLT.

2.2.3.1 Attribute value templates

An attribute value template provides a way to bring computed data into attribute values. Think for a moment why such a syntax is needed. You know that the markup character < is not allowed in attribute values. That's a rule from the XML 1.0 specification. So, you couldn't use something like a value-of element in an attribute value. And you can't use entity references such as &lt; as you normally would in an attribute value of a literal result element because an XSLT processor will interpret these references as literal text. These are a few reasons why XSLT provides this special syntax.

The following line in doc.xsl contains an attribute value template:

<style type="{@styletype}">

Because it is processing the doc element, and eventually all its children, the processor uncovers the attribute styletype on doc. In the stylesheet, the braces ({ }) enclose the attribute value template. Everything in the braces is computed rather than copied through. The at sign (@) syntax comes from XPath and indicates that the following item in the location path is an attribute you're looking for in the context node. The XSLT processor then picks up the value of the styletype attribute from the source tree and places it at this same spot in the output, giving you:

<style type="text/css">

in the result tree. (You can read more about attribute value templates in Section 7.6.2 of the XSLT specification.)

Now process this transformation and save the result in the file:

xalan -o doc.html doc.xml doc.xsl

The resulting file doc.html will look like this:

<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Using Literal Result Elements</title> <style type="text/css">  h1 {font-family: sans-serif; font-size: 24pt}  p {font-size: 16pt} </style> </head> <body> <h1>What Is a Literal Result Element?</h1> <p>You can use literal result elements in stylesheets. A literal result element is any non-XSLT element, including any attributes, that can be written literally in a template, and that will be pushed literally onto the result tree when processed.</p> </body> </html>

Figure 2-2 shows what doc.html looks like in Netscape 7.1. Actually, you can either open doc.html or doc-pi.xml and you'll be looking at essentially the same document.

Figure 2-2. Displaying doc.html in Netscape 7.1
figs/lxsl_0202.gif
2.2.3.2 Applying namespaces

Before moving on, I want to call your attention to the namespace declaration in doc.html. This, which originated in a literal result element in doc.xsl, is considered a default namespace declaration:

<html xmlns="http://www.w3.org/1999/xhtml">

The URI http://www.w3.org/1999/xhtml, by the way, is the official namespace for XHTML 1.0. No prefix appears on any element or attribute in the resulting document. A default namespace declaration applies to the element on which it was declared, and also to any child elements that follow that element, but default declarations never apply to attributes.

There is little to no risk of having a name conflict between attribute names. For example, take two elements that both can have an attribute with the same name. With or without a namespace declaration, there won't be a name conflict because an attribute's domain, so to speak, is limited to the element that owns it. You can only use an attribute once on a given element attribute names must be unique within the element. If, however, two attributes have the same name, and one is qualified with a namespace prefix (a QName with a prefix), those names won't conflict. For example, in the following fragment, the invoice start tag has two attributes:

<invoice order="293-7756-11" new:order="2003-08-31-4556">

There are two order attributes, but because one is qualified with a prefix, the names won't collide, and you don't break the rule of using an attribute more than once. For more details, see Section 5.2 of the XML namespaces specification.



Learning XSLT
Learning XSLT
ISBN: 0596003277
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net