Приглашаем посетить
Чуковский (chukovskiy.lit-info.ru)

5.3 Manipulating XML data with XSLT

Table of Contents

Previous Next

5.3 Manipulating XML data with XSLT

5.3.1 Generating loops with XSLT

In this section, we consider some XSLT pages and techniques that can perform some data manipulation of an XML file. First, we will show you how to perform loops on XML data. Based on the loops, a number of basic database operations such as sorting, filtering, and query can be performed.

Another way to display the entire XML page or data is to use the for-each element <xsl:foreach>. This element has the following general form:



<xsl:for-each select="street/profile">
  xxx
  xxx
</xsl:for-each>

This statement can read all children of the <profile> element one by one specified by the calling XML document. To construct an example of this feature, you first modify line 2 of ex05-11.xml to call the XSLT page. The new page is called ex05-12.xml. The XSLT file ex05-12.xsl is listed below:



Example: ex05-12.xsl - Generating Loops

 1: <?xml version="1.0" encoding="ISO-8859-1"?>
 2: <xsl:stylesheet version="1.0"
 3: xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4: <xsl:template match="/">
 5:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 6:  <head><title>ex05-12.xsl</title>
 7:   <style>
 8:     .txtSt {font-family:arial;font-size:19pt;font-weight:bold}
 9:   </style>
10:  </head>
11:  <body class="txtSt" style="color:#000088">
12:     Household Records Of Richmond Road <br />
13:     West Yorkshire <br /><br />
14:     <table border="1" style="background:#888888;
15:        color:#ffffff;font-family:arial;font-size:14pt">
16:       <tr>
17:         <th>Name</th> <th>Job</th>
18:         <th>Sex</th> <th>Age</th>
19:         <th>Phone</th> <th>Location</th> <th>Address</th>
20:       </tr>
21:       <xsl:for-each select="street/profile">
22:       <tr>
23:         <td><xsl:value-of select="name"/></td>
24:         <td><xsl:value-of select="job"/></td>
25:         <td><xsl:value-of select="sex"/></td>
26:         <td><xsl:value-of select="age"/></td>
27:         <td><xsl:value-of select="phone"/></td>
28:         <td><xsl:value-of select="location"/></td>
29:         <td><xsl:value-of select="address"/></td>
30:       </tr>
31:       </xsl:for-each>
32:     </table>
33:   </body>
34:   </html>
35: </xsl:template>
36: </xsl:stylesheet>

If you compare this page with ex05-09.xsl, you will find that we have inserted the for-each element <xsl:for-each select=xxx> in lines 2131. As a result, it works like a simple for-loop to generate a series of statements between the loops. It will generate a number of table rows for the XHTML table. Also, we have added some CSS style settings in this example to show that XSLT takes care of CSS properties as well. A screen shot of this example is shown in Fig. 5.9.

Figure 5.9. XSLT of ex05-12.xml

graphics/05fig09.jpg


Now, you have put the data into a table. The next question is: how can you a sort the data?

5.3.2 Sorting XML data with XSLT

One important feature for data manipulation is sorting. With XSLT, you will find that to sort the data within an XML document is very easy. In many cases, all you have to do is to add one sort statement into your XSLT page. Consider the following example ex05-13.xsl:



Example: ex05-13.xsl - Sorting Elements

 1: <?xml version="1.0" encoding="ISO-8859-1"?>
 2: <xsl:stylesheet version="1.0"
 3: xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4: <xsl:template match="/">
 5:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 6:  <head><title>ex05-13.xsl</title>
 7:   <style> .txtSt {font-family:arial;font-size:19pt;font-weight:bold}
 8:   </style>
 9:  </head>
