KyleCrowley
KyleCrowley

Reputation: 930

XML Parsing with XPath

So I am pretty new to XML parsing, but I looked around and I found some info that was of value to me. I came across something called XPath and I thought that it might work. Unfortunately, I am having some trouble with it.

Currently I am trying to get a string using this line of code:

String summaryFedEx = (String) xpath.evaluate("/SOAP-ENV:Envelope/SOAP-ENV:Body/v4:TrackReply/v4:HighestSeverity", dom, XPathConstants.STRING);

Before you ask, dom is fine. So that leaves me to believe the expression itself is wrong.

Below I have the XML I am trying to parse. Maybe someone could give some assistance?

I should note: I am trying to get the "v4:HighestSeverity" data.

XML:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header />
   <SOAP-ENV:Body>
      <v4:TrackReply xmlns:v4="http://fedex.com/ws/track/v4">
         <v4:HighestSeverity>ERROR</v4:HighestSeverity>
         <v4:Notifications>
            <v4:Severity>ERROR</v4:Severity>
            <v4:Source>prof</v4:Source>
            <v4:Code>1000</v4:Code>
            <v4:Message>Authentication Failed</v4:Message>
         </v4:Notifications>
         <v4:TransactionDetail>
            <v4:CustomerTransactionId>TC030_WSVC_Track_v4 _POS</v4:CustomerTransactionId>
            <v4:Localization>
               <v4:LanguageCode>EN</v4:LanguageCode>
            </v4:Localization>
         </v4:TransactionDetail>
         <v4:Version>
            <v4:ServiceId>trck</v4:ServiceId>
            <v4:Major>4</v4:Major>
            <v4:Intermediate>0</v4:Intermediate>
            <v4:Minor>0</v4:Minor>
         </v4:Version>
      </v4:TrackReply>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Upvotes: 2

Views: 2374

Answers (1)

helderdarocha
helderdarocha

Reputation: 23637

If you just want to read the data and won't have any conflicts ignoring the namespace, you can use a XPath expression that ignores namespaces, like this:

"/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='TrackReply']/*[local-name()='HighestSeverity']"

It's simply the same XPath but selecting * any element, and adding a predicate [...] to limit those elements to the ones that have a matching local name.

If you need to preserve namespaces, then you have to register the prefixes. You can do that implementing a NamespaceContext and setting it to your xpath object reference before performing the search:

xPath.setNamespaceContext(new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        if (prefix.equals("SOAP-ENV")) {
            return "http://schemas.xmlsoap.org/soap/envelope/";
        } else if (prefix.equals("v4")) {
            return "http://fedex.com/ws/track/v4";
        } else {
            return XMLConstants.NULL_NS_URI;
        }
    }
    public String getPrefix(String namespaceURI) { return null;}
    public Iterator getPrefixes(String namespaceURI) { return null;}
});

Upvotes: 2

Related Questions