22

I'm trying to use XPath to find all elements that have an element in a given namespace.

For example, in the following document I want to find the foo:bar and doodah elements:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:foo="http://foo.example.com">
  <foo:bar quux="value">Content</foo:bar>
  <widget>Content</widget>
  <doodah foo:quux="value">Content</doodah>
</root>

I know I can use the following XPath expression to load all attributes from a given namespace:

"//@*[namespace-uri()='http://foo.example.com']"

However:

  • This doesn't give me the elements, just the attributes.
  • Where elements contain multiple attributes from that namespace, this selector will return a result per-attribute rather than per-element

Is it possible to get what I want, or do I have to gather the attributes and calculate the unique set of elements they correspond to?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Gareth
  • 133,157
  • 36
  • 148
  • 157
  • Did you forgot to add a namespace for doodah? Because I don't see how it can be selected through a namespace. – Emmanuel Rodriguez Feb 09 '09 at 19:54
  • If the clarifications weren't clear, I used the wrong namespace in my original example. My mistake. – Gareth Feb 10 '09 at 14:06
  • 1
    Thanks for this post, it really helped. To sum up: - To get elements with attributes from a given namespace: `//*[@*[namespace-uri()='http://foo.example.com']]` - To get attributes from a given namespace: `//@*[namespace-uri()='http://foo.example.com']` – Lance Feb 16 '10 at 05:59

4 Answers4

28

Use:

//*[namespace-uri()='yourNamespaceURI-here'
   or
    @*[namespace-uri()='yourNamespaceURI-here']
   ]

the predicate two conditions are or-ed with the XPath or operator.

The XPath expression thus selects any element that either:

  • belongs to the specified namespace.
  • has attributes that belong to the specified namespace.
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • It was only the second half of that I needed :) I didn't know you could nest predicates in predicates. Have updated my post accordingly – Gareth Feb 10 '09 at 00:03
  • @Dimitre Novatchev could you pls have a look here is this a namespace problem? tnx http://stackoverflow.com/questions/7007767/iphone-sdk-xml-mystery-after-adding-child-nodeforxpath-returns-nothing – Spring Aug 10 '11 at 14:57
4

I'm not sure if this is what you mean, but by only deleting one char in your XPath you get all elements in a certain namespace:

//*[namespace-uri()='http://foo.example.com']
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
jor
  • 711
  • 3
  • 7
1

You could try

//*[namespace-uri()='http://foo.example.com' or @*[namespace-uri()='http://foo.example.com']]

It will give you element foo:bar and element doodah (if you change tal:quux to foo:quux in your XML-data):

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:foo="http://foo.example.com" xmlns:tal="xxx">
  <foo:bar quux="value">Content</foo:bar>
  <widget>Content</widget>
  <doodah foo:quux="value">Content</doodah>
</root>

Is that what you want?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Johannes Weiss
  • 52,533
  • 16
  • 102
  • 136
  • Not quite so... namespace-uri(./@*)='http://foo.example.com'] returns true only if the first attribute (which is implementation dependent!) belongs to that namespace. The original post wants the element to be selected if *any* of its attributes belongs to the namespace – Dimitre Novatchev Feb 09 '09 at 21:30
0

Your XPath expression is almost perfect. Instead of asking for attributes "@" ask for elements "" and it should work:

"//*[namespace-uri()='http://foo.example.com']"
Emmanuel Rodriguez
  • 1,584
  • 10
  • 9
  • You haven't understood the question. The OP wants any element to be selected, that either belongs to the namespace or has ot least one attribute that belongs to the namespace. Your expression doesnt select an element that has attributes in the namespace but the element doesnt belong to the namespace – Dimitre Novatchev Feb 09 '09 at 21:33
  • Thanks for the clarification. I know that I haven't understood the question as I added a comment to the question asking why "doodah" should be selected. – Emmanuel Rodriguez Feb 10 '09 at 07:09