0

I am trying to retrieve the value of an attribute from an xmel file using XPath and I am not sure where I am going wrong..

This is the XML File

<soapenv:Envelope>
  <soapenv:Header>
    <common:TestInfo testID="PI1" />
  </soapenv:Header>
</soapenv:Envelope>

And this is the code I am using to get the value. Both of these return nothing..

XPathBuilder getTestID = new XPathBuilder("local-name(/*[local-name(.)='Envelope']/*[local-name(.)='Header']/*[local-name(.)='TestInfo'])");
XPathBuilder getTestID2 = new XPathBuilder("Envelope/Header/TestInfo/@testID");

Object doc2 = getTestID.evaluate(context, sourceXML);
Object doc3 = getTestID2.evaluate(context, sourceXML);

How can I retrieve the value of testID?

Jens Erat
  • 37,523
  • 16
  • 80
  • 96
stinkyPete
  • 1
  • 1
  • 8
  • Which of the many `XPathBuilder` implementations are you using? – parsifal Feb 08 '13 at 15:40
  • Please make sure to post *valid* XML, the ` closing tag actually was another opening one. – Jens Erat Feb 08 '13 at 15:46
  • 1
    Possibly off-topic, but as this concerns SOAP: if you're trying to implement your own SOAP service/request parser, please don't; you'll cut yourself on one of its many many sharp edges. – akaIDIOT Feb 08 '13 at 15:57

4 Answers4

0

The XML file you provided does not contain an <Envelope> element, so an expression that requires it will never match.

Post-edit edit

As can be seen from your XML snippet, the document uses a specific namespace for the elements you're trying to match. An XPath engine is namespace-aware, meaning you'll have to ask it exactly what you need. And, keep in mind that a namespace is defined by its uri, not by its abbreviation (so, /namespace:element doesn't do much unless you let the XPath engine know what the namespace namespace refers to).

akaIDIOT
  • 9,171
  • 3
  • 27
  • 30
  • I was just showing a cross section as an example. Need help with the XPath expression.. – stinkyPete Feb 08 '13 at 15:27
  • 1
    While that is understandable, please always provide enough data for anyone here to reproduce the problem, should they decide to try. Asking people to help based on half a problem doesn't work well :) – akaIDIOT Feb 08 '13 at 15:52
0

However you're iterating within the java, your context node is probably not what you think, so remove the "." specifier in your local-name(.) like so:

/*[local-name()='Header']/*[local-name()='TestInfo']/@testID worked fine for me with your XML, although as akaIDIOT says, there isn't an <Envelope> tag to be seen.

JWiley
  • 3,129
  • 8
  • 41
  • 66
  • I've added the Envelope tags to show that I do have them. The XPath string still isn't working with my code.. – stinkyPete Feb 08 '13 at 15:36
  • There's no difference between `local-name()` and `local-name(.)`. The first one is just one character shorter. – JLRishe Feb 08 '13 at 18:03
0

If you don't care for the namespaces and use an XPath 2.0 compatible engine, use * for it.

//*:Header/*:TestInfo/@testID

will return the desired input.

It will probably be more elegant to register the needed namespaces (not covered here, depends on your XPath engine) and query using these:

//soapenv:Header/common:TestInfo/@testID
Jens Erat
  • 37,523
  • 16
  • 80
  • 96
  • That's not valid XPath. You can't use `*` as a namespace prefix wildcard. – JLRishe Feb 08 '13 at 18:04
  • You're right, it isn't valid XPath 1.0, but [allowed in XPath 2.0](http://developer.marklogic.com/blog/namespace-wildcards-in-xpath). I added this to my answer, thank you. – Jens Erat Feb 08 '13 at 18:26
0

Your first XPath has an extra local-name() wrapped around the whole thing:

local-name(/*[local-name(.)='Envelope']/*[local-name(.)='Header']
                                                         /*[local-name(.)='TestInfo'])

The result of this XPath will either be the string value "TestInfo" if the TestInfo node is found, or a blank string if it is not.

If your XML is structured like you say it is, then this should work:

/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='TestInfo']/@testID

But preferably, you should be working with namespaces properly instead of (ab)using local-name(). I have a post here that shows how to do this in Java.

Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169