Day 5
Inserting Text and Elements

Yesterday you learned all about using templates, that they are key to Extensible Stylesheet Language Transformations (XSLT), and that they can either be explicitly called or matched by the processor. When templates are being matched, multiple templates may match the current node. You have learned how to control which template is actually matched when this situation occurs, enabling you to control the output that is actually generated.

In today’s lesson, you will learn more details about inserting text and elements into the resulting output. You will learn how to do the following:

• Insert text with special characters

• Insert elements and attributes into the XML result

• Insert elements and attributes with a generated name

• Copy elements from the source XML into the result

Inserting Text

As you learned in previous lessons, inserting text is easy. In a template, you specify the text you want, and it is then inserted each time the template is processed. When you want to insert the value from an element or attribute in the source XML document into the result, you can use the xsl:value-of element to specify which value you want to insert.

You may be wondering why this section is devoted entirely to inserting text if the procedure is so simple. Well, I included this discussion because the text inserted and the values in elements and attributes have been plain in the previous samples. I specifically avoided special characters that might cause problems in those samples. Because you will most certainly encounter situations in which you need to work with characters such as é, ë, ê, and so on, a closer look is in order.

Text with Special Characters

NEW TERM

Unless you specify otherwise, a stylesheet will generate XML. In XML, and thus in XSLT, some characters need to be treated differently. They are called special characters. Generally, special characters are a problem when a document is processed—either because of the encoding used or because these characters have a special function within the document (for example, tag delimiters).

NEW TERM

To use special characters in a value (in text), you need to use output escaping. Characters are said to be output escaped when they are replaced by a series of characters that represent them. You use them if you want to insert those characters without their performing the function they have within the document, or when those characters are not supported by the encoding used and hence need to be represented in some other way.

Output escaping is common in HTML documents because these documents are based on ASCII encoding, which supports only 256 characters. Many characters used in different languages are not among those 256 characters, so to represent them, you need to use some kind of alternative encoding. Because XML can be based on many encoding schemes, including Unicode, XML by default requires only minimal output escaping. In Unicode, most common international characters can be inserted as is, so you don’t need to replace characters such as é, ë, and ê with other characters to represent them. If your policy is to always output escape these kinds of characters, you are certainly allowed to do so.

NEW TERM

In XML, output escaping works on the basis of entities. An entity is a name that represents a character or series of characters. It can be used as a replacement for a special character or as a shortcut to insert a value (for example, a copyright notice).

By default, XML defines only five entities, which replace characters within XML that have a special function. Table 5.1 shows the characters for which entities have been defined in XML.

TABLE 5.1 Default Entities Defined in XML

Image

NEW TERM

Of the entities in Table 5.1, only the first two always must be used. The & entity always denotes the start of an entity that is being inserted, including the one replacing it. The < entity always denotes the start of an XML tag, so it can never be used in regular text. You must use the other three entities only when the processor may interpret a character’s presence as performing the function it has in XML rather than being part of the text. If, at that point, you want to insert that character in the text, you need to insert the entity. When the actual character’s presence cannot be misinterpreted, you can insert that character as is, as shown in Listing 5.1.

LISTING 5.1 Sample with Different Forms of Output Escaping

  1:  <?xml version=″“1.0”" encoding="UTF-8"?>
  2:  <escaping>
  3:    <amp>&amp;</amp>
  4:     <lt>&lt;</lt>
  5:    <quot>&quot;</quot>
  6:    <quot attr="&quot;">"</quot>
  7:    <apos attr='&apos;'>&apos;</apos>
  8:    <apos>'</apos>
  9:     <gt>&gt;</gt>
  10:   <gt attr="&gt;">></gt>
  11:   <other>&#100;</other>
  12:   <other>&#x00E7;</other>

  13: </escaping>

Note

You can download the sample listings in this lesson from the publisher’s Web site.

ANALYSIS

Listing 5.1 contains quite a mix of escaped characters. Where possible, the characters are inserted as is. For the values of the elements on lines 3–4, using entities instead of the actual characters is mandatory. Not doing so would result in an error. For the quote character on line 6, you can use either the quote character within an element value or use the corresponding entity. Because the element’s attribute on line 6 uses the quote character to delimit the value, the quote entity is needed to insert the actual character in the value. For the apostrophe character, this use is similar, as shown on lines 7–8. The > character also doesn’t need to be output escaped, except when it is within an attribute value. Otherwise, it could be mistaken for the element tag’s ending. The characters on lines 11–13 don’t need to be escaped, but you can choose to do so.

If you look at the code for Listing 5.1 in an XML-enabled viewer, such as Internet Explorer 5.0 or higher, you can see that the output-escaped characters actually appear as the characters themselves, as shown in Figure 5.1.

FIGURE 5.1 Screenshot of Listing 5.1 viewed in Internet Explorer 5.

Image

HTML Entities

If you’re familiar with HTML, you may have noticed that entities such as &nbsp; (non-breaking space) are no longer defined. Actually, inserting such an entity by itself results in an error. For &nbsp; you should use &#160; instead. The five built-in entities in XML will be properly processed by all parsers on all platforms. You can extend entities either by using numerical codes or by creating your own with a DTD.

Note

You can find a complete list of the entities defined in HTML 4.0 at <http://www.w3.org/TR/REC-html40/sgml/entities.html. For each entity listed, the equivalent number code also is given. These number codes, which correspond to the number codes in Unicode, can be used in XML, as can all other Unicode number codes.

Another option is to create a Document Type Definition (DTD) that defines these entities and use that DTD when you’re creating documents and stylesheets in which you want to use these entities.

Note

Defining entities with DTDs is beyond the scope of this book. Using DTDs is discussed further on Day 15, “Working with Namespaces.”

Special Characters in XSLT

The bottom line from the preceding discussion is that XML can contain special characters, but some characters have to be output escaped because of their function in XML. The question that now arises is “How does XSLT deal with these characters?” To answer this question, look at Listing 5.2.

Listing 5.2 Stylesheet with Special Characters

    1:  <?xml version=″“1.0”" encoding="UTF-8"?>
    2:  <xsl:stylesheet version=″“1.0”"
    3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    4:
    5:    <xsl:template match="/">
    6:       <xsl:apply-templates />
    7:    </xsl:template>
    8:
    9:    <xsl:template match="apos">
    10:     &quot;<xsl:value-of select="." />&quot;
    11:   </xsl:template>
    12:
    13:    <xsl:template match="gt">
    14:      >&quot;<xsl:value-of select="." />"&lt;
    15:   </xsl:template>
    16:
    17:   <xsl:template match="amp|lt|quot|other">
    18:     &apos;<xsl:value-of select="." />'
    19:   </xsl:template>
    20: </xsl:stylesheet>

