xml - Obtaining Previous element in xslt 1.0 sort order, not dom order -


i have cd list entries not in specific sort order:

<?xml version="1.0" encoding="utf-8"?> <catalog>     <cd>         <title>empire burlesque</title>         <artist>bob dylan</artist>         <country>usa</country>         <company>columbia</company>         <price>10.90</price>         <year>1985</year>     </cd>     <cd>         <title>hide heart</title>         <artist>bonnie tyler</artist>         <country>uk</country>         <company>cbs records</company>         <price>9.90</price>         <year>1988</year>     </cd>     <cd>         <title>greatest hits</title>         <artist>dolly parton</artist>         <country>usa</country>         <company>rca</company>         <price>9.90</price>         <year>1982</year>     </cd>     <cd>         <title>still got blues</title>         <artist>gary moore</artist>         <country>uk</country>         <company>virgin records</company>         <price>10.20</price>         <year>1990</year>     </cd> </catalog> 

i want output list in html, grouped first letter of title. since eluded me how, first ran xml through simple sort:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform"     xmlns:xs="http://www.w3.org/2001/xmlschema"     exclude-result-prefixes="xs" version="1.0">     <xsl:output method="xml" indent="yes" />     <xsl:template match="catalog">         <catalog>             <xsl:apply-templates select="cd"><xsl:sort select="title"/></xsl:apply-templates>         </catalog>     </xsl:template>     <xsl:template match="cd"><xsl:copy-of select="."/></xsl:template> </xsl:stylesheet> 

which enables me use preceding-sibling check change in title letter. resulting sheet looks this:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform">   <xsl:template match="/">     <html>       <head>         <title> booklist books <xsl:value-of select="count(/catalog/cd)"/>         </title>         <style type="text/css">           table.main {width : 100%}           table.main td {padding : 2px; border-bottom : 1px solid gray}           th {text-align : left}           tr.header {background-color : #9acd32}           table.bar {border: 1px solid gray; background-color #cacaca}           table.bar td {border-left : 1px solid gray; padding : 4px; margin : 2px; font-size : x-large}           tr.firstbook {background-color : #cacaca}           td.firstbook {font-size : xx-large}           td.firstbook a.up {text-decoration: none; font-size : normal}         </style>       </head>       <body>         <xsl:apply-templates mode="header"/>         <xsl:apply-templates/>       </body>     </html>   </xsl:template>    <xsl:template match="catalog">     <table class="main">       <tr class="header">         <th> title </th>         <th> artist </th>         <th> country </th>         <th> company </th>         <th> price </th>         <th> year </th>       </tr>       <xsl:apply-templates select="cd">         <xsl:sort select="title"/>       </xsl:apply-templates>     </table>   </xsl:template>    <xsl:template match="cd">     <xsl:variable name="firstletter" select="substring(title,1,1)"/>     <xsl:variable name="oldletter" select="substring(preceding-sibling::*[1]/title,1,1)"/>      <xsl:if test="not($firstletter=$oldletter)">       <tr class="firstbook">         <td class="firstbook" colspan="5">           <a name="{$firstletter}">             <xsl:value-of select="$firstletter"/>           </a>         </td>         <td class="firstbook">           <a class="up" href="#">&#11014;</a>         </td>       </tr>     </xsl:if>      <tr>       <td>         <xsl:value-of select="title"/>       </td>       <td>         <xsl:value-of select="artist"/>       </td>       <td>         <xsl:value-of select="country"/>       </td>       <td>         <xsl:value-of select="company"/>       </td>       <td>         <xsl:value-of select="price"/>       </td>       <td>         <xsl:value-of select="year"/>       </td>     </tr>   </xsl:template>    <!-- header link handling -->   <xsl:template match="catalog" mode="header">     <table class="bar">       <tr>         <xsl:apply-templates mode="header"           select="cd[not(substring(title,1,1)=substring(preceding-sibling::*[1]/title,1,1))]">           <xsl:sort select="title"/>         </xsl:apply-templates>       </tr>     </table>   </xsl:template>    <xsl:template mode="header" match="cd">     <xsl:variable name="firstletter" select="substring(title,1,1)"/>     <td>       <a href="#{$firstletter}">         <xsl:value-of select="$firstletter"/>       </a>     </td>   </xsl:template>  </xsl:stylesheet> 

the key part comparison: not(substring(title,1,1)=substring(preceding-sibling::*[1]/title,1,1)) looks @ dom , not result of sort operation.

what i'm looking way in xslt-1.0 combine effect of 2 transformations, have 1 stylesheet, unsorted input list , result looks 2 stylesheets produce:

screenshot xslt result

how do that?

you can sort first variable (which in xslt result tree fragment), can use extension function exsl:node-set convert result tree fragment node-set processed further existing code.

so need 2 changes, template catalog has be

  <xsl:template match="catalog">     <table class="main">       <tr class="header">         <th> title </th>         <th> artist </th>         <th> country </th>         <th> company </th>         <th> price </th>         <th> year </th>       </tr>       <xsl:variable name="sorted-cds">         <xsl:for-each select="cd">           <xsl:sort select="title"/>           <xsl:copy-of select="."/>         </xsl:for-each>       </xsl:variable>       <xsl:apply-templates select="exsl:node-set($sorted-cds)/cd"/>     </table>   </xsl:template> 

and stylesheet root has declare exsl namespace:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"   xmlns:exsl="http://exslt.org/common"   exclude-result-prefixes="exsl"> 

note not xslt processors support exsl:node-set while support @ least similar extension function in proprietary namespace. assuming want use microsoft's msxml (for instance inside of internet explorer), need use <xsl:apply-templates select="ms:node-set($sorted-cds)/cd"/> ,

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"   xmlns:ms="urn:schemas-microsoft-com:xslt"   exclude-result-prefixes="ms"> 

Comments

Popular posts from this blog

Java 3D LWJGL collision -

spring - SubProtocolWebSocketHandler - No handlers -

methods - python can't use function in submodule -