在xsl:foreach select语句中使用xsl:variable

时间:2010-03-15 17:12:26

标签: xslt variables foreach

我正在尝试使用xsl:foreach迭代xml文档,但我需要select =“”是动态的,所以我使用变量作为源。这是我尝试过的:

...

<xsl:template name="SetDataPath">
  <xsl:param name="Type" />

  <xsl:variable name="Path_1">/Rating/Path1/*</xsl:variable>
  <xsl:variable name="Path_2">/Rating/Path2/*</xsl:variable>

  <xsl:if test="$Type='1'">
    <xsl:value-of select="$Path_1"/>
  </xsl:if>

  <xsl:if test="$Type='2'">
    <xsl:value-of select="$Path_2"/>
  </xsl:if>
<xsl:template>

...

    <!-- Set Data Path according to Type -->
  <xsl:variable name="DataPath">
    <xsl:call-template name="SetDataPath">
      <xsl:with-param name="Type" select="/Rating/Type" />
    </xsl:call-template> 
  </xsl:variable>

...

<xsl:for-each select="$DataPath">

...

foreach抛出错误声明:“XslTransformException - 要在路径表达式中使用结果树片段,首先使用msxsl:node-set()函数将其转换为节点集。”

当我使用msxsl:node-set()函数时,我的结果是空白的。

我知道我将$ DataPath设置为一个字符串,但是node-set()函数不应该从它创建一个节点集吗?我错过了什么吗?当我不使用变量时:

<xsl:for-each select="/Rating/Path1/*">

我得到了正确的结果。

这是我正在使用的XML数据文件:

<Rating>
    <Type>1</Type>
    <Path1>
       <sarah>
          <dob>1-3-86</dob>
          <user>Sarah</user>
       </sarah>
       <joe>
          <dob>11-12-85</dob>
          <user>Joe</user>
       </joe>
    </Path1>
    <Path2>
       <jeff>
          <dob>11-3-84</dob>
          <user>Jeff</user>
       </jeff>
       <shawn>
          <dob>3-5-81</dob>
          <user>Shawn</user>
       </shawn>
    </Path2>
</Rating>

我的问题很简单,你如何在两条不同的路径上运行foreach?

3 个答案:

答案 0 :(得分:3)

试试这个:

   <xsl:for-each select="/Rating[Type='1']/Path1/*
                         |
                          /Rating[Type='2']/Path2/*">

答案 1 :(得分:3)

标准XSLT 1.0不支持对xpath进行动态评估。但是,您可以通过重构解决方案以调用命名模板,将要处理的节点集作为参数传递来实现所需结果:

<xsl:variable name="Type" select="/Rating/Type"/>
<xsl:choose>
    <xsl:when test="$Type='1'">
        <xsl:call-template name="DoStuff">
            <xsl:with-param name="Input" select="/Rating/Path1/*"/>
        </xsl:call-template>
    </xsl:when>
    <xsl:when test="$Type='2'">
        <xsl:call-template name="DoStuff">
            <xsl:with-param name="Input" select="/Rating/Path2/*"/>
        </xsl:call-template>
    </xsl:when>
</xsl:choose>

...

<xsl:template name="DoStuff">
    <xsl:param name="Input"/>
    <xsl:for-each select="$Input">
        <!-- Do stuff with input -->
    </xsl:for-each>
</xsl:template>

答案 2 :(得分:0)

您提到的node-set()函数可以将结果树片段转换为节点集,这是正确的。但是:您的XSLT不会生成结果树片段。

您的模板SetDataPath会生成一个字符串,然后将其存储到变量$DataPath中。执行<xsl:for-each select="$DataPath">时,XSLT处理器会忽略DataPath不包含节点集但只包含字符串的事实。

您的整个样式表似乎都围绕着动态选择/评估XPath表达式的想法。放下这个想法,这既不可能也不必要。

显示您的XML输入并指定您想要进行的转换,我可以尝试向您展示一种方法。