ANALYSIS

Listing 5.2 contains several templates that could be used with Listing 5.1. In the templates, some characters are output escaped, but others aren’t just to show you that you can mix up the characters when it doesn’t matter whether you use output escaping. In the template starting on line 13, one of the quote characters is output escaped; the other is not. Also, the > that starts the template’s value is not output escaped. It can be used this way because it is in a position where the parser does not expect a > character to perform a function (ending a tag). The < character ending the value needs to be output escaped, however, if you don’t want the parser to mistake it for the start of a tag.

Listing 5.3 shows the result of applying Listing 5.2 to Listing 5.1.

OUTPUT

LISTING 5.3 Result from Applying Listing 5.3 to Listing 5.1

1:  <?xml version=″“1.0”" encoding="utf-8"?>
2:
3:      '&amp;'
4:
5:
6:      '&lt;'
7:
8:
9:       '"'
10:
11:
12:      '"'
13:
14:
15:      "'"
16:
17:
18:      "'"
19:
20:
21:      &gt;"&gt;"&lt;
22:
23:
24:      &gt;"&gt;"&lt;
25:
26:
27:      'd'
28:
29:
30:      'ç'
31: 

ANALYSIS

In Listing 5.3, most output-escaped characters are replaced by their actual characters. The reason for this conversion has already been hinted at in Figure 5.1. When the parser loads the XML, the characters it can handle without their being output escaped are immediately converted to the characters themselves. In effect, after the XML is loaded, you cannot tell whether the characters were output escaped. This is why in XSLT you cannot determine whether a character in the source XML was output escaped.

Note

If you apply Listing 5.2 to Listing 5.1 from the command prompt or console, the output looks a little different because the command prompt doesn’t have the means to display some of the characters. If you save the result to a file and view that file in a text editor that supports these characters, the characters are displayed as they should be.

When the output is created, the processor outputs all the characters conforming to the output encoding used (in this case, UTF-8), regardless of the output escaping used in the source XML or stylesheet. If the processor determines that a character does need to be output escaped, it outputs the character by itself, also regardless of the way the character appeared in the input. Refer to line 10 of Listing 5.1 and the output generated from that line with the stylesheet, which appears on line 24 of Listing 5.3. As you can see, the processor automatically converts the > character to its entity.

As long as your XML source and stylesheets are output escaped properly, you don’t need to worry about what the resulting output will look like from an output-escaping point of view. When you’re creating XML output, the processor ensures that the output is encoded and output escaped as it should be. When you create other forms of output, you may have to be more careful, however.

Note

On Day 7, “Controlling the Output,” different output types will be discussed further.

Inserting Elements and Attributes

I have been saying that the samples in this book produce XML output. Strictly speaking, this is true because all the output is preceded by an XML prolog, and all characters conform to XML encoding and output escaping. You may have noticed that none of the results contain tags; they contain only text. The output created therefore is not well-formed XML because well-formed XML documents need to have at least a root element.

Values in the document must exist inside that root element; otherwise, the document is not valid. So, to create valid XML documents, you need to be able to insert elements.

Inserting Elements

Like inserting text, inserting elements is straightforward. You can insert elements anywhere within a template, as long as you use well formed XML (if it isn’t, the stylesheet itself will not be well formed XML). If you want to insert elements with a namespace, that namespace needs to be declared within the stylesheet.

Note

On Day 15, “Working with Namespaces,” inserting elements with a name-space will be discussed thoroughly.

Inserting elements in the output is required if you want the output to be XML or HTML. If you restructure your source document or if you format the source document for display on the Web, this is the case. When you’re transforming elements to HTML, for instance, you may want to insert hyperlinks, text in boldface, and so on.

The best way to show how easily you can insert elements is by example. The first thing you need is an XML document to be transformed. The document used in Listing 5.4 comes from yesterday’s lesson.

LISTING 5.4 XML Sample Document with Car Information

<?xml version=″“1.0”" encoding="UTF-8"?>
<cars>
    <car model="Focus" manufacturer="Ford" year="2000" />
    <car model="Golf" manufacturer="Volkswagen" year="1999" />
    <car model="Camry" manufacturer="Toyota" year="1999" />
    <car model="Civic" manufacturer="Honda" year="2000" />
    <car model="Prizm" manufacturer="Chevrolet"year="2000"/>
</cars>

Now you need a stylesheet to transform Listing 5.4 and add some elements. Listing 5.5 shows such a stylesheet.

LISTING 5.5 Stylesheet That Inserts Elements into the Output

 1:  <?xml version=″“1.0”" encoding="UTF-8"?>
 2:  <xsl:stylesheet version=″“1.0”"
 3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4: 
 5:    <xsl:template match="/">
 6:       <xsl:apply-templates />
 7:    </xsl:template>
 8:
 9:     <xsl:template match="cars">
 10:     <table>
 11:        <xsl:apply-templates />
 12:     </table>
 13:   </xsl:template>
 14:
 15:   <xsl:template match="car">
 16:     <tr>
 17:       <xsl:apply-templates select="@*" />
 18:     </tr>
 19:   </xsl:template>
 20:
 21:    <xsl:template match="@*">
 22:     <td><xsl:value-of select="." /></td>
 23:   </xsl:template>
 24: </xsl:stylesheet>

ANALYSIS

The stylesheet in Listing 5.5 creates an HTML table containing all the information on the cars stored in Listing 5.4. For each car element, a row is created in the table. The cars template starting online 9 creates the start tag of the table element and then uses the xsl:apply-templates element to invoke other templates for each child element of the cars element. When that has been done, the end tag of the table element is inserted onine 12. The car template starting online 15 is invoked several times, for each car element in Listing 5.4. This template inserts a table row starting tag online 16, and the closing tag online 18. In between, it invokes the processor for all its attributes. For each attribute, a table cell is created by the template starting online 21, which also inserts the value of the attribute. When you apply Listing 5.5 to Listing 5.4, you get the result shown in Listing 5.6.

OUTPUT

