This is the input XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:SendResponse xmlns:ns2="http://mycompany.com/schema/">
<ns2:SendResult>
<ns2:Token>A00179-02</ns2:Token>
</ns2:SendResult>
</ns2:SendResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This the code that I'm using to read the XML (Variable xmlString contains the XML above):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlString));
Document doc = db.parse(is);
System.out.println("Element :" + doc.getElementsByTagName("Token").item(0));
System.out.println("Element :" + doc.getElementsByTagName("ns2:Token").item(0));
Output:
Element :null
Element :[ns2:Token: null]
I'm able to read the element if I use "ns2:Token" as the tag name, but I don't want to use the prefix in my code as I'm not sure if it'll be the same or change in the future. Is there any way to read the xml element without hard-coding the namespace in the tag name?
The W3C dom method for namespaced elements:
getElementsByTagNameNS
NodeList getElementsByTagNameNS(String namespaceURI,
String localName)
Returns a NodeList of all the Elements with a given local name and namespace URI in document order.
Parameters:
namespaceURI - The namespace URI of the elements to match on. The special value "*" matches all namespaces.
localName - The local name of the elements to match on. The special value "*" matches all local names.
Returns:
A new NodeList object containing all the matched Elements.
Since:
DOM Level 2
IIRC earlier version of the W3C DOM had poor support for namespaces so I don't use it. However if you use the above with the full namespaceURI http://schemas.xmlsoap.org/soap/envelope/
it should work. The prefix is unimportant - it has no permanency outside the document it is used in.
so try:
System.out.println("Element :" + doc.getElementsByTagNameNS(
"http://schemas.xmlsoap.org/soap/envelope/", "Token").item(0));
get the namespace first
docFactory.setNamespaceAware(true);
StringBuilder nameSpace = new StringBuilder(
doc.getDocumentElement().getPrefix() != null ? doc.getDocumentElement().getPrefix() + ":" : "");
then use nameSpace variable accrodingly
eg:
Node node= doc.getElementsByTagName(nameSpace + "Node1").item(0)
.getFirstChild();
You could always assign the namespace to a variable, this would allow changing it on the fly in the future.
Try to use XPath expression. See sample code below.
Document doc = dBuilder.parse(new ByteArrayInputStream(responseXML.getBytes()));
doc.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/ns6:ReadPersonReturn/ns6:object/ns3:Person/ns3:Phone/ns3:item";
NodeList nodes = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
Element secondNode = null;
if(nodes != null && nodes.getLength() > 0){
secondNode = (Element) leadCloudPingRecordNodes.item(i);
}