Domanda

Lets say I have a UPnP SOAP response like this:

<?xml version="1.0"?>
<m:head xmlns:m="dont_care_about_any_node_in_this_namespace">
  <m:body xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1">
    <u:SomeFunctionResponse>
      <u:OutParamName>Some Text</u:OutParamName>
    </u:SomeFunctionResponse>
  </m:body>
</m:head>

I want to select all nodes that have a u namespace prefix, but:

  • The node names in the u namespace could be different.
  • I don't know that the namespace prefix is u in advance and it could be anything.
  • The only thing I do know is the service that I used to invoke the action, in this case urn:schemas-upnp-org:service:WANPPPConnection:1

How do I select only u nodes? Something like:

//urn:schemas-upnp-org:service:WANPPPConnection:1/*

I've seen articles about implementing NamespaceContext but I just don't understand what that does or how I can use it... Those examples usually end up hard-coding a prefix at some point, making them seem foolish to me. And also, implementations of that interface usually seem like a lot of code for something that appears quite simple...

È stato utile?

Soluzione

I actually answered my own question a few mins after asking. I needed to set my DocumentBuilderFactory to be NameSpace Aware:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse("myxml.xml");
XPath xp = XPathFactory.newInstance().newXPath();
XPathExpression xpe = xp.compile("//*[namespace-uri()='urn:schemas-upnp-org:service:WANPPPConnection:1']");
NodeList nl = (NodeList) xpe.evaluate(doc, XPathConstants.NODESET);
for(int i = 0; i < nl.getLength(); i++){
  Element e = (Element) nl.item(i);
  System.out.println(e.getNodeName());
}

Output:

u:SomeFunctionResponse
u:OutParamName
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top