LISTING 5.6 Result from Applying Listing 5.5 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><table>
    <tr><td>Focus</td><td>Ford</td><td>2000</td></tr>
    <tr><td>Golf</td><td>Volkswagen</td><td>1999</td></tr>
    <tr><td>Camry</td><td>Toyota</td><td>1999</td></tr>
    <tr><td>Civic</td><td>Honda</td><td>2000</td></tr>
   <tr><td>Prizm</td><td>Chevrolet</td><td>2000</td></tr>
</table>

If you open Listing 5.6 as an HTML file in a browser, you get a neat table with cars.

Note

Technically, Listing 5.6 is XML. However, because the entire document conforms to the rules of HTML, you can save it as an HTML file and view it in a Web browser.

ANALYSIS

The stylesheet in Listing 5.5 could also have created non-HTML tags. In that case, Listing 5.6 would look different, but it would have been well-formed XML as well. Nothing restricts you to using only HTML tags. I chose to generate HTML tags to give you a practical example that might occur in the real world. I created the HTML tags in such a way that the result is well-formed XML as well. Therefore, you can load the result into a viewer or parser without generating an error. Some HTML tags are not well-formed XML, such as <br> and <input>. If you want to insert such tags, you need to make them well formed—for instance, <br><br> or <input />. If you don’t, the

stylesheet itself is not well-formed XML, so an error occurs when you try to use it. When these tags are sent to the output as well-formed XML, they may not always appear correctly in a Web browser.

Note

You’ll learn how to create correct HTML output on Day 7, “Controlling the Output.”

Creating a Different XML Structure

Listing 5.4 contains car elements, with the values stored in attributes. Yesterday you saw a listing with the same information, but stored in child elements. You created a stylesheet to generate the same output for both structures. Another option is to restructure one of the documents so that it uses the same structure as the other. The stylesheet in Listing 5.7 does exactly that.

LISTING 5.7 Stylesheet to Restructure Listing 5.4

   1:  <?xml version=″“1.0”" encoding61;"UTF-8"?>
   2:  <xsl:stylesheet version="1.0"
   3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   4:
   5:    <xsl:template match="/">
   6:      <xsl:apply-templates />
   7:    </xsl:template>
   8:
   9:    <xsl:template match="cars">
   10:     <cars>
   11:       <xsl:apply-templates />
   12:     </cars>
   13:   </xsl:template>
   14:
   15:   <xsl:template match="car">
   16:     <car>
   17:       <xsl:apply-templates select="@*" />
   18:     </car>
   19:   </xsl:template>
   20:
   21:   <xsl:template match="@model">
   22:     <model><xsl:value-of select="." /></model>
   23:   </xsl:template>
   24:
   25:   <xsl:template match="@manufacturer">
   26:     <manufacturer><xsl:value-of select="." /></manufacturer>
   27:   </xsl:template>
   28:
   29:   <xsl:template match="@year">
   30:     <year><xsl:value-of select="." /></year>
   31:   </xsl:template>
   32: </xsl:stylesheet>

ANALYSIS

Listing 5.7 isn’t very different from Listing 5.5. The cars template on line 9 inserts a cars element instead of a table element, and the car template on line 15 inserts a car element instead of a tr element. The major difference between Listings 5.7 and 5.5 is the way the car element’s attributes are handled. In Listing 5.5, all attributes are handled by the same template, which inserts a td element and the value of the attribute being processed. In Listing 5.7, each attribute is handled by a different template, to see to it that the newly created elements have the same name as the attribute in the source XML. When you apply Listing 5.7 to Listing 5.4, you get the results shown in Listing 5.8.

OUTPUT

LISTING 5.8 Result from Applying Listing 5.7 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><cars>
    <car><model>Focus</model><manufacturer>Ford</manufacturer>
 Image<year>2000</year></car>
    <car><model>Golf</model><manufacturer>Volkswagen</manufacturer>
  Image<year>1999</year></car>
    <car><model>Camry</model><manufacturer>Toyota</manufacturer>
  Image<year>1999</year></car>
    <car><model>Civic</model><manufacturer>Honda</manufacturer>
  Image<year>2000</year></car>
    <car><model>Prizm</model><manufacturer>Chevrolet</manufacturer>
  Image<year>2000</year></car>
</cars>

ANALYSIS

In Listing 5.8, the result contains all attributes from Listing 5.4 as elements. Although Listing 5.8 isn’t as neatly formatted as Listing 4.14 in yesterday’s lesson, they are syntactically and semantically identical. When the documents are loaded into a parser, the resulting XML document tree is the same for all intents and purposes.

Inserting Elements with a Generated Name

Earlier you learned how to insert elements literally into a stylesheet. This approach makes it easy to insert elements. You also can use another method to insert elements. This method uses xsl:element to insert elements. Using this XSLT element, you could write

xsl:element name=”model”>Focus</xsl:element>

instead of

<model>Focus</model>

Using this method, as shown in Listing 5.9, you could also achieve the result in Listing 5.6.

LISTING 5.9 Stylesheet Using xsl:element

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:
5:    <xsl:template match="/">
6:       <xsl:apply-templates />
7:    </xsl:template>
8:
9:    <xsl:template match="cars">
10:     <xsl:element name="table">
11:       <xsl:apply-templates />
12:      </xsl:element>
13:   </xsl:template>
14:
15:   <xsl:template match="car">
16:      <xsl:element name="tr">
17:       <xsl:apply-templates select="@*" />
18:      </xsl:element>
19:   </xsl:template>
20:
21:    <xsl:template match="@*">
22:      <xsl:element name="td">
23:       <xsl:value-of select="." />
24:      </xsl:element>
25:   </xsl:template>
26: </xsl:stylesheet>

ANALYSIS

Listings 5.5 and 5.9 are nearly identical. In Listing 5.5, the elements are literally inserted; in this listing, the xsl:element element is used on lines 10, 16, and 22 to insert the elements. The result is identical. Writing the elements into the stylesheet literally is a shortcut for the method used in Listing 5.9

You might be wondering why you would use xsl:element instead of inserting the elements literally. In the preceding situation, using xsl:element is indeed unnecessary. The code is easier to create and easier to read when you just insert the elements literally. The situation becomes different when you want to create elements in which the element names can be determined only at runtime. Literal elements have to be determined at design time rather than runtime, so inserting elements literally is not a possibility. You might be able to create templates with very complex match expressions to have more diversity in the elements you create, but the more complex the source XML processed becomes, the harder it becomes to deal with all the possibilities.

To get around the drawback of not being able to create elements dynamically at runtime, you can use xsl:element because the value of the name attribute of xsl:element can be determined at runtime using XPath expressions. This means that you can create elements that have a name given as a value in the source XML. Listing 5.10 shows how this technique works.

