1 / 62

Practical XSLT Bob DuCharme snee/bob bob@snee these slides: snee/xml 1.0

Practical XSLT Bob DuCharme www.snee.com/bob bob@snee.com these slides: www.snee.com/xml 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

kathy
Download Presentation

Practical XSLT Bob DuCharme snee/bob bob@snee these slides: snee/xml 1.0

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Practical XSLT Bob DuCharme www.snee.com/bob bob@snee.com these slides: www.snee.com/xml 1.0

  2. 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

  3. 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."

  4. Documents, trees From 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?

  5. 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"

  6. Running it my saxon shell script: #! /bin/sh java 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.

  7. 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>

  8. 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

  9. Doing it yourself: sample data wine.xml for demonstrations orders.xml for exercises

  10. 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>

  11. 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>

  12. orders.xml (part 1 of 5) <!ELEMENT orders (order+)>         <!ELEMENT order  (quantity, pricePerItem, orderDate, warrantee?,billingAddr,shippingAddr?,productPic?)>

  13. 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>

  14. 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>

  15. 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>

  16. 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>

  17. 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.

  18. 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"

  19. 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.)

  20. 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>

  21. 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>

  22. 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.

  23. Renaming Attributes   <wine grape="{@grape}"> outputs this:   <wine grape="chardonnay"> And this   <wine varietal="{@grape}"> will output this:   <wine varietal="chardonnay">

  24. Converting Attributes to Elements & Vice Versa   <xsl:template match="wine">     <winevintage="{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>

  25. 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)}">

  26. What We've Covered So Far deleting elements renaming elements reordering elements deleting attributes renaming attributes converting elements to attributes converting attributes to elements

  27. 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.)

  28. 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>

  29. 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

  30. 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>

  31. Controlling White Space, Part 2 Output of previous stylesheet with wine.xml: Wine: BenzigerCarneros1997 Wine: DuckpondMerit Selection1996 Wine: Lindeman'sBin 651998

  32. 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>

  33. Controlling White Space, Part 2b Output of previous stylesheet with wine.xml: Wine: Benziger Carneros 1997 Wine: Duckpond Merit Selection 1996 Wine: Lindeman's Bin 65 1998

  34. 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,20000623 4,9.99,20000621 1,300.00,20000625 2,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.

  35. 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>

  36. xsl:if in Action Prceding 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>

  37. 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>

  38. 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>

  39. 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>

  40. 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>

  41. 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>

  42. 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;).

  43. 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

  44. 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

  45. 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>

  46. Addressing Parts of a Document /poem/title /poem/stanza/verse / /poem/* .. ../title

  47. 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>

  48. XPath: Location Steps From 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.

  49. 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">

More Related