Reputation: 23
I am trying to obtain a list of qux
attributes of siblings with a certain attribute, in this case x
in attribute foo
and y
in attribute foo
of it's sibling.
//node[@foo="x" and following-sibling::node[@foo="y"]]/@qux | //node[@foo="y" and preceding-sibling::node[@foo="x"]]/@qux
This creates a list, but is the same as running both parts separately and adding them together, except for the order. I need a list of both qux
next to eachother, so a list of two qux
elements per row, obviously where the siblings match up.
Can this be done in xpath, and if so, how? If not, would xquery do the job?
edit: sample file and output:
<database>
<ds version="1">
<node>
<node foo="x" qux="hello"/>
<node foo="y" qux="world"/>
</node>
</ds>
<ds version="1">
<node>
<node>
<node foo="x" qux="another"/>
<node foo="y" qux="sentence"/>
<node foo="y" qux="example"/>
<node foo="z" qux="irrelevant"/>
</node>
</node>
</ds>
<ds version="1">
<node>
<node foo="y" qux="not"/>
<node foo="z" qux="returned"/>
</node>
</ds>
</database>
Note that the depth of the node I'm interested in isn't known, so (I think) usage of //node is necessary.
A query should return:
hello world
another sentence
another example
Upvotes: 2
Views: 111
Reputation: 243519
As per the OP's expressed interest in an XPath 2.0 solution:
This XPath 2.0 expression:
for $n in //node[@foo eq 'x' and following-sibling::*[1][self::node[@foo eq 'y']]]
return
( ($n|$n/following-sibling::*[1])/@qux/string(), '
')
produces the wanted result.
Upvotes: 1
Reputation: 699
Its not so easy to get your results with a single XPATH statement- XPATH is intented for XML navigation really. XSL is used for XML transformations (which is really what you want to do, i.e. transform an attribute list [hello][world] into a string "hello world"..) SO here is the XSL you need to get the results you want-
<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml file:///C:/Users/Damien/Desktop/testXML.xml?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-
functions">
<xsl:template match="/">
<xsl:for-each select="//node[@foo='x' and following-
sibling::node[@foo='y']]/@qux | //node[@foo='y' and preceding-
sibling::node[@foo='x']]/@qux">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 12817
For lack of complete understanding of the requirements, but wouldn't something like this work?
//@qux[../@foo = 'x' or ../@bar='y']
Upvotes: 0