如何根据与我正在搜索的树中的属性同名的属性,在循环中获取带有xpath的XML节点?

时间:2010-10-05 12:45:58

标签: xslt xpath

我真的不能更好地表达,所以我会选择一个例子:

XML:

<root>
  <foo>
    <bar id="1">sdf</bar>
    <bar id="2">sdooo</bar
  </foo>
  <feng>
    <heppa id="4">hihi</heppa>
    <heppa id="2">sseeapeea</heppa>
    <heppa id="1">....</heppa>
  </feng>
</root>

XSLT:

<xsl:for-each select="/root/foo/bar">
  <p>
    <xsl:value-of select="." />: <xsl:value-of select="/root/feng/heppa[@id = @id]" />
  </p>
</xsl:for-each>

期望的输出:

<p>sdf: ....</p>
<p>sdooo: sseeapeea</p>

实际输出:

<p>sdf: hihi</p>
<p>sdooo: hihi</p>

3 个答案:

答案 0 :(得分:3)

要选择仅包含XPath 1.0的节点,您需要进行节点集比较:

/root/feng/heppa[@id=/root/foo/bar/@id]

当然,这具有NxM复杂性(与其他XSLT解决方案一样)

使用XSLT 1.0,你应该使用密钥,因为有交叉引用:

<xsl:key name="kBarById" select="bar" use="@id"/>

<xsl:template match="/root/feng/heppa[key('kBarById',@id)]">       
    <p>       
        <xsl:value-of select="concat(key('kBarById',@id),': ',.)"/>
    </p>       
</xsl:template> 

答案 1 :(得分:2)

我认为您的意思是/root/foo/bar,因为/root/foo元素没有ID。

您将@id与其自身进行比较,因此对于所检查的第一个节点来说当然是这样。您可以使用current()来引用表达式中的当前节点:

<xsl:for-each select="/root/foo/bar">
  <p>
    <xsl:value-of select="." />: <xsl:value-of select="/root/feng/heppa[@id = current()/@id]" />
  </p>
</xsl:for-each>

答案 2 :(得分:1)

另一种解决方案是将id属性读入变量。

<xsl:for-each select="/root/foo/bar">
    <xsl:variable name="id" select="@id"/>
    <p>
        <xsl:value-of select="." />: <xsl:value-of select="/root/feng/heppa[@id = $id]" />
    </p>
</xsl:for-each>

如果您的实际用例更复杂,并且您需要在此for-each部分中多次使用id的值,这可能更方便。