10:  <body class="txtSt" style="color:#000088">
11:     Household Records Of Richmond Road <br />
12:     West Yorkshire <br />(With Sorting On Names)<br /><br />
13:     <table border="1" style="background:#888888;
14:        color:#ffffff;font-family:arial;font-size:14pt">
15:       <tr>
16:         <th>Name</th> <th>Job</th>
17:         <th>Sex</th> <th>Age</th>
18:         <th>Phone</th> <th>Location</th>
19:         <th>Address</th>
20:       </tr>
21:       <xsl:for-each select="street/profile">
22:       <xsl:sort select="name" />
23:       <tr>
24:         <td><xsl:value-of select="name"/></td>
25:         <td><xsl:value-of select="job"/></td>
26:         <td><xsl:value-of select="sex"/></td>
27:         <td><xsl:value-of select="age"/></td>
28:         <td><xsl:value-of select="phone"/></td>
29:         <td><xsl:value-of select="location"/></td>
30:         <td><xsl:value-of select="address"/></td>
31:       </tr>
32:       </xsl:for-each>
33:     </table>
34:   </body>
35:   </html>
36:  </xsl:template>
37: </xsl:stylesheet>

If you compare this example with ex05-12.xsl, you will find that the main difference is the statement in line 22:



<xsl:sort select="name" />

In fact, you have just added this statement inside the for-each loop described in lines 2232. This statement will select the data within the <name> element and perform a sort. Suppose you have modified line 2 of ex05-12.xml to form a new example (e.g., ex05-13.xml) to call this transformation page. If you activate this new XML page by http://www.pwtex.com/book/chap05a/ex05-13.xml, you will see the sort result as illustrated in Fig. 5.10.

Figure 5.10. XSLT with sorting

graphics/05fig10.jpg


By just using one more statement, XML data can be sorted automatically. You can use this statement to sort almost any data described in your XML pages. In general, the sort element in XSLT has the following syntax:



<xsl:sort   select       ="expression"
            order        ="ascending|descending"
            case-order   ="upper-first|lower-first"
            lang         ="language-code"
            data-type    ="text|number|qname"/>

The detailed explanation of the attributes and values is given in Table 5.2.

Table 5.2. XSLT sort element

Attribute

Value

Description

select

expression

Sort expression

order

ascending

descending

Sort order; the default is "ascending"

case-order

upper-first

lower-first

Upper case letters or lower case letters come first

lang

language-code

The language to use for sorting purposes

data-type

Text

Number

Qname

The type of the data to be sorted (number, text, or user-defined type) and the default type is "text"


Next, we are going to show you how to perform some data filtering using XSLT pages and techniques.

5.3.3 Using XSLT filtering and query features

To be able to select and filter data is important for many data-related applications. In XSLT, some of these filtering and query features can be implemented easily. For example, you can use the select attribute to filter the data in an XML file. Consider the following XSLT page:



Example: ex05-14.xsl - XSLT With Filtering And Query

 1: <?xml version="1.0" encoding="ISO-8859-1"?>
 2: <xsl:stylesheet version="1.0"
 3: xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4: <xsl:template match="/">
 5:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 6:  <head><title>ex05-14.xsl</title>
 7:   <style> .txtSt {font-family:arial;font-size:19pt;font-weight:bold}
 8:   </style>
 9:  </head>
10:  <body class="txtSt" style="color:#000088">
11:     Household Records Of Richmond Road <br />
12:     West Yorkshire <br /><br />
13:     <table border="1" style="background:#888888;
14:        color:#ffffff;font-family:arial;font-size:14pt">
15:       <tr>
16:         <th>Name</th> <th>Job</th>
17:         <th>Sex</th> <th>Age</th>
18:         <th>Phone</th> <th>Location</th>
19:         <th>Address</th>
20:       </tr>
21:       <xsl:for-each select="street/profile[name='Peter']">
22:       <tr>
23:         <td><xsl:value-of select="name"/></td>
24:         <td><xsl:value-of select="job"/></td>
25:         <td><xsl:value-of select="sex"/></td>
26:         <td><xsl:value-of select="age"/></td>
27:         <td><xsl:value-of select="phone"/></td>
28:         <td><xsl:value-of select="location"/></td>
29:         <td><xsl:value-of select="address"/></td>
30:       </tr>
31:       </xsl:for-each>
32:     </table>
33:   </body>
34:   </html>
35: </xsl:template>
36: </xsl:stylesheet>

