sortingxsltforeachapache-fopdita-ot

xsl:for-each and xsl:sort repeat the same list


I'm trying to sort a list of items in a <dl>. The XML is tagged like this. I assigned "sort" to the outputclass attribute to indicate this specific <dl> is to be sorted.

<dl outputclass="sort"> 
        <dlentry> 
          <dt> Ant 
          </dt> 
          <dd> 
             <p> A Java-based software tool for automating builds. 
             </p> 
          </dd> 
        </dlentry> 
        <dlentry> 
          <dt> Node 
          </dt> 
          <dd> 
             <p> A level in a document hierarchy. 
             </p> 
          </dd> 
        </dlentry>
        <dlentry> 
          <dt> DITA (Darwin Information Typing Architecture) 
          </dt> 
          <dd> 
             <p> An XML-based authoring model based on inheritance and specialization. 
             </p> 
          </dd> 
        </dlentry> 
....
</dl>

I know that <xsl:sort> needs to be nested in a <xsl:for-each>. After several attempts, this is the XSLT that has consistently generated sorted text for a PDF:

<xsl:for-each select="../dlentry">
   <xsl:sort select="dt"/>
   <fo:block xsl:use-attribute-sets="dlentry.dd__content" margin-left="0pt">
      <xsl:apply-templates select="dt"/>
      <xsl:apply-templates select="dd"/>
   </fo:block>
</xsl:for-each>

The problem is that it repeats the sorted list for each <dlentry> in my list:

Ant
A Java-based software tool for automating builds.
DITA (Darwin Information Typing Architecture)
An XML-based authoring model based on inheritance and specialization.
Node
A level in a document hierarchy.
Ant
A Java-based software tool for automating builds.
DITA (Darwin Information Typing Architecture)
An XML-based authoring model based on inheritance and specialization.
Node
A level in a document hierarchy.
Ant
A Java-based software tool for automating builds.
DITA (Darwin Information Typing Architecture)
An XML-based authoring model based on inheritance and specialization.
Node
A level in a document hierarchy.

How do I get a sorted list, and only have it generated once instead of for each <dlentry>? Thank you for your help.


Solution

  • You are only showing us a part of your code, so we can only guess.

    Still, your instruction:

    <xsl:for-each select="../dlentry">
    

    can work only if it is called from the context of dlentry, and if so called, will execute the code for all dlentry elements, not only the current one, but also all its siblings.

    Apparently you are doing this for every dlentry, so in the end the code is executed 3x3 times.

    Instead you should be doing something like:

    <xsl:template match="dl">
        <xsl:for-each select="dlentry">
           <xsl:sort select="dt"/>
           <fo:block xsl:use-attribute-sets="dlentry.dd__content" margin-left="0pt">
              <xsl:apply-templates select="dt"/>
              <xsl:apply-templates select="dd"/>
           </fo:block>
        </xsl:for-each>
    </xsl:template>