Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath find all elements with specific child node

Tags:

xml

xpath

Could you please help me to find all the elements b which have the child element c in the example below?

<a>     <b name = "b1"></b>     <b name = "b2"><c/></b>     <b name = "b3"></b> </a> 

The xpath query must return the b2 element

The second question is I want to combine 2 conditions: I want to get the element which have name = "b2" and has the element c But this syntax seems not to work: //b[@name='b2' and c]

like image 957
nam Avatar asked Jun 04 '12 12:06

nam


People also ask

What is child :: In XPath?

As defined in the W3 XPath 1.0 Spec, " child::node() selects all the children of the context node, whatever their node type." This means that any element, text-node, comment-node and processing-instruction node children are selected by this node-test.

How do I select the first child in XPath?

The key part of this XPath is *[1] , which will select the node value of the first child of Department .


2 Answers

Whenever the structure of the XML document is known, it is better to avoid using the // XPath pseudo-operator, as its use can result in big inefficiency (traversal of the whole document tree).

Therefore, I recomment this XPath expression for the provided XML document:

/*/b[c] 

This selects any b element that is a child of the top element of the XML document and that has a child-element named c.

UPDATE: The OP asked a second question just minutes ago:

The second question is I want to combine 2 conditions: I want to get the element which have name = "b2" and has the element c But this syntax seems not to work: //b[@name='b2' and c]

The provided XPath expression does select exactly the wanted element.

Here is XSLT - based verification:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output omit-xml-declaration="yes" indent="yes"/>  <xsl:strip-space elements="*"/>   <xsl:template match="/*">      <xsl:copy-of select="//b[@name='b2' and c]"/>  </xsl:template> </xsl:stylesheet> 

When this transformation is applied on the provided XML document:

<a>     <b name = "b1"></b>     <b name = "b2"><c/></b>     <b name = "b3"></b> </a> 

the XPath expression is evaluated and the correctly-selected element is copied to the output:

<b name="b2">    <c/> </b> 
like image 180
Dimitre Novatchev Avatar answered Sep 20 '22 17:09

Dimitre Novatchev


It should be as simple as

//b[c] 

i.e. find a b anywhere that has a c child.

like image 25
choroba Avatar answered Sep 22 '22 17:09

choroba