表达式中的XPath相对路径

时间:2012-07-01 09:40:49

标签: xslt xpath

我在' group'节点。从中,我想找到这样的'项目'节点,有' id'属性等于当前的'组' node' ref_item_id'属性值。所以在我的情况下,通过进入' group'节点B,我想要' item'节点A作为输出。这有效:

<xsl:value-of select="preceding-sibling::item[@id='1']/@description"/>

但这并没有(什么也没有):

<xsl:value-of select="preceding-sibling::item[@id=@ref_item_id]/@description"/>

当我输入:

<xsl:value-of select="@ref_item_id"/>

我有&#39; 1&#39;结果。所以这个属性肯定是可访问的,但我无法从上面的XPath表达式中找到它的路径。我尝试了许多&#39; ../'组合,但无法使其发挥作用。

要测试的代码:http://www.xmlplayground.com/7l42fo

完整XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item description="A" id="1"/>
    <item description="C" id="2"/>
    <group description="B" ref_item_id="1"/>
</root>

完整XSLT:

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

<xsl:output method="text" indent="no"/>
  <xsl:template match="root">
     <xsl:for-each select="group">
        <xsl:value-of select="preceding-sibling::item[@id=@ref_item_id]/@description"/>
     </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

4 个答案:

答案 0 :(得分:8)

这与上下文有关。输入谓词后,上下文将成为谓词当前正在过滤的节点,不再与模板匹配的节点。

您有两个选择 - 使用变量缓存外部范围数据并在谓词中引用该变量

<xsl:variable name='ref_item_id' select='@ref_item_id' />
<xsl:value-of select="preceding-sibling::item[@id=$ref_item_id]/@description"/>

或使用current()功能

<xsl:value-of select="preceding-sibling::item[@id=current()/@ref_item_id]/@description"/>

答案 1 :(得分:1)

您的表达式搜索id属性与其自己的ref_item_id匹配的项。您需要在xsl:variable中捕获当前的ref_item_id,并在表达式中引用该xsl:variable。

答案 2 :(得分:0)

查看XML,如果我假设您有<item><group>作为兄弟姐妹和任何顺序。 然后,示例输入XML将如下所示。

 <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <item description="A" id="1"/>
        <item description="C" id="2"/>
        <group description="B" ref_item_id="1"/>
        <item description="D" id="1"/>
        <group description="E" ref_item_id="2"/>
    </root>

现在,如果目标是提取 id 与对应的<item> *节点ref_item_id *匹配的所有<group>个节点的描述。然后我们可以简单地仅循环这些<item>节点并获得它们的描述。

    <xsl:output method="text" indent="no"/>
      <xsl:template match="root">
         <xsl:for-each select="//item[(./@id=following-sibling::group/@ref_item_id) or (./@id=preceding-sibling::group/@ref_item_id)]">
            <xsl:value-of select="./@description"/>
         </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>

因为您说节点具有唯一ID,并且所有节点都放在节点之前。 我建议你使用以下XSL并在特定节点而不是节点上循环。

 <xsl:output method="text" indent="no"/>
      <xsl:template match="root">
         <xsl:for-each select="//item[./@id=following-sibling::group/@ref_item_id]">
            <xsl:value-of select="./@description"/>
         </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>

答案 3 :(得分:0)

使用xsl:key

的另一种可能的解决方案
<xsl:key name="kItemId" match="item" use="@id" />

<xsl:template match="root">
    <xsl:for-each select="group">
        <xsl:value-of select="key('kItemId', @ref_item_id)[1]/@description"/>
    </xsl:for-each>
</xsl:template>