如何解决xsl:for-each与xsl:sort排序列表重复生成的问题
outputclass="sort"的<dl>列表时重复生成内容 尝试对带有outputclass="sort"属性的<dl>中的<dlentry>列表进行排序,已知<xsl:sort>需嵌套在<xsl:for-each>中。编写XSLT后虽能生成排序后的PDF文本,但会随每个<dlentry>重复生成整个排序列表,需要实现仅生成一次的排序列表。
相关XML代码
<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>
现有XSLT代码
<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>
当前错误输出
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.
解决方案
问题原因
现有XSLT的<xsl:for-each>写在单个<dlentry>的模板里,每处理一个<dlentry>就会遍历一次所有<dlentry>并输出排序后的列表,导致内容重复生成。
修正后的XSLT代码
把排序逻辑移到<dl>元素的模板中,针对带outputclass="sort"的<dl>,直接遍历并排序其下所有<dlentry>,确保只执行一次排序输出:
<!-- 匹配带outputclass="sort"的dl元素 --> <xsl:template match="dl[@outputclass='sort']"> <!-- 遍历当前dl下的所有dlentry并排序 --> <xsl:for-each select="dlentry"> <xsl:sort select="normalize-space(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> <!-- 保留普通dlentry的处理模板(针对不带排序属性的dl) --> <xsl:template match="dlentry"> <!-- 此处编写普通dlentry的输出逻辑 --> </xsl:template>
关键说明
- 将排序逻辑绑定到
<dl>模板,确保整个排序列表只生成一次。 normalize-space(dt)能清除<dt>文本前后的冗余空格,避免空格干扰排序结果。- 区分带排序属性和普通
<dl>的处理逻辑,避免模板冲突。
内容的提问来源于stack exchange,提问作者Matthew Stern

