XPath expression with multiple namespaces?

Hello all.

I have been scouring the forums and Google and can't seem to find anything similar to my problem.

I have the following XML with three namespaces. Two are defined in the root element and the third is defined in the the IdSession element. To make things even more confusing, the second and third namespaces have the same prefix, 'f'.

This is the xml:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<NamespaceTestCall xmlns="http://my.default/namespace"

xmlns:f="http://my.second/namespace">

...<f:Level1>

......<f:IdSession xmlns:f="http://my.third/namespace">12345</f:IdSession>

......<Language>ENG</Language>

...</f:Nivel1>

</NamespaceTestCall>

My question is, how do I get at the IdSession element? Don't I need to create an XPath object and assign it more than one NamespaceContext?

This is what I am doing:

Document xmlDocument = loadXML(xmlSource);

XPath xpathEvaluator = XPathFactory.newInstance().newXPath();

xpathEvaluator.setNamespaceContext(new NamespaceContextProvider("a", "http://my.third/namespace"));

... xpathEvaluator.evaluate("//a:IdSession", ...);

This code works but it might not return the 'IdSession' I want, since by searching like this '//a:IdSession' it is looking in the whole document. If there were another 'IdSession' somewhere else in the document with the same URI, it would be returned. I want the 'IdSession' that lives inside of 'Level1'.

So what I would like to do is something like this:

... xpathEvaluator.evaluate("/*/Level1/a:IdSession", ...);

But this does NOT work because 'Level1' has its own namespace. So what it seems like I need to do is the following:

... xpathEvaluator.evaluate("/*/b:Level1/a:IdSession", ...);

Having already added the 'Level1' namespace to the XPath object, with the prefix 'b'. But unlike JDOM, there is no 'add' functionality, only 'set', meaning if you call set twice the second call overwrites the first.

Is there anyway to do this?

Many thanks!

Bob

[2197 byte] By [syg6a] at [2007-11-26 19:03:14]
# 1

Bob,

I'm not entire sure I understand your problem. So let me ask you another question. I see that you're using a NamespaceContextProvider. What prevents you from creating an instance of this class with separate mappings for the prefixes "a" and "b"? I'm not sure which NamespaceContextProvider you are using, but whichever it is, it should support multiple mappings.

spericasa at 2007-7-9 20:50:12 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 2

Hello,

Sorry, that was my bad. I should have explained that NamespaceContextProvider is nothing more than my implementation of the NamespaceContext interface. The way I did it, I simply implemented getNamespaceURI() and getPrefix(). And the constructor accepted two parameters -- prefix and URI. So my problem was that when I assigned this NamespaceContext to my XPath object it would only have one prefix and one URI.

But I found an implementation here:

http://www.oreillynet.com/cs/user/view/cs_msg/50304

that instead of only having one prefix and URI uses a map. Thus its method setNamespace() adds the prefix and URi to the map, and getPrefix() and getPrefixes() retrieve them from the map.

Now when I want to use more than one namespace I simply call setNamespace() as many times as necessary, adding a prefix and URI pair each time, and when I am done I assign it to my XPath object.

And it works!

Thanks for the response!

Bob

syg6a at 2007-7-9 20:50:12 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...