在XSL中使用'for-each'处理参数堆栈?

时间:2014-04-01 11:22:49

标签: xml xslt xpath param

我在模板中有一系列相互依赖的param元素(即每个后续param使用前一个param的值作为它的一部分< XPath)

e.g。

<xsl:param name="input1" select="path/node/@value"/>

<xsl:param name="input2" select="path/anothernode[@value=$input1]/anothervalue"/>

<xsl:param name="input3" select="path/thirdnode[@value=$input2]/@endvalue"/>

等。等

一堆参数在一次运行中完美运行。但是,当我使用for-each循环调用模板并使用xsl:with-param将for-each值传递给它时,只处理顶部参数 - 该值不会传递给下一个参数。

这是我的完整xsl:

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/" name="test">

  <xsl:param name="memberId"    
    select="PLMXML/Organisation/UserData/UserValue/UserList/Item/@value"/>
  <xsl:param name="memberRef" 
    select="PLMXML/OrganisationMember[@id=$memberId]/@memberRef"/>  
  <xsl:param name="memberRef2"    
    select="translate($memberRef,'#','')"/> 
  <xsl:param name="userId"    
    select="PLMXML/User[@id=$memberRef2]/@personRef"/>
  <xsl:param name="userId2"    
    select="translate($userId,'#','')"/>    
  <xsl:param name="personName"    
    select="PLMXML/Person[@id=$userId2]/@lastName"/>
  <xsl:param name="groupRef"    
    select="PLMXML/User[@id=$memberRef2]/UserData/UserValue/@dataRef"/>
  <xsl:param name="groupRef2"    
    select="translate($groupRef,'#','')"/>
  <xsl:param name="groupName"    
    select="PLMXML/Organisation[@id=$groupRef2]/@name"/>
  <xsl:param name="roleRef"    
    select="PLMXML/Organisation[@id=$groupRef2]/UserData/UserValue/@dataRef"/>
  <xsl:param name="roleRef2"    
    select="translate($roleRef,'#','')"/>
  <xsl:param name="roleName"    
    select="PLMXML/Role[@id=$roleRef2]/@name"/>

  <xsl:value-of select="$memberId"/>

  <xsl:value-of select="$memberRef"/>

  <xsl:value-of select="$personName"/>  
  <xsl:value-of select="$groupName"/>
  <xsl:value-of select="$roleName"/>

</xsl:template>

<xsl:template match="/">

  <xsl:for-each select="PLMXML/Organisation/UserData/UserValue/UserList/Item/@value">

    <xsl:call-template name="test">

      <xsl:with-param name="memberId" select="."/>

    </xsl:call-template>

  </xsl:for-each>

</xsl:template>


</xsl:stylesheet>

但是,for-each循环只在模板中填充堆栈的顶部变量&#39; test&#39; - 即xsl:value-of select="$memberId"/>有效,但<xsl:value-of select="$memberRef"/>没有。

非常感谢有关如何解决此问题的任何想法。

1 个答案:

答案 0 :(得分:1)

你遇到的问题是上下文之一;您当前在XML中的位置。考虑一下 xsl:for-each 循环

<xsl:for-each select="PLMXML/Organisation/UserData/UserValue/UserList/Item/@value">

您正在循环 @value 属性,这意味着您在循环中位于 @value 属性上,因此任何相对xpath表达式都将相对于该属性。当您执行 xsl:call-template 时,您仍将位于 @value 属性上,因此 xsl:param中的所有xpath表达式陈述将与此相关。

<xsl:param name="memberRef" 
     select="PLMXML/OrganisationMember[@id=$memberId]/@memberRef"/>  

也就是说, select 语句正在当前 @value 下面寻找 PLMXML 元素,这显然不存在!

第一个参数 memberId 的作用原因是您将显式值传递给它,因此将使用选择中的默认值属性。所有其他参数都不起作用,因为它们将使用默认值。

解决方案可能是使所有参数都具有绝对表达式,这意味着为它们添加/前缀。

<xsl:param name="memberRef" 
     select="/PLMXML/OrganisationMember[@id=$memberId]/@memberRef"/> 

/表示顶级文档节点,因此xpath表达式将相对于该节点,而不是当前节点。

注意,您可以考虑在此实例中使用 xsl:key 来查找此类元素。例如

<xsl:key name="OrganisationMember" match="OrganisationMember" use="@id" />

然后param语句变为:

<xsl:param name="memberRef" select="key('OrganisationMember', $memberId)/@memberRef"/> 

顺便说一句,将两个具有相同优先级的模板匹配相同的东西被视为错误。所以,你的第一个名字&#39;模板应该删除匹配属性。即代替<xsl:template match="/" name="test">,执行此操作

 <xsl:template name="test">