Search code examples
xsltsaxon

XSL Sort on Autogenerated and User entered Titles


I have a document that contains paragraphs with a mixture of user authored titles and autogenerated titles that I need to have sorted alphabetically for a table of contents.

The data looks like

<theory><text>Stuff goes here</text></theory>
<general><text>More stuff</text></general>
<paragraph><title>First user title</title><text>Lots of stuff</text>   
   <subparagraph><title>Subordinate Paragraph</title><text>The last stuff.</text></subparagraph>
</paragraph>
<paragraph><title>Last user title</title><text>Just a little stuff</text>
</paragraph>

The expected output is

3. First User Title............
2. General Information.........
4. Last User Title.............
3.1 Subordinate Paragraph......
1. Theory of Operation.........

I can't figure out how to get it to sort on the literal values for some paragraphs and the titles when they exist. Right now I have:

<xsl:for-each select="paragraph|theory|general|paragraph/subparagraph">
   <xsl:sort select="name()"/>
   <xsl:sort select="title"/>
   <xsl:apply-templates select="." mode="TOC"/>
</xsl:for-each>

but it outputs as:

2. General................
3. First User Title.......
4. Last User Title........
1. Theory of Operation....
3.1 Subordinate Paragraph.

Solution

  • You could handle this in a more general way by using template rules to compute the sort key:

    <xsl:for-each select="paragraph,theory,general">
       <xsl:sort>
          <xsl:apply-templates select="." mode="sort-key"/>
       </xsl:sort>
       <xsl:apply-templates select="." mode="TOC"/>
    </xsl:for-each>
    
    <xsl:template match="paragraph" mode="sort-key" as="xs:string">
      <xsl:sequence select="string(title)"/>
    </xsl:template>
    
    <xsl:template match="theory|general" mode="sort-key" as="xs:string">
      <xsl:sequence select="string(text)"/>
    </xsl:template>