LISTING 5.10 Stylesheet Creating Dynamic Elements

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:
5:    <xsl:template match="/">
6:      <xsl:apply-templates />
7:    </xsl:template>
8:
9:    <xsl:template match="cars">
10:     <caryears>
11:       <xsl:apply-templates />
12:     </caryears>
13:   </xsl:template>
14:
15:   <xsl:template match="car">
16:     <xsl:element name="{@model}">
17:       <xsl:value-of select="@year" />
18:     </xsl:element>
19:   </xsl:template>
20: </xsl:stylesheet>

Applying Listing 5.10 to Listing 5.4 yields the result in Listing 5.11.

OUTPUT

LISTING 5.11 Result from Applying Listing 5.10 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><caryears>
    <Focus>2000</Focus>
    <Golf>1999</Golf>
    <Camry>1999</Camry>
    <Civic>2000</Civic>
    <Prizm>2000</Prizm>
</caryears>

ANALYSIS

Listing 5.11 shows a list of car model years. You create the elements with the year value by using the xsl:element tag, as shown on line 16 in Listing 5.10. Line 17 inserts the corresponding year. The result is that each element’s name corresponds to the value of each car’s model attribute in Listing 5.4. Instead of using a literal value for the xsl:element tag’s name attribute, you use an expression. You can see that it is an expression because of the curly braces surrounding the expression @model. Instead of creating elements like <{@model}>, the curly braces and expression are replaced with the value of the expression by the processor.

The expression on line 16 in Listing 5.10 is simple. You can make it more complex, getting a value from an entirely different part of the source XML. Also, you can mix expressions and literal text in the value of the name attribute, as shown in Listing 5.12.

LISTING 5.12 Creating an Element from Literal and Dynamic Values

   1:    <xsl:template match="car">
   2:      <xsl:element name="{@manufacturer}-{@model}">
   3:        <xsl:value-of select="@year" />
   4:      </xsl:element>
   5:    </xsl:template>

ANALYSIS

You can use the template in Listing 5.12 instead of the car template starting on line 15 in Listing 5.10. The value of the name attribute on line 2 in this listing contains two expressions surrounded by curly braces, with some literal text in between. If you apply the complete stylesheet of Listing 5.12 to Listing 5.4, the result is similar to Listing 5.13

OUTPUT

LISTING 5.13 Result from Applying Listing 5.12 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><caryears>
    <Ford-Focus>2000</Ford-Focus>
    <Volkswagen-Golf>1999</Volkswagen-Golf>
    <Toyota-Camry>1999</Toyota-Camry>
    <Honda-Civic>2000</Honda-Civic>
   <Chevrolet-Prizm>2000</Chevrolet-Prizm>
</caryears>

ANALYSIS

In Listing 5.13, the text and expressions comprising the value of the name attribute on line 2 of Listing 5.12 create elements with names that consist of the values of the manufacturer and model attributes, with a hyphen (-) in between. As long as the resulting element name is valid in XML, any combination of expressions and literal values is fine.

Using the Name of an Element or Attribute

In Listing 5.7, each attribute had to be handled by a different template to restructure the document. If you could use the attribute’s name to create an element, that approach would not have been necessary. The XPath function name () comes into play here. This function gives the name of the context node. Listing 5.14 shows it in action.

LISTING 5.14 Stylesheet Using the name () Function

1:  <?xml version="1.0" encoding="UTF-8"?>
2:  <xsl:stylesheet version="1.0"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:
5:    <xsl:template match="/">
6:       <xsl:apply-templates />
7:    </xsl:template>
8:
9:    <xsl:template match="cars">
10:      <cars>
11:       <xsl:apply-templates />
12:     </cars>
13:   </xsl:template>
14:
15:   <xsl:template match="car">
16:     <car>
17:       <xsl:apply-templates select="@*" />
18:      </car>
19:   </xsl:template>
20:
21:    <xsl:template match="@*">
22:     <xsl:element name="{name ()}"><xsl:value-of select="." /></xsl:element>
23:   </xsl:template>
24: </xsl:stylesheet>

ANALYSIS

When Listing 5.14 is applied to Listing 5.4, the result is the same as Listing 5.8. This stylesheet, however, requires a lot less code than the one in Listing 5.7. In Listing 5.14, all the attributes are matched by the template that starts on line 21. Using the name () function, this template creates a new element with the name of the context node on line 22. In each case, this name is the name of the attribute. The value of the attribute becomes the value of the newly created element. The templates in lines 5, 9, and 15 all perform functions discussed earlier.

Using the method from Listing 5.14, you can actually create a stylesheet that works on every XML document that has attributes and convert that document so that it uses only elements. If you apply that same stylesheet to an XML document that has no attributes, the output is the same as the source document. The code to convert attributes is remarkably simple; it’s shown in Listing 5.15.

LISTING 5.15 Stylesheet Converting Attributes to Elements

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:
5:    <xsl:template match="*">
6:       <xsl:element name="{name ()}">
7:        <xsl:apply-templates select="@*" />
8:        <xsl:apply-templates />
9:       </xsl:element>
10:   </xsl:template>
11:
12:   <xsl:template match="@*">
13:      <xsl:element name="{name ()}">
14:        <xsl:value-of select="." />
15:      </xsl:element>
16:   </xsl:template>
17:
18:    <xsl:template match="text ()">
19:      <xsl:value-of select="." />
20:   </xsl:template>
21: </xsl:stylesheet>

ANALYSIS

The template that starts on line 5 in Listing 5.15 will match any element in the document because it uses a wildcard. When it is invoked, it creates an element with the same name as the element for which the template is invoked, the context node. Then xsl:apply-templates invokes the processor for each attribute of that element. The template that starts on line 12 will match all these attributes because the attribute wildcard expression matches any attribute. This template creates an element with the name of the attribute being processed and gives it the value of that same attribute. After all the attributes are processed, control reverts to the template on line 5, which then invokes the processor for all child elements. These elements are either matched by the template itself or by the template starting on line 18, which just writes the value to the output.

As you can see, Listing 5.15 does not contain a template that matches the root element of the source document. Because of the built-in template rule, such a template isn’t necessary.

Inserting Attributes

Inserting attributes isn’t much different from inserting elements. If you insert elements literally, you can add attributes literally as well. Listing 5.16 shows how to do so.

LISTING 5.16 Partial Stylesheet Inserting Literal Attributes