As you can see from this example, you don't need to add any additional statements to perform data filtering. Instead, you can modify the select attribute to do the job. The statement in line 21



<xsl:for-each select="street/profile[name='Peter']">

generates a for-each loop and selects any data whose name is Peter at the same time. If you modify the XML page ex05-13.xml and call it ex05-14.xml to call this XSLT, you will see the selected result as illustrated in Fig. 5.11.

Figure 5.11. XSLT with selection

graphics/05fig11.gif


Another way to perform selection is to use the if conditional element <xsl:if test=xxx>. For example, the following statement can be used to pick all the names equal to "Peter":



<xsl:if test="name='Peter'">
    xxx xxx xxx
    xxx xxx xxx
</xsl:if>

As a simple example, you can modify the second half of ex05-14.xsl (starting from line 21) as follows:



Listing ex05-01.txt - Code Fragment Of ex0515.xsl

21:       <xsl:for-each select="street/profile">
22:       <xsl:if test="name='Peter'">
23:       <tr>
24:         <td><xsl:value-of select="name"/></td>
25:         <td><xsl:value-of select="job"/></td>
26:         <td><xsl:value-of select="sex"/></td>
27:         <td><xsl:value-of select="age"/></td>
28:         <td><xsl:value-of select="phone"/></td>
29:         <td><xsl:value-of select="location"/></td>
30:         <td><xsl:value-of select="address"/></td>
31:       </tr>
32:       </xsl:if>
33:       </xsl:for-each>
34:     </table>
35:   </body>
36:   </html>
37: </xsl:template>
38: </xsl:stylesheet>

The if element in this example performs a selection. Only those names equal to "Peter" will get through the statements in lines 2331. This example has the same result as example ex05-14.xsl.

Another interesting XSLT query is the combination of the choose, when, and otherwise elements. The general calling format for this query is



<xsl:choose>
   <xsl:when test="name='Peter'">
        xxx coding for the test xxx
   </xsl:when>
   <xsl:otherwise>
        xxx coding for the otherwise xxx
   </xsl:otherwise>
</xsl:choose>

This structure is often used to select some particular data for a special purpose. For a simple use of this structure, let's consider the following example:



Example: ex05-16.xsl - Using The Choose Feature

 1: <?xml version="1.0" encoding="ISO-8859-1"?>
 2: <xsl:stylesheet version="1.0"
 3: xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4: <xsl:template match="/">
 5:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 6:  <head><title>ex05-16.xsl</title>
 7:   <style> .txtSt {font-family:arial;font-size:19pt;font-weight:bold}
 8:   </style>
 9:  </head>
10:  <body class="txtSt" style="color:#000088">
11:     Household Records Of Richmond Road <br />
12:     West Yorkshire <br /><br />
13:     <table border="1" style="background:#888888;
14:        color:#ffffff;font-family:arial;font-size:14pt">
15:       <tr>
16:         <th>Name</th> <th>Job</th>
17:         <th>Sex</th> <th>Age</th>
18:         <th>Phone</th> <th>Location</th>
19:         <th>Address</th>
20:       </tr>
21:       <xsl:for-each select="street/profile">
22:       <tr>
23:        <xsl:choose>
24:        <xsl:when test="name='Peter'">
25:          <td style="background:#ff0000;color:#ffff00">
26:              <xsl:value-of select="name"/></td>
27:          <td><xsl:value-of select="job"/></td>
28:          <td><xsl:value-of select="sex"/></td>
29:          <td><xsl:value-of select="age"/></td>
30:          <td><xsl:value-of select="phone"/></td>
31:          <td><xsl:value-of select="location"/></td>
32:          <td><xsl:value-of select="address"/></td>
33:        </xsl:when>
34:        <xsl:otherwise>
35:          <td><xsl:value-of select="name"/></td>
36:          <td><xsl:value-of select="job"/></td>
37:          <td><xsl:value-of select="sex"/></td>
38:          <td><xsl:value-of select="age"/></td>
39:          <td><xsl:value-of select="phone"/></td>
40:          <td><xsl:value-of select="location"/></td>
41:          <td><xsl:value-of select="address"/></td>
42:        </xsl:otherwise>
43:        </xsl:choose>
44:       </tr>
45:       </xsl:for-each>
46:     </table>
47:   </body>
48:   </html>
49: </xsl:template>
50: </xsl:stylesheet>

