Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve namespaces in XML files using Xpath

I have an XML file that starts like this:

<Elements name="Entities" xmlns="XS-GenerationToolElements"> 

I'll have to open a lot of these files. Each of these have a different namespace but will only have one namespace at a time (I'll never find two namespaces defined in one xml file).

Using XPath I'd like to have an automatic way to add the given namespace to the namespace manager. So far, i could only get the namespace by parsing the xml file but I have a XPathNavigator instance and it should have a nice and clean way to get the namespaces, right?

-- OR --

Given that I only have one namespace, somehow make XPath use the only one that is present in the xml, thus avoiding cluttering the code by always appending the namespace.

like image 671
Luis Filipe Avatar asked Sep 23 '08 17:09

Luis Filipe


People also ask

How do I find the XML namespace?

XML Namespaces - The xmlns Attribute When using prefixes in XML, a namespace for the prefix must be defined. The namespace can be defined by an xmlns attribute in the start tag of an element. The namespace declaration has the following syntax. xmlns:prefix="URI".

How does XPath handle namespace?

XPath treats the empty prefix as the null namespace. In other words, only prefixes mapped to namespaces can be used in XPath queries. This means that if you want to query against a namespace in an XML document, even if it is the default namespace, you need to define a prefix for it.


1 Answers

There are a few techniques that you might try; which you use will depend on exactly what information you need to get out of the document, how rigorous you want to be, and how conformant the XPath implementation you're using is.

One way to get the namespace URI associated with a particular prefix is using the namespace:: axis. This will give you a namespace node whose name is the prefix and whose value is the namespace URI. For example, you could get the default namespace URI on the document element using the path:

/*/namespace::*[name()=''] 

You might be able to use that to set up the namespace associations for your XPathNavigator. Be warned, though, that the namespace:: axis is one of those corners of XPath 1.0 that isn't always implemented.

A second way of getting that namespace URI is to use the namespace-uri() function on the document element (which you've said will always be in that namespace). The expression:

namespace-uri(/*) 

will give you that namespace.

An alternative would be to forget about associating a prefix with that namespace, and just make your path namespace-free. You can do this by using the local-name() function whenever you need to refer to an element whose namespace you don't know. For example:

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

You could go one step further and test the namespace URI of the element against the one of the document element, if you really wanted:

//*[local-name() = 'Element' and namespace-uri() = namespace-uri(/*)] 

A final option, given that the namespace seems to mean nothing to you, would be to run your XML through a filter that strips out the namespaces. Then you won't have to worry about them in your XPath at all. The easiest way to do that would be simply to remove the xmlns attribute with a regular expression, but you could do something more complex if you needed to do other tidying at the same time.

like image 100
JeniT Avatar answered Sep 21 '22 22:09

JeniT