62
©CSW Group Ltd 2005 Practical XSLT Bob DuCharme www.snee.com/bob [email protected] these slides: www.snee.com/xml 1.0

©CSW Group Ltd 2005 Practical XSLT Bob DuCharme [email protected] these slides: 1.0

Embed Size (px)

Citation preview

Page 1: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

©CSW Group Ltd 2005

Practical XSLTBob DuCharme

www.snee.com/[email protected] slides:

www.snee.com/xml1.0

Page 2: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0
Page 3: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Outline• What is XSLT?

• Our first stylesheet: renaming and deletion

• Running stylesheets

• Reordering elements

• Renaming attributes

• Converting elements to attributes and vice versa

• Outputting plain text and controlling white space

• Conditional execution

• Selective output of data

• XPath

Page 4: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XSLT

• XSL Transformations (XSLT)• relationship to XSL• XSLT 1.0 W3C Recommendation November

16, 1999• XSLT 1.1 W3C Working Draft December 12,

2000

• (as of 8 June 2005): XPath 2.0, XSLT 2.0, XQuery 1.0 in “last call Working Draft” status

from Abstract:"This specification defines the syntax and

semantics of XSLT, which is a language for transforming XML documents into other XML documents."

Page 5: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Documents, treesFrom section 1, "Introduction" of XSLT spec:

"A transformation expressed in XSLT describes rules for transforming a source tree into a result tree."

What about documents?

Page 6: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

An XSLT stylesheet<?xml version="1.0"?> <xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="year">    <vintage>      <xsl:apply-templates/>    </vintage>  </xsl:template>

  <xsl:template match="price">  </xsl:template>

  <xsl:template match="@*|node()">    <xsl:copy>      <xsl:apply-templates select="@*|node()"/>    </xsl:copy>  </xsl:template>

</xsl:stylesheet>

"Literal result elements"

Page 7: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Running it

my saxon shell script:#! /bin/shjava net.sf.saxon.Transform $1 $2 $3 $4 $5 $6 $7

saxon.bat:java net.sf.saxon.Transform %1 %2 %3 %4 %5 %6 %7

Running example:saxon -o wine1.out wine1.xml wine1.xsl

More processors: Xalan C++, Xalan Java, libxslt... see http://www.xmlsoftware.com/xslt.html.

Page 8: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Effect of first example

testxslt -in wine1.xml -xsl wine1.xsl

turns this

  <wine grape="chardonnay">    <product>Carneros</product>    <year>1997</year>    <price>10.99</price>  </wine>

into this:

  <?xml version="1.0" encoding="UTF-8"?>  <wine grape="chardonnay">    <product>Carneros</product>    <vintage>1997</vintage>      </wine>

Page 9: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Empty xsl:stylesheet element<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>

turns this <winelist date="20000626">

  <wine grape="chardonnay">     <product>Carneros</product>     <year>1997</year>     <price>10.99</price>   </wine>

</winelist>

into this: <?xml version="1.0" encoding="UTF-8"?>

    Carneros     1997     10.99

Page 10: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Doing it yourself: sample data

• wine.xml for demonstrations

• orders.xml for exercises

Page 11: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

wine.xml (part 1 of 2)

<?xml version="1.0"?><winelist>

  <wine grape="chardonnay">    <winery>Benziger</winery>    <product>Carneros</product>    <year>1997</year>    <desc>Well-textured flavors, good finish.</desc>    <prices>      <list>10.99</list>      <discounted>9.50</discounted>      <case>114.00</case>    </prices>  </wine>

Page 12: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

wine.xml (part 2 of 2)

  <wine grape="cabernet">    <winery>Duckpond</winery>    <product>Merit Selection</product>    <year>1996</year>    <desc>Sturdy and generous flavors, long finish.</desc>    <prices>      <list>13.99</list>      <discounted>11.99</discounted>      <case>143.50</case>    </prices>  </wine>

  <wine grape="chardonnay">    <winery>Lindeman's</winery>    <product>Bin 65</product>    <year>1998</year>    <desc>Youthful, with a cascade of spicy fig.</desc>    <prices>      <list>6.99</list>      <discounted>5.99</discounted>      <case>71.50</case>    </prices>  </wine></winelist>

