XSL for-each 创建可迭代节点列表



我需要多次按照语言字段的排序顺序遍历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-ofcopy-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() 函数将变量中的结果树片段转换为节点集。

相关内容

最新更新