7

I am trying to determine the correct XPath expression to return the value of the xsi:type attribute on the Body element. I have tried what seems like everything without luck. Based on what I read this would seem close but it is obviously not quire correct. Any quick guidance so that I can put finally to rest?

//v20:Body/@xsi:type

I want it to return v20:SmsMessageV1RequestBody

<v20:MessageV1Request>
    <v20:Header>
        <v20:Source>
            <v20:Name>SOURCE_APP</v20:Name>
            <v20:ReferenceId>1326236916621</v20:ReferenceId>
            <v20:Principal>2001</v20:Principal>
        </v20:Source>
    </v20:Header>
    <v20:Body xsi:type="v20:SmsMessageV1RequestBody">
        <v20:ToAddress>5555551212</v20:ToAddress>
        <v20:FromAddress>11111</v20:FromAddress>
        <v20:Message>TEST</v20:Message>
    </v20:Body>
</v20:MessageV1Request>
Wayne
  • 59,728
  • 15
  • 131
  • 126
J. Scarbrough
  • 704
  • 2
  • 8
  • 12
  • 4
    The Xpath expression looks good to me. Are you using this XPath in an XQUERY, an XSLT or something else? The most likely cause of a problem here is confusion caused by the namespace prefixes. One way to eliminate namespaces as a source of confusion is to rewrite the xpath as this: //*[local-name() eq 'Body']/@*[local-name() eq 'type'] – Murray McDonald Jan 10 '12 at 23:28
  • Murray is right, because there are generally two ways to deal with namespaces in XPath - first: using `local-name()` and `namespace-uri()` XPath functions, second: using proper mechanisms of XPath engine - e.g. for standard JAXP you have to use properly configured NamespaceContext which maps prefixes to namespaces. – Grzegorz Grzybek Jan 11 '12 at 06:14

2 Answers2

2

As was pointed out in the comments, you have two choices:

  1. Use local-name() to reference the target nodes without regard for namespaces
  2. Properly register all namespaces with the XPath engine

Here's how to do the latter in Java:

XPath xpath = XPathFactory.newInstance().newXPath();
NamespaceContext ctx = new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        if ("v20".equals(prefix)) {
            return "testNS1";
        } else if ("xsi".equals(prefix)) {
            return "http://www.w3.org/2001/XMLSchema-instance";
        }
        return null;
    }
    public String getPrefix(String uri) {
        throw new UnsupportedOperationException();
    }
    public Iterator getPrefixes(String uri) {
        throw new UnsupportedOperationException();
    }
};
xpath.setNamespaceContext(ctx);
XPathExpression expr = xpath.compile("//v20:Body/@xsi:type");       
System.out.println(expr.evaluate(doc, XPathConstants.STRING));

Note that I'm assuming the following namespace declarations:

<v20:MessageV1Request xmlns:v20="testNS1" 
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

You'll need to update getNamespaceURI to use the actual values.

Wayne
  • 59,728
  • 15
  • 131
  • 126
0

All great answers/feedback. My actual issue seems have resolved itself with a night away and fresh build in the morning. I will be enhancing with the feedback. Thanks all.

J. Scarbrough
  • 704
  • 2
  • 8
  • 12