Page 13: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

orders.xml (part 1 of 5)

<!ELEMENT orders (order+)>        <!ELEMENT order  (quantity, pricePerItem, orderDate, warrantee?,billingAddr,shippingAddr?,productPic?)>

Page 14: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

orders.xml (part 2 of 5)

<orders>

  <order orderNum="o43123" itemNum="i1009">    <quantity>1</quantity>    <pricePerItem>29.99</pricePerItem>    <orderDate>20000623</orderDate>    <warrantee>90 days parts and labor</warrantee>    <billingAddr lastUpdate="20000623">      <recip>Sterling Moss</recip>      <line1>21 Manor Dr.</line1>      <line2></line2>      <city>Milford</city>      <state>CT</state>      <zip>06460</zip>    </billingAddr>    <productPic picent="a124"/>  </order>

Page 15: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

orders.xml (part 3 of 5)  <order orderNum="o24987" itemNum="i0874">    <quantity>4</quantity>    <pricePerItem>9.99</pricePerItem>    <orderDate>20000621</orderDate>    <billingAddr lastUpdate="20000621">      <recip>Johnny Herbert</recip>      <line1>37 8th Ave.</line1>      <line2>Apt. 3</line2>      <city>Brooklyn</city>      <state>NY</state>      <zip>11217</zip>    </billingAddr>

    <shippingAddr lastUpdate="19990405">      <recip>Martin Blundell</recip>      <line1>37 8th Ave.</line1>      <line2>Apt. 5</line2>      <city>Brooklyn</city>      <state>NY</state>      <zip>11217</zip>    </shippingAddr>    <productPic picent="a123"/>  </order>

Page 16: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

orders.xml (part 4 of 5)  <order orderNum="o86734" itemNum="i2118">    <quantity>1</quantity>    <pricePerItem>300.00</pricePerItem>    <orderDate>20000625</orderDate>    <warrantee></warrantee>    <billingAddr lastUpdate="19990422">      <recip>Damon Hill</recip>      <line1>321 Main St.</line1>      <line2></line2>      <city>Delavan</city>      <state>WI</state>      <zip>21353</zip>    </billingAddr>    <shippingAddr lastUpdate="19990405">      <recip>Graham Hill</recip>      <line1>9344 Simon Rd.</line1>      <line2></line2>      <city>Lake Geneva</city>      <state>WI</state>      <zip>21993</zip>    </shippingAddr>  </order>

Page 17: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

orders.xml (part 5 of 5)

  <order orderNum="o67918" itemNum="i1009">    <quantity>2</quantity>    <pricePerItem>29.99</pricePerItem>    <orderDate>20000622</orderDate>    <warrantee></warrantee>    <billingAddr lastUpdate="19981103">      <recip>Jenson Button</recip>      <line1>38 North Spring Ave.</line1>      <line2>Apt. 32</line2>      <city>Atlanta</city>      <state>GA</state>      <zip>92344</zip>    </billingAddr>    <productPic picent="a124"/>  </order>

</orders>

Page 18: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Exercise 1

In a DOS window:

• Enter "saxon" by itself to see what happens.

• Take a look at empty.xsl and orders.xml with your text editor.

• Have saxon process orders.xml using empty.xsl. You can pipe it to "more" or redirect it to a text file if you like.

• Process the same XML file with identity.xsl.

Page 19: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Reviewing Renaming and Deletion<?xml version="1.0"?> <xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="year">    <vintage>      <xsl:apply-templates/>    </vintage>  </xsl:template>

  <xsl:template match="price">  </xsl:template>

  <xsl:template match="@*|node()">    <xsl:copy>      <xsl:apply-templates select="@*|node()"/>    </xsl:copy>  </xsl:template>

</xsl:stylesheet>

"Literal result elements"

Page 20: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Deleting, Part 2

Another way to delete price from the following:

  <wine grape="chardonnay">    <product>Carneros</product>    <year>1997</year>    <price>10.99</price>  </wine>

is like this:

  <xsl:template match="wine">    <wine>      <!-- <xsl:apply-templates/> -->      <xsl:apply-templates select="product"/>      <xsl:apply-templates select="year"/>    </wine>  </xsl:template>

