使用 'for-each' 处理参数堆栈在 XSL 中? [英] Processing stacks of parameters using 'for-each' in XSL?

查看:17
本文介绍了使用 'for-each' 处理参数堆栈在 XSL 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如

<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: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/组织[@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:模板><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:模板></xsl:stylesheet>

然而,for-each 循环只填充模板 'test' 中堆栈的顶部变量 - 即 xsl:value-of select="$memberId"/> 有效但 <xsl:value-of select="$memberRef"/> 没有.

任何有关如何解决此问题的想法将不胜感激.

解决方案

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

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

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

第一个参数 memberId 起作用的原因是因为您向其传递了一个显式值,因此将在 select 中使用它而不是默认值属性.所有其他参数都将不起作用,因为它们将使用默认值.

解决方案可能是让所有参数都具有绝对表达式,这意味着在它们前面加上 /.

/ 代表顶级文档节点,因此 xpath 表达式将与其相关,而不是当前节点.

请注意,在这种情况下,您可能会考虑使用 xsl:key 来查找此类元素.例如

然后param语句变成这样:

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

顺便说一句,两个具有相同优先级的模板匹配同一事物被认为是错误的.因此,您的第一个命名"模板可能应该删除 ma​​tch 属性.即代替 ,这样做

 

I have a series of param elements inside a template that rely upon each other (i.e. each subsequent param uses the value of the previous one as part of it's 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"/>

etc. etc.

The stack of params works perfectly on a single run through. However, when I use a for-each loop to call the template and pass the for-each value to it using xsl:with-param, only the top param is processed - the value is NOT passed to the next the parameter.

Here's my full 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>

However, the for-each loop only populates the top variable of the stack in template 'test' - i.e. xsl:value-of select="$memberId"/> works but <xsl:value-of select="$memberRef"/> does not.

Any ideas on how to work around this issue would be much appreciated.

解决方案

The problem you are having is one of context; where you are currently positioned in the XML. Consider your xsl:for-each loop

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

You are looping over @value attributes, meaning within the loop you are positioned on a @value attribute, and consequently any relative xpath expressions will be relative to that. When you do your xsl:call-template you will still be positioned on the @value attribute, and so all the xpath expressions in the xsl:param statements will be relative to that.

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

That is to say, the select statement is looking for a PLMXML element underneath the current @value, which clearly does not exist!

The reason the first parameter, memberId, works is because you pass an explicit value to that, and so that will be used instead of the default value in the select attribute. All the other parameters will not work because they will use the default value.

The solution is, probably, is to make all your parameters have absolute expressions, which means prefixing them with a /.

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

The / represents the top level document node, and so the xpath expression will then be relative to that, and not the current node.

Note, you might consider using xsl:key in this instance to look-up such elements. For example

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

Then the param statement becomes this:

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

As an aside, it is considered an error to have two templates of equal priority matching the same thing. So, your first 'named' template should probably have the match attribute removed. i.e. Instead of <xsl:template match="/" name="test">, do this

 <xsl:template name="test">

这篇关于使用 &amp;#39;for-each&amp;#39; 处理参数堆栈在 XSL 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