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

时间:2014-04-03 10:51:48

标签: xslt

我需要多次按语言字段的排序顺序迭代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处理器抱怨select表达式没有计算到节点集。

编辑:不确定这是否重要,但我有

<xsl:output encoding="UTF-8" 
          method="xml" 
          media-type="text/xml" 
          indent="yes" />

我需要在循环中插入什么才能将结果导入节点集?这有可能吗?

4 个答案:

答案 0 :(得分:1)

鉴于你这么说

  

XSL处理器抱怨select表达式没有计算到节点集。

我假设您使用的是XSLT 1.0而不是2.0。在XSLT 1.0中,当您使用内容而不是select属性声明变量时,结果变量包含称为“结果树片段”而不是节点集的内容。您可以将value-ofcopy-of应用于RTF以将其发送到输出,但无法使用XPath表达式导航到它。

大多数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中,结果树片段和节点集之间没有区别 - 它们都被视为序列 - 因此您不需要该版本中的扩展函数。

答案 1 :(得分: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/*">

答案 2 :(得分:0)

您需要使用EXSLT node-set() function将变量中的结果树片段转换为节点集。

答案 3 :(得分:0)

XSLT 1.0允许您按排序顺序处理节点集,但它不允许您将已排序的序列保存在变量中(数据模型只有集合,而不是序列)。在1.0中保存排序数据的唯一方法是构造一个包含不同顺序的原始元素副本的新树,然后使用node-set()扩展来使该树可处理。

XSLT 2.0中的这种变化,它具有基于序列的数据模型。在2.0中,您可以在变量中保存已排序的节点序列,而无需将节点复制到新树中。