The choose element will take effect at line 23. The when element in line 24



<xsl:when test="name='Peter'">

will test the data for the name equal to "Peter." If there is a match, the formatting statements in lines 2532 will be used to format the data. In this case, both the foreground and background colors of the data will be changed. If the name is not "Peter," the statements (lines 3442) in the otherwise element <xsl:otherwise> are executed. As a result, only the record with name equal to "Peter" will change color. A screen shot of this example is shown in Fig. 5.12.

Figure 5.12. XSLT with choose

graphics/05fig12.jpg


In order to use XSLT more effectively, you may need to use variables in XSLT.

5.3.4 Using variables in XSLT

You can declare a variable in XSLT by using the variable element <xsl:variable>. This element has the following general calling format:



<xsl:variable name="name" select="expression">
   xxx xxx xxx
</xsl:variable>

The attributes and accepted values are listed in Table 5.3.

Table 5.3. The attributes and values of the variable element

Attribute

Value

Description

name

name

Variable name

select

expression

Variable value


The name attribute is to identify the variable so the corresponding value stored in the variable can be accessed. The select attribute is the usual expression (select expression) and is used to obtain the value of the variable. For example, the statement below declares a variable element called jacket:



<xsl:variable name="jacket" select="'leather'" >
</xsl:variable>

In fact, the select attribute is optional. For example, the following example will define a variable with an empty string as value:



<xsl:variable name="jacket"> xxx xxx xxx </xsl:variable>

For a practical example, let's consider a menu from a restaurant. The menu consists of some dishes grouped into different categories. By using XML and XSLT, you will find that it is easier to generate line numbers for the menu item than the HTML/XHTML counterpart. Consider the XML data page for the menu:



Example: ex05-17.xml - Using XSLT Variables

 1: <?xml version="1.0"?>
 2: <?xml-stylesheet type="text/xsl" href="ex05-17.xsl"?>
 3: <menu>
 4:   <item>
 5:     <dishes_type>Sea Food -- $7.60</dishes_type>
 6:     <dishes>Fried Fish In Thai Style (Hot) -- With Salad</dishes>
 7:     <dishes>Fried Squid In Thai Style (Hot) -- With Salad</dishes>
 8:     <dishes>Curry Crab Thai Style (Hot) -- With Salad</dishes>
 9:   </item>
10:   <item>
11:     <dishes_type>Curry &amp; Meat -- $6.40</dishes_type>
12:     <dishes>Red Beef Curry (Hot) -- With Salad</dishes>
13:     <dishes>Green Curry Chicken (Hot) -- With Salad</dishes>
14:     <dishes>Roast Pork Curry (Hot) -- With Salad</dishes>
15:   </item>
16:   <item>
17:     <dishes_type>Rice &amp; Noodles -- $3.40</dishes_type>
18:     <dishes>Fried Rice Noodles Thai Style </dishes>
19:     <dishes>Fried Rice In Thai Style </dishes>
20:     <dishes>King Prawn Fried Rice In Thai Style</dishes>
21:   </item>
22: </menu>

This menu has three item elements <item>. Each item contains one dish-type element <dishes_type> and some dishes <dishes>. In practice, we would like to build a line number on the <dishes> element across the whole page to make it easier for customers to make their choices. To do that, you can use the XSLT below:



Example: ex05-17.xsl - Using Variables

 1: <?xml version="1.0" encoding="ISO-8859-1"?>
 2: <xsl:stylesheet version="1.0"
 3:  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4:
 5:  <xsl:template match="/">
 6:   <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 7:   <head><title>ex0517.xsl</title>
 8:   </head>
 9:   <body style="font-family:arial;;font-weight:bold;