1:     <xsl:template match="cars">
2:      <table border="1" width="500">
3:         <xsl:apply-templates />
4:      </table>
5:     </xsl:template>
6:
7:    <xsl:template match="car">
8:      <tr bgcolor="#dddddd">
9:        <xsl:apply-templates select="@*" />
10:     </tr>
11:    </xsl:template>

ANALYSIS

The templates in Listing 5.16 are replacements for the cars and car templates on lines 9 and 15 in Listing 5.5. On line 2 of Listing 5.16, two attributes are added to the table element that line 1’s template inserts. On line 8, the tr element now has a bgcolor attribute. The result is that each time these templates are invoked, the attributes are inserted along with the elements, as you can see in the result in Listing 5.17.

OUTPUT

LISTING 5.17 Result from Applying Listing 5.16 to Listing 5.4

<?xml version="1.0" encoding="utf-8"?><table border="1" width="500">
    <tr bgcolor="#dddddd"><td>Focus</td><td>Ford</td><td>2000</td></tr>
    <tr bgcolor="#dddddd"><td>Golf</td><td>Volkswagen</td><td>1999</td></tr>
    <tr bgcolor="#dddddd"><td>Camry</td><td>Toyota</td><td>1999</td></tr>
    <tr bgcolor="#dddddd"><td>Civic</td><td>Honda</td><td>2000</td></tr>
    <tr bgcolor="#dddddd"><td>Prizm</td><td>Chevrolet</td><td>2000</td></tr>
</table>

Figure 5.2 shows what Listing 5.17 looks like when you save it as an HTML file and view it in Internet Explorer 5.

FIGURE 5.2 Screenshot of Listing 5.17 viewed in Internet Explorer 5.

Image

Inserting Attributes with a Generated Name

Earlier you learned that you can insert elements with a name generated with an expression. You can do the same with attributes by using xsl:attribute. This element’s name attribute gives the created attribute its name. Just as with xsl:element, this can be literal text, an expression, or a mix of literal text and expressions. Listing 5.18 shows an example with literal text; this example is equivalent to Listing 5.16.

LISTING 5.18 Partial Stylesheet Inserting Literal Attributes

1:     <xsl:template match="cars">
2:      <table>
3:        <xsl:attribute name="border">1</xsl:attribute>
4:        <xsl:attribute name="width">500</xsl:attribute>
5:         <xsl:apply-templates />
6:      </table>
7:     </xsl:template>
8:
9:    <xsl:template match="car">
10:     <tr>
11:       <xsl:attribute name="bgcolor">#dddddd</xsl:attribute>
12:       <xsl:apply-templates select="@*" />
13:     </tr>
14:    </xsl:template>

ANALYSIS

In Listing 5.18, the attributes that were inserted literally in Listing 5.16 have been replaced by xsl:attribute elements on lines 3, 4, and 11. The value of the name attribute of the xsl:attribute element is the name used literally in Listing 5.16. The value of the created attribute is given in between the tags of the xsl:attribute element. The result of Listing 5.18 applied to Listing 5.4 would be identical to Listing 5.17 because Listings 5.16 and 5.18 are the same as far as the processor is concerned.

Earlier you looked at some samples that converted Listing 5.4 into an XML document with only elements, as shown in Listing 5.8. With the xsl:attribute element, you also can perform this process in reverse, converting Listing 5.8 into Listing 5.4. Listing 5.19 shows a stylesheet that does this.

Note

You should realize by now that there is nearly always more than one way to get the same result. Throughout this book, the samples are used to explain a specific function, but they may not show the most efficient way to perform a task.

LISTING 5.19 Stylesheet Converting Listing 5.8 into Listing 5.4

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:
5:     <xsl:template match="/">
6:      <xsl:apply-templates />
7:    </xsl:template>
8:
9:    <xsl:template match="cars">
10:      <cars>
11:       <xsl:apply-templates />
11:     </cars>
12:   </xsl:template>
13:
14:   <xsl:template match="car">
15:     <car>
16:       <xsl:apply-templates />
17:      </car>
18:   </xsl:template>
19:
20:    <xsl:template match="*">
21:     <xsl:attribute name="{name ()}">
22:       <xsl:value-of select="." />
23:     </xsl:attribute>
24:   </xsl:template>
25: </xsl:stylesheet>

ANALYSIS

The template that actually converts attributes to elements starts on line 20. It matches any element, but the cars and car elements are overridden by the templates on lines 9 and 14, respectively. The match expression for the template on line 20 could also have been model|manufacturer|year, but then any other child elements of the car element would not be converted, as well as any child elements with different names elsewhere in the document tree. The template creates a new attribute each time it is invoked, with the name and value of the context element.

As you can see from Listing 5.19, the xsl:attribute element doesn’t necessarily have to be a child element of some element being created. It can exist inside a matched or called template. The attribute is then added to the element that is being created from another template—the car element in Listing 5.19. This capability is useful when you need to create multiple related attributes. You can create a named template that inserts the attributes you need, as shown in Listing 5.20.

LISTING 5.20 Partial Stylesheet Inserting Attributes from a Named Template

      1:  <?xml version=″“1.0”" encoding="UTF-8"?>
      2:  <xsl:stylesheet version=″“1.0”"
      3:     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      4:
      5:    <xsl:template match="/">
      6:       <xsl:apply-templates />
      7:     </xsl:template>
      8:
      9:    <xsl:template match="cars">
      10:     <table>
      11:        <xsl:call-template name="tableprop" />
      12:        <xsl:apply-templates />
      13:     </table>
      14:    </xsl:template>
      15:
      16:   <xsl:template match="car">
      17:     <tr>
      18:        <xsl:call-template name="rowprop" />
      19:       <xsl:apply-templates select="@*" />
      20:     </tr>
      21:    </xsl:template>
      22:
      23:    <xsl:template match="@*">
      24:     <td><xsl:value-of select="." /></td>
      25:    </xsl:template>
      26:
      27:   <xsl:template name="tableprop">
      28:     <xsl:attribute name="border">1</xsl:attribute>
      29:      <xsl:attribute name="width">500</xsl:attribute>
      30:    </xsl:template>
      31:
      
      32:      <xsl:template name="rowprop">
      33:        <xsl:attribute name="bgcolor">#dddddd</xsl:attribute>
      34:      </xsl:template>
      35:    </xsl:stylesheet>

ANALYSIS

