Selecting specific and unique attributes with XPATH
I'm trying to execute an XPATH query that will allow me to select nodes based on two criteria.
First I need nodes that contain a unique attribute value and second I need nodes that contain a specific attribute value.
For example:
<rows>
<row value="0" id="130"/>
<row value="1" id="130"/>
<row value="2" id="130"/>
<row value="0" id="131"/>
<row value="1" id="131"/>
<row value="1" id="131"/>
<row value="2" id="131"/>
<row value="0" id="132"/>
<row value="1" id="132"/>
<row value="2" id="132"/>
</rows>
In this scenario I'd want all n开发者_如何学Codes that contain unique 'values' but only if they also have id="131". I would also want the second value='1' node removed. I would expect this result:
<row value="0" id="131"/>
<row value="1" id="131"/>
<row value="2" id="131"/>
Is this possible with a single XPATH query?
Thanks.
Yes, but it's not pretty. There is probably a better way, but here it goes:
/rows/row[@id='131'][(not(preceding-sibling::row[@id='131']) or not(following-sibling::row[@id='131'])) or
preceding-sibling::row[@id='131']/@value != @value and
following-sibling::row[@id='131']/@value != @value]
Here's an example using this on a slightly more complicated version of your input XML. (I added another <row value="1" id="131"/>
to show that it only returns unique results.)
Input XML:
<rows>
<row value="0" id="130"/>
<row value="0" id="131"/>
<row value="0" id="132"/>
<row value="1" id="130"/>
<row value="1" id="131"/>
<row value="1" id="132"/>
<row value="2" id="130"/>
<row value="2" id="131"/>
<row value="2" id="132"/>
<row value="1" id="131"/>
</rows>
Results:
<row value="0" id="131"/>
<row value="1" id="131"/>
<row value="2" id="131"/>
Sure, you can use the <xsl:key> element and the key() function. Construct a key that is the combination of the @value and @id attributes of a <row> element, and select only those 'key sets' that contain one node and whose @id attribute is equal to '131' (or whatever).
<xsl:key name="id-key" match="row" use="concat(@value, '-', @id)" />
<xsl:template
match="row[count(key('id-key', concat(@value, '-', @id))) = 1 and @id='131']">
<xsl:copy-of select="." />
</xsl:template>
Fun, isn't it?
Read more about it here: http://www.jenitennison.com/xslt/grouping/muenchian.html
EDIT: Sorry, I just realized you needed an XPATH query. Note to self: read the questions more carefully. However, the answer could still be useful, so I'll leave it.
精彩评论