(Note how it also deletes the grape attribute.)

Page 21: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Reordering Elements

  <xsl:template match="wine">    <wine grape="{@grape}">      <xsl:apply-templates select="price"/>      <xsl:apply-templates select="year"/>      <xsl:apply-templates select="product"/>    </wine>  </xsl:template>

turns this

  <wine grape="chardonnay">    <product>Carneros</product>    <year>1997</year>    <price>10.99</price>  </wine>

into this:

  <wine grape="chardonnay">    <price>10.99</price>    <year>1997</year>    <product>Carneros</product>  </wine>

Page 22: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

skeleton.xsl

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!--<xsl:template match="">  <xsl:apply-templates/></xsl:template>-->

<xsl:template match="@*|node()">  <xsl:copy>    <xsl:apply-templates      select="@*|node()"/>  </xsl:copy></xsl:template>

</xsl:stylesheet>

Page 23: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Exercise 2

Copy skeleton.xsl to create a stylesheet called ws1.xsl that does the following when orders.xml is used as input:

•Renames quantity to amount and orderDate to dateOrdered

•Deletes any warrantee and productPic elements (use either deletion method)

•Moves the order date to be the first thing in the order and the shipping address to before the billing address

Don't worry about the order element's attributes for now.

Page 24: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Renaming Attributes

  <wine grape="{@grape}">

outputs this:

  <wine grape="chardonnay">

And this

  <wine varietal="{@grape}">

will output this:

  <wine varietal="chardonnay">

Page 25: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Converting Attributes to Elements & Vice Versa

  <xsl:template match="wine">    <wine vintage="{year}">      <xsl:apply-templates select="product"/>      <category><xsl:value-of select="@grape"/>      </category>      <xsl:apply-templates select="price"/>    </wine>  </xsl:template>

converts  <wine grape="chardonnay">    <product>Carneros</product>    <year>1997</year>    <price>10.99</price>  </wine>

to this:  <wine vintage="1997">    <product>Carneros</product>    <category>chardonnay</category>    <price>10.99</price>  </wine>

Page 26: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Attribute Value Templates

Following WRONG:

<wine functest =      "<xsl:value-of select='string-length(@grape)'>">

Attribute value templates give you much of the power of xsl:value-of in attribute values.

Correct:

<wine functest="{string-length(@grape)}">

Page 27: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

What We've Covered So Far

• deleting elements

• renaming elements

• reordering elements

• deleting attributes

• renaming attributes

• converting elements to attributes

• converting attributes to elements

Page 28: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Exercise 3

Prepare a stylesheet that copies orders.xml, doing the following to the result:

•Rename the itemNum attribute to be just item.

•Make orderNum a subelement of order instead of an attribute.

•Make quantity an attribute of order instead of a subelement.

If time, give order a new child called addresses that has billingAddr and shippingAddr as its children. (Hint: you can use a literal result element with XSLT elements inside of it.)

Page 29: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Controlling White Space, Part 1

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>

  <xsl:template match="wine">

 test string 1 <xsl:apply-templates select="winery"/>

 <xsl:text>test string 2</xsl:text> <xsl:apply-templates select="winery"/>

  </xsl:template>

</xsl:stylesheet>

Page 30: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Controlling White Space, Part 1

Output of previous stylesheet with wine.xml:

  test string 1  Benzigertest string 2Benziger

  test string 1  Duckpondtest string 2Duckpond

  test string 1  Lindeman'stest string 2Lindeman's

Page 31: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Controlling White Space, Part 2

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>

  <xsl:template match="wine">

    Wine:    <xsl:apply-templates select="winery"/>    <xsl:apply-templates select="product"/>    <xsl:apply-templates select="year"/>

  </xsl:template>

</xsl:stylesheet>

Page 32: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Controlling White Space, Part 2

Output of previous stylesheet with wine.xml:

Wine: BenzigerCarneros1997 Wine: DuckpondMerit Selection1996 Wine: Lindeman'sBin 651998

Page 33: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Controlling White Space, Part 2b

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>

  <xsl:template match="wine">

