XSLT Tips you don't learn at w3schools

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jkmyoung
    Recognized Expert Top Contributor
    • Mar 2006
    • 2057

    XSLT Tips you don't learn at w3schools

    Here's a short list of useful xslt general tricks that aren't taught at w3schools.
    1. Attribute Value Template
      Official W3C explanation and example

      This is when you want to put dynamic values in the attribute of an element. Instead of using the <xsl:attribut e> element, you can simply place the xpath in the attribute itself.

      The most common usage of this is in creating hyperlinks.

      Example:
      Source XML
      [code=xml]
      <item>
      <link>www.googl e.ca</link>
      <desc>Search Engine</desc>
      </item>
      <item>
      <link>http://www.mytelus.com/ncp_news/</link>
      <desc>news</desc>
      </item>
      [/code]
      Old XSLT:
      [code=xml]
      <xsl:template match="item">
      <a>
      <xsl:attribut e name="href">
      <xsl:value-of select="link"/>
      </xsl:attribute>
      <xsl:value-of select="desc"/>
      </a>
      </xsl:template>
      [/code]
      New XSLT:
      [code=xml]
      <xsl:template match="item">
      <a href="{link}">< xsl:value-of select="desc"/></a>
      </xsl:template>
      [/code]
      Result:
      [code=html]
      <a href="www.googl e.ca">Search Engine</a>
      <a href="http://www.mytelus.com/ncp_news/">news</a>
      [/code]
      Now isn't that much nicer?

    2. Muenchian Grouping
      Jeni's XSLT Pages: Grouping Using the Muenchian Method
      This is a way of grouping together elements by a particular value. It's especially useful in interpreting the data generated by database dumps, since many fields are repeated. This is only needed for xslt 1.0, as 2.0 has built in grouping.

      Example:
      [code=xml]
      <book>
      <title>How to Win Friends and Influence People</title>
      <author>Dale Carnegie</author>
      </book>
      <book>
      <title>Harry Potter and the Philosopher's Stone</title>
      <author>J.K. Rowling</author>
      </book>
      <book>
      <title>Harry Potter and the Deathly Hallows /title>
      <author>J.K. Rowling</author>
      </book>
      [/code]
      Here we want to group the books by author, so we have xslt code like so:
      [code=xml]
      <xsl:key name="bookByAut hor" match="book" use="author">

      <xsl:for-each select="//book[count(.|key('bo okByAuthor', author)[1]) = 1]">
      <author>
      <name><xsl:valu e-of select="author"/></name>
      <xsl:for-each select="key('bo okByAuthor', author)">
      <book><xsl:valu e-of select="title"/></book>
      </xsl:for-each>
      </author>
      [/code]
      Output:
      [code=xml]
      <author>
      <name>Dale Carnegie</name>
      <book>How to Win Friends and Influence People</book>
      </author>
      <author>
      <name>J.K. Rowling</name>
      <book>Harry Potter and the Philosopher's Stone</book>
      <book>Harry Potter and the Deathly Hallows</book>
      </author>
      [/code]
    3. Axes
      A lot of the time you need to select particular nodes, but don't have an easy way of selecting them. Solution? Use an axis! The most important ones are as follows:
      1. following-sibling:: and preceding-sibling::
      2. descendant:: (also written as .//)
      3. ancestor::
      See the link for a list of all the axes.
      XSLT 1.0: axes

      Here's a contrived example:
      [code=xml]
      <stock symbol="SYM">
      <price day="11022008" close="156">
      <price day="12022008" close="135">
      <price day="13022008" close="158">
      <price day="14022008" close="158">
      <price day="15022008" close="146">
      </stock>
      [/code]
      In order to find the change from the day before we do the following:
      [code=xml]
      <xsl:template match="stock">
      <table>
      <tr>
      <th>day</th>
      <th>close</th>
      <th>change</th>
      </tr>
      <xsl:apply-templates/>
      </table>
      </xsl:template>
      <xsl:template match="price">
      <tr>
      <td><xsl:valu e-of select="@day"></td>
      <td><xsl:valu e-of select="@close" ></td>
      <td>
      <xsl:choose>
      <xsl:when test="position( ) = 1">-</xsl:when>
      <xsl:otherwis e>
      <xsl:value-of select="@close - preceding-sibling::price[1]/@close"/>
      </xsl:otherwise>
      </xsl:choose>
      </td>
      </tr>
      [/code]
      So if the day we're checking isn't the first day, we subtract the value of the preceding price from this day's to see the change. Note the use of [1] after price. This tells the processor we only want the first price node right before the one we're working on. The nodes in axis have position based on the axis.

      Result:
      [code=html]
      <table>
      <tr><th>day</th><th>close</th><th>change</th></tr>
      <tr><td>1102200 8</td><td>156</td><td>-</td></tr>
      <tr><td>1202200 8</td><td>135</td><td>-21</td></tr>
      <tr><td>1302200 8</td><td>158</td><td>23</td></tr>
      <tr><td>1402200 8</td><td>158</td><td>0</td></tr>
      <tr><td>1502200 8</td><td>146</td><td>-12</td></tr>
      </table>
      [/code]
    4. Namespaces
      Many times there are complaints that someone can't select an element because of a namespace prefix at the beginning of an element.

      [code=xml]
      <atta:root xmlns:atta="www .atta.com">
      <atta:table>
      <atta:row>
      <atta:city>Vanc ouver</atta:city>
      <atta:hnde>24 </atta:hnde>
      </atta:row>
      <atta:row>
      <atta:city>Mont real</atta:city>
      <atta:hnde>36 </atta:hnde>
      </atta:row>
      </atta:table>
      </atta>
      [/code]
      To access the 24 under Vancouver, the xpath could be something like:
      "/atta:root/atta:table/atta:row[atta:city = 'Vancouver']/atta:hnde"


    5. Honourable mention: the node-set function.
      Since this isn't strictly xslt, but relies on extension functions, I haven't included it. This treats xsl variables as node sets (automatic in XSLT 2.0). eg. either exsl:node-set() xmlns:exslt="ht tp://exslt.org/common" OR
      msxsl:node-set() xmlns:msxsl="ur n:schemas-microsoft-com:xslt"
      EXSLT - exsl:node-set
      Support for the msxsl:node-set() Function


    General Reference List:
    1. XSLT Tutorial
    2. XSLT Reference
      Good reference for XSLT 1.0. In particular, axes.
    3. XSLT Reference
      XSL elements
      XPath, XQuery, and XSLT Function Reference
      XPath 2.0 functions.


    If you have any other tips which you should be added here, feel free to respond.
  • Azat Razetdinov
    New Member
    • Aug 2008
    • 1

    #2
    Don't mislead your readers: descendant:: is not equivalent to //
    See NOTE at http://www.w3.org/TR/xpath#path-abbrev

    Comment

    • jkmyoung
      Recognized Expert Top Contributor
      • Mar 2006
      • 2057

      #3
      Thanks, I've changed it to .// to avoid confusion.

      Comment

      Working...