Reputation: 563
I need to fetch a node set containing elements that refer to exactly two other elements. I can't figure out how to do it in a single XPath expression.
My (simplified) source XML looks like this:
<group>
<id>1337</id>
</group>
<group>
<id>1338</id>
</group>
<member>
<id>31415</id>
<groupId>1337</groupId>
</member>
<member>
<id>31416</id>
<groupId>1337</groupId>
</member>
<member>
<id>31417</id
<groupId>1338</groupId>
</member>
Now, I want to select all <group>
nodes that refer to exactly two <member>
s, which should result in returning the group with id=1337 only. I tried the following...
<xsl:variable name="groupsWithTwoMembers" select="group[count(../member[id=??]) = 2]"/>
...and obviously at the '??' I need to insert the groupId of the group I selected at the start of the XPath expression, but I can't think of a way to get to this groupId. Can anyone out there think of one? Thanks!
Upvotes: 2
Views: 247
Reputation: 3186
In XPath 1.0 this is not possible. In XPath 2.0 you can do the following (untested):
for $a in fn:distinct-values(//group/id)
if count(../../member[@id = $a]) = 2 then return $a
Upvotes: 0
Reputation: 243479
XPath2.0:
$p/group[count(index-of($p/member/groupId, id)) eq 2]
where $p
is the parent of the provided XML fragment.
Upvotes: 1
Reputation: 4657
You should look into the difference between the current node and context node. They are usually the same but when dealing with predicates, the context node (often represented with a .) matches the node you are predicating against. In this situation you should use current() to access the current node rather than the context node.
Upvotes: 0
Reputation:
The problem is that predicates filters previous selected nodes with each of those nodes as context. So, you need to pull in the out of context reference.
This can be done with variable/parameter reference or current()
function (results in context node for the whole XSLT instruction).
Also, in this case having cross references, it's better to use keys:
<xsl:key name="kMemberByGroupId" match="member" use="groupId"/>
...
<xsl:variable name="groupsWithTwoMembers"
select="group[count(key('kMemberByGroupId',id)) = 2]"/>
Upvotes: 2