Wine:<xsl:apply-templates select="winery"/><xsl:text></xsl:text>    <xsl:apply-templates select="product"/><xsl:text></xsl:text>    <xsl:apply-templates select="year"/>

  </xsl:template>

</xsl:stylesheet>

Page 34: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Controlling White Space, Part 2b

Output of previous stylesheet with wine.xml:Wine:BenzigerCarneros1997

Wine:DuckpondMerit Selection1996

Wine:Lindeman'sBin 651998

Page 35: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Exercise 4

Prepare a stylesheet that creates a comma-separated value (CSV) from orders.xml showing each order's quantity, pricePerItem, and orderDate on each line. The output should look like this:

1,29.99,200006234,9.99,200006211,300.00,200006252,29.99,20000622

Don't worry if lines are skipped between the lines of output, but make sure that each order's information is all on one line.

Page 36: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Control Structures: if

<xsl:template match="wine">  <wine grape="{@grape}">    <xsl:if test='@grape = "chardonnay"'>      <emph>Special sale on chardonnays!</emph>    </xsl:if>    <xsl:apply-templates select="*|@*|text()"/>  </wine></xsl:template>

Page 37: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

xsl:if in ActionPrceding turns this:

<wine grape="chardonnay">  <product>Carneros</product>  <year>1997</year>  <price>10.99</price></wine><wine grape="cabernet">  <product>Merit Selection</product>  <year>1996</year>  <price>13.99</price></wine>

into this:

<wine grape="chardonnay">  <emph>Special sale on chardonnays!</emph>  <product>Carneros</product>  <year>1997</year>  <price>10.99</price></wine><wine grape="cabernet">  <product>Merit Selection</product>  <year>1996</year>  <price>13.99</price></wine>

Page 38: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Control Structures: choose

<xsl:template match="wine">  <wine grape="{@grape}">    <xsl:choose>      <xsl:when test='@grape = "chardonnay"'>        <emph>Special sale on chardonnays!</emph>      </xsl:when>      <xsl:when test='@grape = "cabernet"'>        <emph>Gotta love them cabernets!</emph>      </xsl:when>      <xsl:otherwise>        <emph>Another fabulous grape!</emph>      </xsl:otherwise>    </xsl:choose>    <xsl:apply-templates select="*|@*|text()"/>  </wine></xsl:template>

Page 39: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

xsl:choose in Action

Preceding template turns this

<wine grape="chardonnay">  <product>Carneros</product>  <year>1997</year><price>10.99</price></wine><wine grape="cabernet">  <product>Merit Selection</product>  <year>1996</year><price>13.99</price></wine>

into this:

<wine grape="chardonnay">  <emph>Special sale on chardonnays!</emph>  <product>Carneros</product>  <year>1997</year><price>10.99</price></wine>

<wine grape="cabernet">  <emph>Gotta love them cabernets!</emph>  <product>Merit Selection</product>  <year>1996</year><price>13.99</price></wine>

Page 40: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Selective output based on data values, Part 1<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="wine">  <xsl:if test="@grape = 'chardonnay'">    <xsl:copy>      <xsl:apply-templates        select="@*|node()"/>    </xsl:copy>  </xsl:if></xsl:template>

<xsl:template match="@*|node()">  <xsl:copy>    <xsl:apply-templates      select="@*|node()"/>  </xsl:copy></xsl:template>

</xsl:stylesheet>

Page 41: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Selective output based on data values, Part 1<?xml version="1.0" encoding="utf-8"?><winelist>  <wine grape="chardonnay">    <winery>Benziger</winery>    <product>Carneros</product>    <year>1997</year>    <desc>Well-textured flavors, good finish.</desc>    <prices>      <list>10.99</list>      <discounted>9.50</discounted>      <case>114.00</case>    </prices>  </wine>  <wine grape="chardonnay">    <winery>Lindeman's</winery>    <product>Bin 65</product>    <year>1998</year>    <desc>Youthful, with a cascade of spicy fig.</desc>    <prices>      <list>6.99</list>      <discounted>5.99</discounted>      <case>71.50</case>    </prices>  </wine></winelist>

Page 42: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Selective output based on data values, Part 2

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="wine[@grape != 'chardonnay']"></xsl:template>

