Unable to read xml with namespace prefix using DOM parser

Posted on

Unable to read xml with namespace prefix using DOM parserError is an illegal operation performed by the user which results in the abnormal working of the program. By now, you’ve probably seen a few errors, either when compiling or running your code like Unable to read xml with namespace prefix using DOM parser. It can be frustrating, but they can also give you a lot of information about exactly how you can fix the problems in your code about java and xml. In this post covers the types of errors you’ll see when programming in Java, and how to fix them. Don’t pay any attention to the number of errors. Just read the first error message and work on fixing that error.

Problem :

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?

Solution :

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);
}

Leave a Reply

Your email address will not be published. Required fields are marked *