我需要多次按照语言字段的排序顺序遍历XML文件的元素。我尝试的是获取可迭代的语言列表,如下所示:
<xsl:variable name="languages">
<xsl:for-each select="elem/FIELD[@NAME='language']">
<xsl:sort select="."/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
虽然我可以用
<xsl:value-of select="$languages"/>
排序有效,我无法像迭代一样迭代
<xsl:for-each select="$langauges">...</xsl:for-each>
因为 XSL 处理器抱怨选择表达式的计算结果不是节点集。
编辑:不确定这是否重要,但我有
<xsl:output encoding="UTF-8"
method="xml"
media-type="text/xml"
indent="yes" />
我必须在循环中插入什么才能将结果放入节点集中?这可能吗?
鉴于你说
XSL 处理器抱怨选择表达式的计算结果不是节点集。
我假设您使用的是 XSLT 1.0 而不是 2.0。 在 XSLT 1.0 中,当您声明一个包含内容而不是select
属性的变量时,生成的变量包含称为"结果树片段"而不是节点集的东西。 可以将value-of
和copy-of
应用于 RTF 以将其发送到输出,但无法使用 XPath 表达式导航到该 RTF。
大多数 XSLT 处理器都提供某种扩展函数来将 RTF 转换为实际节点集 - Microsoft 处理器为 msxsl,大多数其他处理器为 exslt。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl">
<!-- .... -->
<xsl:variable name="languagesRTF">
<xsl:for-each select="elem/FIELD[@NAME='language']">
<xsl:sort select="."/>
<lang><xsl:value-of select="."/></lang>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="languages" select="exsl:node-set($languagesRTF)/lang" />
在 XSLT 2.0 中,结果树片段和节点集之间没有区别 - 它们都被视为序列 - 因此您不需要该版本中的扩展函数。
XSLT 1.0 允许您按排序顺序处理节点集,但它不允许您将排序序列保存在变量中(数据模型只有集,没有序列)。在 1.0 中保存排序数据的唯一方法是构造一个新树,其中包含不同顺序的原始元素的副本,然后使用 node-set() 扩展使此树可处理。
这在 XSLT 2.0中发生了变化,XSLT 2.0 具有基于序列的数据模型。在 2.0 中,您可以将排序的节点序列保存在变量中,而无需将节点复制到新树中。
尝试以下操作:
声明变量:
<xsl:variable name="languages">
<xsl:for-each select="elem/FIELD[@NAME='language']">
<xsl:sort select="."/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
并循环:
<xsl:for-each select="$languages/*">
您需要使用 EXSLT node-set() 函数将变量中的结果树片段转换为节点集。