<xsl:template match="@*|node()">  <xsl:copy>    <xsl:apply-templates      select="@*|node()"/>  </xsl:copy></xsl:template>

</xsl:stylesheet>

Page 43: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Exercise 5

• Write a stylesheet that only copies the order elements with a pricePerItem of more than 50.

• Remember that a < or > character inside of an attribute value must be represented as an entity reference (&lt; or &gt;).

Page 44: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath

Abstract of spec: a "language for addressing parts of an XML document, designed to be used by both XSLT and XPointer."

Split out from XSLT; became a W3C Recommendation in November of 1999.

Used by XSLT, XPointer, and by XQuery

Page 45: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Iterating across a set of nodes<a> <b>3</b> <c>10</c> <b>4</b> <c>20</c> <b>5</b></a>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="a"> <xsl:for-each select="b"> <xsl:value-of select=". + 5"/> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template></xsl:stylesheet>

output:

<?xml version="1.0" encoding="UTF-8"?>8 9 10

Page 46: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Addressing Parts of a Document

<poem> <title>Crossroad Blues</title>

<stanza> <verse>I went down to the crossroads, fell down on my

knees.</verse> <verse>I went down to the crossroads, fell down on my

knees.</verse> <verse>Ask the lord above have mercy, save me if you

please.</verse> </stanza>

<stanza> <verse>Standing at the crossroads, tried to flag a ride</verse> <verse>Standing at the crossroads, tried to flag a ride</verse> <verse>Nobody seems to know me, everybody pass me by.</verse> </stanza></poem>

Page 47: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Addressing Parts of a Document

/poem/title

/poem/stanza/verse

/

