Ryan Ternier
Ryan Ternier

Reputation: 8804

Can XPath return only nodes that have a child of X - with namespaces?

This question is a continuation of Can XPath return only nodes that have a child of X? .

I want to find all "pets" that have foo, where some pets have a namespace and other pets do not.

Is it possible to use XPath to select only the nodes that have a particular child elements? For example, from this XML I only want the elements in pets that have a child of 'bar'. So the resulting dataset would contain the lizard and pig elements.

<pets xmlns="urn:cat-org:v1">
  <cat>
    <foo>don't care about this</foo>
  </cat>
  <dog xmlns:v1="urn:cat-org:v1">
     <v1:foo>not this one either</foo>
  </dog>
  <lizard>
     <bar>lizard should be returned, because it has a child of bar</bar>
  </lizard>
  <pig xmlns:v55="urn:cat-org:v1">
     <v55:bar>return pig, too</bar>
  </pig>
</pets>

Any advice would rock.

Upvotes: 1

Views: 460

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

For example, from this XML I only want the elements in pets that have a child of 'bar'.

Use:

/*/*[*[local-name() = 'bar']]

This selects all children of the top element that have at least one child with local name "bar" (regardless of prefixes if such exist).

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="/*/*[*[local-name() = 'bar']]"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document (corrected to be made well-formed):

<pets xmlns="urn:cat-org:v1">
  <cat>
    <foo>don't care about this</foo>
  </cat>
  <dog xmlns:v1="urn:cat-org:v1">
     <v1:foo>not this one either</v1:foo>
  </dog>
  <lizard>
     <bar>lizard should be returned, because it has a child of bar</bar>
  </lizard>
  <pig xmlns:v55="urn:cat-org:v1">
     <v55:bar>return pig, too</v55:bar>
  </pig>
</pets>

the XPath expression is evaluated and the selected elements are copied to the output:

<lizard xmlns="urn:cat-org:v1">
   <bar>lizard should be returned, because it has a child of bar</bar>
</lizard>
<pig xmlns="urn:cat-org:v1" xmlns:v55="urn:cat-org:v1">
   <v55:bar>return pig, too</v55:bar>
</pig>

Upvotes: 3

Related Questions