wyattburp86
wyattburp86

Reputation: 81

XSLT Sorting Issue w/ String Containing Text and Numbers That Are Single and Double Digit

I am looking for assistance with addressing an issue I'm encountering with a XSLT stylesheet I'm applying to a basic XML file, which will output basic HTML for a portal we're building. Specifically, I am trying to apply a <xslt:sort select="" /> to the content I'm outputting based on a title element, which includes text and single and double digit numbers and the sort element puts double digit numbers before single digits (see example below):

Example XML source file:

    <?xml version="1.0" encoding="UTF-8"?>
    <TitleList>
    <book>
        <title>Book 1: Part 3. Buying and Selling Stuff</title>
        <author>Jon Doe</author>
        <PubDate>2010</PubDate>
     </book>
     <book>
      <title>Book 1: Part 7. Making Stuff</title>
      <author>Jane Doe</author>
      <PubDate>2012</PubDate>
      </book>
      <book>
        <title>Book 1: Part 8. The Art of Creating Things </title>
        <author>Jon Doe</author>
        <PubDate>2013</PubDate>
      </book>
     <book>
      <title>Book 1: Part 10. Stuff Happens</title>
      <author>Jane Doe</author>
      <PubDate>2014</PubDate>
     </book>
     </TitleList>

Example XSLT:

     <?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="html" encoding="UTF-8" />
<xsl:template match="/">
    <html>
        <head></head>
        <body>
           <div id="titleList">
               <table>
                   <tr>
                       <th>Title List</th>
                   </tr>
                   <tr>
                       <xsl:call-template name="retrieveTitles"></xsl:call-template>
                   </tr>
               </table>
           </div> 
        </body>
    </html>
</xsl:template>
<xsl:template name="retrieveTitles">
    <xsl:for-each select="TitleList/book">
     <xsl:sort select="title" /> 
     <tr>   
      <td>  
        <xsl:value-of select="title"/>
      </td>
        <td>
            <xsl:value-of select="author" />
        </td>
        <td>
            <xsl:value-of select="PubDate"/>
        </td>
     </tr>   
    </xsl:for-each>
  </xsl:template>
  </xsl:stylesheet>

Resulting HTML with titles out of order:

    <html>
     <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     </head>
     <body>
     <div id="titleList">
     <table>
        <tr>
           <th>Title List</th>
        </tr>
        <tr>
           <tr>
              <td>Book 1: Part 10. Stuff Happens</td>
              <td>Jane Doe</td>
              <td>2014</td>
           </tr>
           <tr>
              <td>Book 1: Part 3. Buying and Selling Stuff</td>
              <td>Jon Doe</td>
              <td>2010</td>
           </tr>
           <tr>
              <td>Book 1: Part 7. Making Stuff</td>
              <td>Jane Doe</td>
              <td>2012</td>
           </tr>
           <tr>
              <td>Book 1: Part 8. The Art of Creating Things </td>
              <td>Jon Doe</td>
              <td>2013</td>
           </tr>
        </tr>
     </table>
  </div>
    </body>
   </html>  

How do I get configure the ordering element for the XSLT script in order to ensure that the titles are ordered consecutively when the jump is made from single digit numbers to double digit numbers? Thanks for your time!

Regards,

wyattburp86

Upvotes: 0

Views: 349

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116992

To minimize the example to the problem at hand, consider the following:

<xsl:template match="/TitleList">
    <table>
        <xsl:apply-templates select="book">
            <xsl:sort select="substring-before(substring-after(title, 'Book ' ), ':')" data-type="number" order="ascending"/>
            <xsl:sort select="substring-before(substring-after(title, 'Part ' ), '.')" data-type="number" order="ascending"/>
        </xsl:apply-templates>
    </table>
</xsl:template>

<xsl:template match="book">
    <tr>
        <td>  
            <xsl:value-of select="title"/>
        </td>
    </tr>       
</xsl:template>

Upvotes: 1

Related Questions