/poem/*

..

../title

Page 48: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath Syntax

XPath expression expressed as a location path.

Location path: one or more location steps separated by "/".

Slash at beginning makes it an absolute location path.

Compare Windows or Unix directory names: \windows\cookies vs. windows\cookies vs. ..\cookies, or /usr/bin vs. usr/bin vs. ../bin

For a winelist node, output the first year child of a wine element:

  <xsl:template match="winelist">    <xsl:value-of select="wine/year"/>  </xsl:template>

Page 49: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath: Location StepsFrom the XPath spec:

"A location step has three parts:

●an axis, which specifies the tree relationship between the nodes selected by the location step and the context node,

●a node test, which specifies the node type and expanded-name of the nodes selected by the location step, and

●zero or more predicates, which use arbitrary expressions to further refine the set of nodes selected by the location step."

For XSLT purposes, the context node is the node that the XSLT processor is currently dealing with as it goes through the source tree's nodes.

Page 50: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath Location Steps: Axes

axes: child, descendant, parent, ancestor, following-sibling, preceding-sibling, following, preceding, attribute, namespace, self, descendant-or-self, and ancestor-or-self.child is default.

<xsl:value-of select="child::wine">

same as

<xsl:value-of select="wine">

Page 51: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

preceding-sibling axis and wine.xml

<xsl:template match="product">    <name>      <xsl:value-of  select="preceding-sibling::winery"/>      <xsl:text> </xsl:text>      <xsl:value-of select="."/>    </name>  </xsl:template>

turns

 <winery>Benziger</winery> <product>Carneros</product>

into this:

<name>Benziger Carneros</name>

Page 52: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath Location Steps: Node Test

<xsl:value-of select="child::wine"><xsl:value-of select="wine">

Node test: "wine" above; "*" in following:

<xsl:value-of select="*">

Page 53: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath Location Steps: Predicate

From spec: "A predicate filters a node-set with respect to an axis to produce a new node-set."

<xsl:value-of select="child::wine[last()]"/>

<xsl:value-of select="child::wine[1]"/>

<xsl:value-of select="wine[@grape='cabernet']">

<xsl:value-of select="wine[count(*) = 0]">

<xsl:value-of select="wine[@grape]">

Contrast last one with

<xsl:value-of select="@grape">

Page 54: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath Abbreviations Part 1

Section 2.5, Abbreviated Syntax of the XPath spec lists handy abbreviations to use instead of the full axisname::nodeTest[predicate] syntax

. abbreviates self::node()

// abbreviates descendant-or-self::node() (node() returns true for all nodes)

Example: .//para is short for self::node()/descendant-or-self::node()/child::para, selecting all para descendants of the current node.

.. abbreviates parent::node()

Page 55: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

XPath Abbreviations Part 2

@ abbreviates attribute::

Example: ../@grape selects the parent node's grape attribute; ../year selects context node's year sibling (compare UNIX and DOS relative path notation)

A missing axis abbreviates child::

Example: product abbreviates child::product

Page 56: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Sample Data for Playing with Axes<!DOCTYPE thing [<!ELEMENT thing (title,thing*)><!ATTLIST thing id ID #IMPLIED><!ELEMENT title (#PCDATA)>]><thing id="i1"><title>main thing</title>  <thing id="i1-1"><title>child 1-1</title>    <thing id="i1-1-1"><title>child 1-1-1</title></thing>    <thing id="i1-1-2"><title>child 1-1-2</title>      <thing id="i1-1-2-1"><title>child 1-1-2-1</title> </thing>      <thing id="i1-1-2-2"><title>child 1-1-2-2</title> </thing>    </thing>    <thing id="i1-1-3"><title>child 1-1-3</title></thing>  </thing>  <thing id="i1-2"><title>child 1-2</title>    <thing id="i1-2-1"><title>child 1-2-1</title></thing>    <thing id="i1-2-2"><title>child 1-2-2</title></thing>  </thing></thing>

Thing n will have children thing n-1, thing n-2, etc.

Page 57: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Xpath sample data: tree structure

i1-2-2

i1

i1-1

i1-1-1 i1-1-2

i1-1-2-1 i1-1-2-2

i1-1-3

i1-2

i1-2-1

Page 58: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

"following" axis: Whole Node List, First Node

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="thing[@id = 'i1-1']">    <xsl:for-each select="following::thing">       <xsl:value-of   select="attribute::id"/><xsl:text> </xsl:text>     </xsl:for-each>  </xsl:template> 

  <xsl:template match="@*|*">     <xsl:apply-templates select="@*|*"/>   </xsl:template> 

</xsl:stylesheet>

Output:i1-2 i1-2-1 i1-2-2

select value of "following::thing[1]" would only select i1-2.

Page 59: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

"preceding" axis: Whole Node List, "First" Node

<xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="thing[@id = 'i1-1-3']">    <xsl:for-each select="preceding::thing">       <xsl:value-of select="attribute::id"/><xsl:text> </xsl:text>     </xsl:for-each>  </xsl:template> 

  <xsl:template match="@*|*">     <xsl:apply-templates select="@*|*"/>   </xsl:template> 

</xsl:stylesheet>

Output:i1-1-1 i1-1-2 i1-1-2-1 i1-1-2-2

Page 60: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

“first” preceding element

select value of "preceding::thing[1]" would select i1-1-2-2, not i1-1-1. Same with ancestor axis.

select value of "preceding::thing[last()] would select i1-1-1.

Page 61: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Combining Node Sets with XPath Expression

  <xsl:template match="thing[@id = 'i1-1-2']">   <xsl:for-each    select="preceding-sibling::thing | following-sibling::thing">     <xsl:value-of select="attribute::id"/>      <xsl:text> </xsl:text>   </xsl:for-each></xsl:template>

Output:

i1-1-1 i1-1-3

Page 62: ©CSW Group Ltd 2005 Practical XSLT Bob DuCharme  bob@snee.com these slides:  1.0

Exercise 6ws2.xsl lists all the nodes that are children of i1-1. Experiment with the context node and different axes in the xsl:for-each element's select value to see what gets selected. Try predicates of [last()] and [n] (where n is a number like 1 or 2), and try combining node sets with the OR (|) operator. (A comment in ws2.xsl shows the structure of the input and lists the axes.)

After exploring for a bit, find the XPath expression that selects every node in the document that starts before i1-1-3 . (Hint: note the "|" in the second template rule's match pattern in ws2.xsl.)

axes: child, descendant, parent, ancestor, following-sibling, preceding-sibling, following, preceding, attribute, namespace, self, descendant-or-self, and ancestor-or-self.