10:           width:800px;height:600px;background:#000088">
11:    <div style="color:#00ff00;font-size:20pt;text-align:center" >
12:          ABC Resturant <br /> (Thai and Oriental Tastes)<br /><br />
13:     <xsl:apply-templates select="/menu/item" />
14:     <span style="font-size:16pt">
15:         All Dishes Come With Coconut Soup Of The Day<br /><br /></span>
16:    </div>
17:   </body>
18:   </html>
19:  </xsl:template>
20:
21:  <xsl:template match="item">
22:   <div align="center">
23:     <table style="font-size:14pt;color:#00ffff;font-family:arial;
24:             margin-top:10px;text-align:left">
25:       <tr><td colspan="2" style="font-size:16pt;
26:              color:#ffff00;text-align:left">
27:           <xsl:apply-templates select="dishes_type" /> </td>
28:       </tr>
29:       <xsl:apply-templates select="dishes" />
30:     </table><br />
31:   </div>
32:  </xsl:template>
33:
34:  <xsl:template match="dishes" >
35:    <tr>
36:      <td width="50" style="text-align:left">
37:        <xsl:variable name="add_no">
38:           <xsl:number level="any" from="menu" />
39:        </xsl:variable>
40:        <xsl:value-of select="$add_no"/>
41:      </td>
42:      <td width="400" style="text-align:left">
43:          <xsl:value-of select="."/></td>
44:    </tr>
45:  </xsl:template>
46:
47: </xsl:stylesheet>

This transform has three templates. The first template is defined in lines 519 and specifies the framework of an XHTML page. When the user agent executes the statement in line 13



<xsl:apply-templates select="/menu/item"/>

each element <item> from the XML document will be processed and output as part of the XHTML page. When each <item> element is called, it will be formatted by the template defined in lines 2132. Inside this template is a table. The first row of the table (lines 2528) outputs the dish type. The statement in line 29



<xsl:apply-templates select="dishes" />

output all values of <dishes>. Before the output, all <dishes> elements are formatted by the third template defined in lines 3445. This template is used to generate line numbers on the <dishes> elements. The important part of this template is in lines 3740:



<xsl:variable name="add_no">
    <xsl:number level="any" from="menu" />
</xsl:variable>
<xsl:value-of select="$add_no"/>

First, a variable called $add_no is declared by using the variable element <xsl:variable>. Inside this element, an XSLT number element <xsl:number> is defined. The attribute from="menu" instructs the user agent (or capable browser) to search the <menu> tree for the <dishes> node and assign a number to it. The number is output by the value-of element. For example, after this template transformation, the first two dishes in the XML file ex05-17.xml turn out to be



<tr>
  <td width="50" style="text-align:left"> 1 </td>
  <td width="400" style="text-align:left">
    Fried Fish In Thai Style (Hot) -- With Salad </td>
</tr>
<tr>
  <td width="50" style="text-align:left"> 2 </td>
  <td width="400" style="text-align:left">
    Fried Squid In Thai Style (Hot) -- With Salad</td>
</tr>

When all the transformations are completed, you will have an XHTML document returned to the browser. A screen shot of this example is shown in Fig. 5.13.

Figure 5.13. Generating line numbers

graphics/05fig13.jpg


From this figure, you can see that the line numbers of the dishes are consecutive. If you change the statement in line 38 as follows:



<xsl:number level="any" from="item" />

the line number starts from the item element and search for each <dishes>. In this case, there will be a recount after each <item>. A screen shot of this in action is shown in Fig. 5.14. However, if you change the statement to



<xsl:number level="any" from="dishes" />

Figure 5.14. Line number for each dish type

graphics/05fig14.jpg


all counting will be zero. This is due to the fact that there is no <dishes> element inside <dishes>. Now, let's consider some other XML techniques on the Web.

    Table of Contents

    Previous Next