Suppose I have the following XML:
假设我有以下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>
Now I want to print all the name
attributes of those element bar
which point to an element foo
that has the attribute checked
. So for the example above, my xslt would output blub
and plim
.
现在我想打印那些元素栏的所有名称属性,这些属性指向一个已检查属性的元素foo。所以对于上面的例子,我的xslt将输出blub和plim。
Here is what I have tried so far is to just check whether I can print the id
attribute of the foo
element that each bar
belongs to:
到目前为止,我所尝试的只是检查是否可以打印每个条形所属的foo元素的id属性:
<xsl:template match="/">
<xsl:for-each select="//bars/bar">
<xsl:value-of select="../../foos/foo[@id=./@for]/@id" />
</xsl:for-each>
</xsl:template>
but to no avail. I think the problem is, that the check foo[@id=./@for]
will select both @id
and @for
from the foo
element. So how can I say that I want the @for
attribute from my current element in the for loop but the @id
from the other current element?
但无济于事。我认为问题是,check foo [@id =。/ @ for]将从foo元素中选择@id和@for。那么我怎么能说我想在for循环中从当前元素获取@for属性,而从另一个当前元素中获取@id?
3 个解决方案
#1
5
how can I say that I want the
@for
attribute from my current element in the for loop but the@id
from the other current element?我怎么能说我想要for循环中当前元素的@for属性,而是来自其他当前元素的@id?
使用current()函数:
<xsl:value-of select="../../foos/foo[@id=current()/@for]/@id" />
Inside the square brackets, .
is the node that the predicate is testing, whereas current()
is the node that is the current target of the for-each
.
在方括号内,。是谓词正在测试的节点,而current()是for-each的当前目标的节点。
#2
1
As an alternative that should also improve performance you can define a key
作为替代方案,还应该提高性能,您可以定义密钥
<xsl:key name="foo-by-id" match="foos/foo" use="@id"/>
and then replace
然后更换
<xsl:for-each select="//bars/bar">
<xsl:value-of select="../../foos/foo[@id=./@for]/@id" />
</xsl:for-each>
with
<xsl:for-each select="//bars/bar">
<xsl:value-of select="key('foo-by-id', @for)/@id" />
</xsl:for-each>
#3
0
To build on the xsl:key
idea from @martin-honnen, make a key for the checked items:
要构建来自@ martin-honnen的xsl:key构思,请为已检查项创建一个键:
<xsl:key name="checked" match="foos/foo[@checked = 'yes']" use="@id" />
Then your XSLT can become:
然后你的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>
Only the foo
with checked="yes"
are included in the checked
key (though if you are working from HTML, it's more likely that it's checked="checked"
). key('checked', @for)
for an element without a corresponding checked="yes"
will return an empty node-set/empty sequence (depending on your XSLT version), so for those elements, the predicate will evaluate to false
, so the xsl:apply-templates
selects only the elements that you are interested in, so the template for bar
becomes very simple.
只有带有checked =“yes”的foo才会包含在已检查的密钥中(但如果您使用的是HTML,那么它更有可能被检查=“已检查”)。没有相应的checked =“yes”的元素的key('checked',@ for)将返回一个空的node-set / empty序列(取决于你的XSLT版本),因此对于这些元素,谓词将评估为false,所以xsl:apply-templates只选择你感兴趣的元素,因此bar的模板变得非常简单。
#1
5
how can I say that I want the
@for
attribute from my current element in the for loop but the@id
from the other current element?我怎么能说我想要for循环中当前元素的@for属性,而是来自其他当前元素的@id?
使用current()函数:
<xsl:value-of select="../../foos/foo[@id=current()/@for]/@id" />
Inside the square brackets, .
is the node that the predicate is testing, whereas current()
is the node that is the current target of the for-each
.
在方括号内,。是谓词正在测试的节点,而current()是for-each的当前目标的节点。
#2
1
As an alternative that should also improve performance you can define a key
作为替代方案,还应该提高性能,您可以定义密钥
<xsl:key name="foo-by-id" match="foos/foo" use="@id"/>
and then replace
然后更换
<xsl:for-each select="//bars/bar">
<xsl:value-of select="../../foos/foo[@id=./@for]/@id" />
</xsl:for-each>
with
<xsl:for-each select="//bars/bar">
<xsl:value-of select="key('foo-by-id', @for)/@id" />
</xsl:for-each>
#3
0
To build on the xsl:key
idea from @martin-honnen, make a key for the checked items:
要构建来自@ martin-honnen的xsl:key构思,请为已检查项创建一个键:
<xsl:key name="checked" match="foos/foo[@checked = 'yes']" use="@id" />
Then your XSLT can become:
然后你的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>
Only the foo
with checked="yes"
are included in the checked
key (though if you are working from HTML, it's more likely that it's checked="checked"
). key('checked', @for)
for an element without a corresponding checked="yes"
will return an empty node-set/empty sequence (depending on your XSLT version), so for those elements, the predicate will evaluate to false
, so the xsl:apply-templates
selects only the elements that you are interested in, so the template for bar
becomes very simple.
只有带有checked =“yes”的foo才会包含在已检查的密钥中(但如果您使用的是HTML,那么它更有可能被检查=“已检查”)。没有相应的checked =“yes”的元素的key('checked',@ for)将返回一个空的node-set / empty序列(取决于你的XSLT版本),因此对于这些元素,谓词将评估为false,所以xsl:apply-templates只选择你感兴趣的元素,因此bar的模板变得非常简单。