只需应用排序查询并输出唯一的查询:
<xsl:variable name="states">
<xsl:value-of select="//state/*[contains(name(), 'current next')]/text()"/>
</xsl:variable>
<xsl:for-each select="str:tokenize($states)">
<xsl:sort select="text()"/>
<xsl:if test="preceding-sibling::*/text() != text()">
<xsl:element name="state"><xsl:value-of select="text()"/></xsl:element>
</xsl:if>
</xsl:for-each>
这是一个更新,其中包含一个使用 exsl 节点集的示例,用于不支持标记化的 xslt 实现:
<xsl:variable name="states">
<xsl:for-each select="//state/*[contains(name(), 'current next')]">
<xsl:element name="state">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:variable>
<xsl:for-each select="exsl:node-set($states)/*">
<xsl:sort select="text()"/>
<xsl:if test="preceding-sibling::*/text() != text()">
<xsl:element name="state"><xsl:value-of select="text()"/></xsl:element>
</xsl:if>
</xsl:for-each>
XSLT 是否可以跨多个级别对节点集进行排序也值得一看。我原本预计这不会起作用,但现在不太确定,因为我想知道 libxsl 是否会首先展平节点集。如果没有,则前面的兄弟:: 引用将失败,因为它只会引用直接节点,而不是选择中的一个:
<xsl:for-each select="//state/*[contains(name(), 'current next')]">
<xsl:sort select="text()"/>
<xsl:if test="preceding-sibling::*/text() != text()">
<xsl:element name="state"><xsl:value-of select="text()"/></xsl:element>
</xsl:if>
</xsl:for-each>