In Listing 5.20, the two named templates defined on lines 27 and 32 add attributes with properties for HTML table elements and tr (row) elements, hence their names tableprop and rowprop. The former is called from line 11 in the cars template, which inserts a table element and then adds its attributes using the named template. The rowprop template is called from line 18 in the car element, which adds a table row for each car. If you apply Listing 5.20 to Listing 5.4, the result is similar to Listing 5.17.

In Listing 5.20, it doesn’t make much difference if the attributes are inserted using named templates because no other templates call the named templates. So, creating those templates is actually overkill. If multiple templates create elements with identical attributes, using this method would be effective for keeping the attributes in a central place so that they can be edited there if they need to change for all the elements.

Using an Attribute-Set

NEW TERM

If you want to insert multiple literal attributes along with an element, using a named (or matched) template is not the only solution. Within a stylesheet, you can define a set of attributes that can be inserted with an element. This set of attributes is appropriately named an attribute-set and can be defined using the xsl:attribute-set element. You can then insert it by using the use-attribute-set attribute with xsl:element, as shown in Listing 5.21.

LISTING 5.21 Partial Stylesheet Using an Attribute-Set

1:    <xsl:template match="cars">
2:      <xsl:element name="table" use-attribute-sets="tableprop">
3:         <xsl:apply-templates />
4:       </xsl:element>
5:     </xsl:template>
6:
7:    <xsl:template match="car">
8:      <xsl:element name="tr" use-attribute-sets="rowprop">
9:        <xsl:apply-templates select="@*" />
10:      </xsl:element>
11:    </xsl:template>
12:
13:   <xsl:attribute-set name="tableprop">
14:     <xsl:attribute name="border">1</xsl:attribute>
15:     <xsl:attribute name="width">500</xsl:attribute>
16:    </xsl:attribute-set>
17:
18:   <xsl:attribute-set name="rowprop">
19:     <xsl:attribute name="bgcolor">#dddddd</xsl:attribute>
20:    </xsl:attribute-set>

ANALYSIS

When you apply Listing 5.21 to Listing 5.4, the result is like Listing 5.17. As you can see on lines 13–20, two attribute-sets are defined, similar to the named templates in Listing 5.20. Apart from the fact that they define an attribute-set, not a template, the code is similar. How the attributes are inserted differs more, however. On line 2, the tableprop attribute-set is added using the use-attribute-sets attribute. The same goes for the rowprop attribute-set, which is used on line 8 as part of the tr element’s definition.

Using Multiple Attribute-Sets

Attribute-sets are flexible. You can employ several methods to use multiple attribute-sets. The easiest way to use them is to specify multiple attribute-sets as a value of the use-attribute-sets attribute, separated by whitespace. Listing 5.22 shows a sample.

LISTING 5.22 Partial Stylesheet Using Multiple Attribute-Sets

1:    <xsl:template match="cars">
2:      <xsl:element name="table" use-attribute-sets="border width">
3:         <xsl:apply-templates />
4:      </xsl:element>
5:
6:    <xsl:attribute-set name="border">
7:      <xsl:attribute name="border">1</xsl:attribute>
8:     </xsl:attribute-set>
9:
10:   <xsl:attribute-set name="width">
11:     <xsl:attribute name="width">500</xsl:attribute>
12:    </xsl:attribute-set>

ANALYSIS

In Listing 5.22, the tableprop attribute-set from Listing 5.21 is replaced by two attribute-sets, border and width, defined on lines 6 and 10. On line 2, the value of use-attribute-sets now contains both these attribute-sets separated by a space. If you apply this stylesheet to Listing 5.4, you again end up with the results shown in Listing 5.17.

The use-attribute-sets attribute is not limited to use with xsl:element. You can, in fact, create an attribute-set with this attribute, in the process creating an attribute-set that consists of all the attribute-sets listed. This is yet another way to replace the tableprop attribute-set in Listing 5.21, as shown in Listing 5.23.

LISTING 5.23 Attribute-Set in an Attribute-Set

<xsl:attribute-set name="tableprop" use-attribute-sets="border">
    <xsl:attribute name="width">500</xsl:attribute>
</xsl:attribute-set>

<xsl:attribute-set name="border">
    <xsl:attribute name="border">1</xsl:attribute>
</xsl:attribute-set>

ANALYSIS

In Listing 5.23, a tableprop attribute-set is defined; it uses use-attribute-sets to “import” the border attribute-set. An attribute also is added, so the result is basically the same as the tableprop attribute-set in Listing 5.21. It is not surprising that the result of Listing 5.23 is the same as the result from Listing 5.21; this result is shown in Listing 5.17.

NEW TERM

Because you can nest attribute-sets as shown, you can create an elaborate structure of attribute-sets, referring to one another. This capability is useful in situations in which you are creating HTML or XSLFO output with elaborate formatting. You need to be careful, however, that you don’t have a circular reference, which occurs when element A refers to element B, which refers back to element A, thus creating a never-ending loop. Circular references can also occur with more elements.

Copying Elements from the Source Document

In some cases, copying elements from the source document into the result without altering them might be useful. In some of the sample listings earlier in this lesson, I did that by re-creating the element or elements in question. A better way to do that is to use other elements, as described in the following sections.

Copying Only the Context Node

NEW TERM

The xsl:copy element copies the context node from the source to the result. This is called shallow copy, so if you want to copy attributes or child elements, you need to explicitly code for this type of copying. Shallow copy means that only the context node is copied. Any attributes or child nodes the node may have are not copied along with the node.

LISTING 5.24 Stylesheet Employing the xsl:copy Element

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:
5:    <xsl:template match="/">
6:      <xsl:apply-templates />
7:    </xsl:template>
8:
9:    <xsl:template match="cars">
10:     <xsl:copy>
11:       <xsl:apply-templates />
12:     </xsl:copy>
13:   </xsl:template>
14:
15:   <xsl:template match="car">
16:     <xsl:copy />
17:   </xsl:template>
18: </xsl:stylesheet>

ANALYSIS

In Listing 5.24, the xsl:copy element is used in two different ways. The first one has an opening tag on line 10 and a closing tag on line 12. This method effectively creates opening and closing tags for the cars element because it is the context node. The element’s value is determined by the result from the xsl:apply-templates element on line 11. The xsl:copy element on line 16 makes a copy of each car element for which the template is invoked. Be aware that this method creates only an empty car element, without any of the attributes. The big difference between the two different xsl:copy elements in Listing 5.24 is that the value of the element created on line 10 is added specifically. If that isn’t done, which is the case on line 16, then the element is empty. You can clearly see this result in Listing 5.25.

