如何在for-each循环中找到与xslt属性值匹配的元素

时间:2014-10-19 12:09:37

标签: xml xslt

假设我有以下XML:

<data>
  <foos>
    <foo id="1" checked="yes" />
    <foo id="2" />
    <foo id="3" />
    <foo id="4" checked="yes" />
  </foos>
  <bars>
    <bar for="1" name="blub" />
    <bar for="2" name="bla" />
    <bar for="3" name="baz" />
    <bar for="4" name="plim" />
  </bars>
</data>

现在,我想要打印那些元素name的所有bar属性,这些属性指向具有属性foo的元素checked。因此,对于上面的示例,我的xslt将输出blubplim

到目前为止,我所尝试的只是检查是否可以打印每个id所属的foo元素的bar属性:

<xsl:template match="/">
  <xsl:for-each select="//bars/bar">
    <xsl:value-of select="../../foos/foo[@id=./@for]/@id" />
  </xsl:for-each>
</xsl:template>

但无济于事。我认为问题是,支票foo[@id=./@for]会从@id元素中选择@forfoo。那么我怎么能说我想要for循环中当前元素的@for属性,而其他当前元素的@id呢?

3 个答案:

答案 0 :(得分:5)

  

我怎么能说我想要for循环中当前元素的@for属性,而其他当前元素的@id

使用the current() function

<xsl:value-of select="../../foos/foo[@id=current()/@for]/@id" />

在方括号内,.是谓词正在测试的节点,而current()for-each的当前目标的节点。

答案 1 :(得分:1)

作为替代方案,还应该提高性能,您可以定义一个键

<xsl:key name="foo-by-id" match="foos/foo" use="@id"/>

然后替换

  <xsl:for-each select="//bars/bar">
    <xsl:value-of select="../../foos/foo[@id=./@for]/@id" />
  </xsl:for-each>

  <xsl:for-each select="//bars/bar">
    <xsl:value-of select="key('foo-by-id', @for)/@id" />
  </xsl:for-each>

答案 2 :(得分:0)

要建立来自@ martin-honnen的xsl:key想法,请为已检查的项目设置密钥:

<xsl:key name="checked" match="foos/foo[@checked = 'yes']" use="@id" />

然后您的XSLT可以变为:

<xsl:template match="/">
  <xsl:apply-templates select="/data/bars/bar[key('checked', @for)]" />
</xsl:template>

<xsl:template match="bar">
  <xsl:value-of select="@name" />
</xsl:template>

foo密钥中只包含checked="yes" checked {(如果您使用的是HTML,则更有可能是checked="checked")。对于没有对应key('checked', @for)的元素,checked="yes"将返回一个空节点集/空序列(取决于您的XSLT版本),因此对于这些元素,谓词将计算为false,因此xsl:apply-templates仅选择您感兴趣的元素,因此bar的模板变得非常简单。