OUTPUT

LISTING 5.25 Result from Applying Listing 5.24 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><cars>
    <car/>
    <car/>
    <car/>
    <car/>
    <car/>
</cars>

The xsl:copy element supports more or less the same functions that xsl:element and xsl:attribute elements offer. You can add child elements and attributes just as you would with the latter two, and you also can use the use-attribute-sets attribute to add attributes. Because I thoroughly discussed these features with xsl:element, I will not discuss them any further. Listing 5.26 shows a sample combining xsl:copy with uses-attribute-sets. Listing 5.27 shows the result from applying Listing 5.26 to Listing 5.4.

LISTING 5.26 Partial Stylesheet Adding Attributes to Copied Elements

1:    <xsl:template match="car">
2:      <xsl:copy use-attribute-sets="year">
3:        <xsl:attribute name="model">Focus</xsl:attribute>
4:      </xsl:copy>
5:    </xsl:template>
6:
7:  <xsl:attribute-set name="year">
8:      <xsl:attribute name="year">1999</xsl:attribute>
9:    </xsl:attribute-set>

ANALYSIS

In Listing 5.26, an attribute-set is defined on line 7. The xsl:copy element on line 2 uses this attribute-set. In addition, line 3 adds another attribute named model.

OUTPUT

LISTING 5.27 Result from Applying Listing 5.26 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><cars>
    <car year="1999" model="Focus"/>
    <car year="1999" model="Focus"/>
    <car year="1999" model="Focus"/>
    <car year="1999" model="Focus"/>
    <car year="1999" model="Focus"/>
</cars>

ANALYSIS

The order in which the attributes appear in Listing 5.27 is deliberate. Any attribute-sets are processed first, in the order in which they are added, and then other attribute definitions are inserted. If an attribute is defined more than once, the last one added is the one sent to the output.

Copying Node-Sets and Tree Fragments

NEW TERM

The xsl:copy element is useful, but it operates only on the context node and copies only the context node, without any of the attributes or child elements. Although you can get around both deficiencies by creating several templates, another element can copy based on an XPath expression and performs deep copy, which is the opposite of shallow copy. In this type of copy, the selected node or node-set and all attributes and descendant elements are copied. In effect, the entire tree fragment under the node or under each node in the selected node-set is copied to the output.

You use the xsl:copy-of element to perform a deep copy. Unlike the xsl:copy element, this element is always empty and has a mandatory select attribute. The select attribute’s value must be a valid XPath expression selecting a node or node-set. Listing 5.28 shows a simple usage of xsl:copy-of.

LISTING 5.28 Partial Stylesheet Copying the Entire Document

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:  
5:    <xsl:template match="/">
6:      <xsl:apply-templates />
7:    </xsl:template>
8:  
9:    <xsl:template match="cars">
10:     <xsl:copy-of select="." />
11:   </xsl:template>
12: </xsl:stylesheet>

ANALYSIS

Line 10 in Listing 5.28 selects the context node and copies it to the output, including all its attributes and descendant elements. Because the context node is the cars element, which is effectively the root element, the entire document is copied to the output. So, if you apply Listing 5.28 to Listing 5.4, the result is the same as Listing 5.4. Because xsl:copy-of is used in the template matching the cars element, only a fragment of the document is copied to the output if the cars element is not the root element of the source document.

If the select expression yields a node-set, for each node in the node-set, the entire tree fragment is copied. This goes for any node-set, even node-sets composed of nodes from different sections in the tree. As such, the node-set should be used with care because you may end up copying many elements you aren’t supposed to. Listing 5.29 shows a replacement template for the template on line 9 of Listing 5.28. The template in Listing 5.29 copies a node-set of two cars.

LISTING 5.29 Partial Stylesheet Copying a Node-Set

<xsl:template match="cars">
    <xsl:copy>

       <xsl:copy-of select="car[1]|car[3]" />
    </xsl:copy>
</xsl:template>

The result from applying Listing 5.28 with the changes from Listing 5.29 to Listing 5.4 is shown in Listing 5.30.

OUTPUT

LISTING 5.30 Result from Applying Listing 5.29 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><cars>
Image<car model="Focus" manufacturer="Ford" year="2000"/>
Image<car model="Camry" manufacturer="Toyota" year="1999"/></cars>

ANALYSIS

As you can see in Listing 5.30, Listing 5.29 copies only the first and third car elements from Listing 5.4. It does, however, copy them with all their attributes.

Using both the xsl:copy and xsl:copy-of elements, you can copy large parts of documents very selectively. The xsl:copy element requires more work than the xsl:copy-of element, but it gives you more control over the output.

Inserting Comments and Processing Instructions

Comments and processing instructions perform a special function in an XML document. Comments are mostly meant for a human reader, telling him or her what is going on in a document. In HTML, comments may also serve to let older browsers ignore a piece of code that they will not understand, such as JavaScript code. Processing instructions are the opposite of comments. They are not meant for the reader; instead, they are instructions for the program reading the XML document. For instance, in XML, a processing instruction is used to attach a stylesheet to an XML document, so if it is viewed by an XML/XSLT-enabled viewer, the viewer will apply the stylesheet automatically. CSS documents are attached to HTML documents the same way.

Inserting Comments

Because comments are not actually part of the XML structure, you can insert them almost anywhere in a document. They can appear at the start or end of a document, beyond the root element of the document, and anywhere a text value is also possible. This does mean that you can’t insert a comment within a start or end tag.

You can insert a comment by using the xsl:comment element. This element has no attributes, and the element value is output as the comment. Now consider this example:

<xsl:comment>This is a comment</xsl:comment>

In XML or HTML output, this code results in the following being inserted into the output at the location the comment was inserted:

<!--This is a comment-->

The <!-- character sequence denotes the start of a comment; the --> sequence, the end, just like start and end tags of an XML element. Because of this, it is not legal to have --in the comment itself; using these characters would result in an error.

Comments are very useful when you’re debugging a stylesheet. For instance, inserting a comment at the start of each template shows you exactly which templates are matched for a source document. Because the comments don’t interfere with the XML, you can use the reulting XML in other applications just as before. Listing 5.31 shows Listing 5.24 with debugging comments.

LISTING 5.31 Listing 5.24 with Comments Added to Templates

1:  <?xml version=″“1.0”" encoding="UTF-8"?>
2:  <xsl:stylesheet version=″“1.0”"
3:     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:  
5:    <xsl:template match="/">
6:      <xsl:comment>template match="/"</xsl:comment>
7:      <xsl:apply-templates />
8:    </xsl:template>
9:  
10:   <xsl:template match="cars">
11:     <xsl:comment>template match="cars"</xsl:comment>
12:     <xsl:copy>
13:       <xsl:apply-templates />
14:     </xsl:copy>
15:   </xsl:template>
16:
17:   <xsl:template match="car">
18:      <xsl:comment>template match="car"</xsl:comment>
19:       <xsl:copy />
20:   </xsl:template>
21: </xsl:stylesheet>
22: </xsl:stylesheet>

ANALYSIS

Lines 6, 11, and 18 of Listing 5.31 insert a comment when the templates on lines 5, 10, and 17 are invoked. This way, you get a complete record of which templates are matched and in what sequence. The result is shown in Listing 5.32.

OUTPUT

LISTING 5.32 Result from Applying Listing 5.32 to Listing 5.4

1: <?xml version=″“1.0”" encoding="utf-8"?><!--template match="/"-->
Image<!--template match="cars"--><cars>
2:    <!--template match="car"--><car/>
3:    <!--template match="car"--><car/>
4:    <!--template match="car"--><car/>
5:    <!--template match="car"--><car/>
6:    <!--template match="car"--><car/>
7: </cars>

ANALYSIS

On line 1 of Listing 5.32, you can see that the root template is matched first and only once. Then the cars template is matched, followed by a match of the car template for each car element in Listing 5.4. The comments show all this clearly, but you can still use this document as if it is the result in Listing 5.25.

A comment doesn’t have to contain literal text. You can use XSLT elements such as xsl:value-of to create the value. This allows you to see which element is being operated on or to provide other useful information.

OUTPUT

ANALYSIS

Inserting Processing Instructions

A processing instruction is used to give a program reading a document additional information on how to process the document. These instructions can be very specific and program/vendor-related instructions or common instructions, such as attaching a stylesheet to an XML or HTML file. Because processing instructions often have bearing on the entire document, they should be inserted at the start of a document. Processing instructions are not widely used in XML, but in HTML, they are more common. It is therefore good to know how to insert them.

Inserting a processing instruction is just as easy as inserting an element, except that you insert a processing instruction with the xsl:processing-instruction element. Like xsl:element, this element has a mandatory name attribute used to identify the processing instruction. The element value is used as the value of the processing instruction. Listing 5.33 shows a sample using a processing instruction.

LISTING 5.33 Stylesheet Inserting a Processing Instruction

1: <?xml version=″“1.0”" encoding="UTF-8"?>
2: <xsl:stylesheet version=″“1.0”"
3:   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4:  
5:   <xsl:template match="/">
6:     <xsl:processing-instruction name="xml-stylesheet">href="05list05.xsl"
Imagetype="text/xml"</xsl:processing-instruction>
7:    <xsl:copy-of select="." />
8:   </xsl:template>
9: </xsl:stylesheet>

ANALYSIS

On line 6 of Listing 5.33, a processing instruction is inserted to attach Listing 5.5 to it as a stylesheet. The name given to the processing instruction is therefore xml-stylesheet. The value links to the file containing Listing 5.5 and specifies that that file is XML. This is just like the processing instruction used on Day 2, “Transforming Your First XML,” to attach a stylesheet to an XML source. Line 7 copies the entire document in Listing 5.4 to the output, so the result is as shown in Listing 5.34.

OUTPUT

LISTING 5.34 Result from Applying Listing 5.33 to Listing 5.4

<?xml version=″“1.0”" encoding="utf-8"?><?xml-stylesheet href="05list05.xsl"
Image    type="text/xml"?><cars>
    <car model="Focus" manufacturer="Ford" year="2000"/>
    <car model="Golf" manufacturer="Volkswagen" year="1999"/>
    <car model="Camry" manufacturer="Toyota" year="1999"/>
    <car model="Civic" manufacturer="Honda" year="2000"/>
    <car model="Prizm" manufacturer="Chevrolet" year="2000"/>
</cars>

ANALYSIS

Listing 5.34 displays the same document as Listing 5.4. The difference is in the first line, which contains a processing instruction attaching Listing 5.5 to it. If you viewed Listing 5.34 in an XML/XSLT enabled browser, it would appear as Listing 5.6 displayed in a browser.

Summary

Today you learned all about inserting text, elements, and attributes. Although most methods are fairly easy, you can choose from many methods. If you need to insert literal elements and attributes, the easiest way is to write them in the stylesheet as they should appear. When they need to be generated from data in the source document, you use xsl:element and xsl:attribute.

You can quickly add sets of elements and attributes using named (or matched) templates. If you need to insert sets of attributes, you have the option of using the use-attribute-sets attribute to specify sets of predefined attributes that need to be inserted. Attribute-sets can be created from other attribute-sets, so you can create quick and easy inserts that actually insert a complex set of attributes. If two attributes inserted for an element are the same, the one defined last prevails.

Tomorrow you will learn more details about taking action based on elements or attributes in the source document. This way, you can insert elements and text even more selectively.

Q&A

Q I have seen several methods to insert elements and attributes. Which is best?

A There is not really a best way to insert elements and attributes. The XSLT specification does not include any implementation details for the processors, so different processors use different implementations with different performance characteristics. Go with what works for you.

Q Why doesn’t xsl:copy-of support attribute-sets?

A Suppose you copy a large tree fragment. In this case, attributes are added to all elements in the tree fragment. The likelihood that you would want this result is very small. When you need this result, you can create a named template to add the attributes.

Q Does xsl:copy-of have to operate on the context node?

A Certainly not. The select attribute can contain an expression that selects any node or node-set. It does not have to be the context node or relative to the context node.

Workshop

This workshop tests whether you understand all the concepts you learned today. It is very helpful to know and understand the answers before starting tomorrow’s lesson. You can find the answers to the quiz questions and exercises in Appendix A.

Quiz

1. True or False: For an XSLT processor, there is a difference between inserting characters as is and using output escaping.

2. True or False: You can use xsl:attribute only to create attributes for an element created with xsl:element.

3. What is the purpose of the XPath function name ()?

4. What is the difference between shallow copy and deep copy?

5. Is there a difference between <xsl:element name=”{name ()}” /> and <xsl:copy />?

Exercise

1. Create a stylesheet for Listing 5.4 to create the output from Listing 5.8, but use xsl:copy and xsl:element where possible.

5

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.51.153