1

I have an XML likewise

<?xml version="1.0" encoding="UTF-8"?>
<QDTM_IN300301QD ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:hl7-org:v3 QDTM_IN300401QD.xsd ">

    <controlActEvent classCode="CACT" moodCode="EVN">
        <code code="QDTM_TE300401QD">
        </code>
        <statusCode code="Active" />
        <subject contextConductionInd="true" contextControlCode="ON"
            typeCode="SUBJ">
            <registrationEvent classCode="REG" moodCode="EVN">
                <statusCode code="token" />
                <subject contextControlCode="AN" typeCode="SBJ">
                    <testCodeIdentifier classCode="ROL">
                        <playingTestCodeDetails classCode="ENT"
                            determinerCode="INSTANCE">
                            <code code="6399Z" codeSystemName="QTIM" codeSystemVersion="Updated">
                                <originalText><![CDATA[CBC (includes Differential and Platelets)]]></originalText>
                                <translation codeSystemName="DOSCATALOGNAMEHTMLENABLED">
                                    <originalText><![CDATA[CBC (includes Differential and Platelets)]]></originalText>
                                </translation>
                            </code>
                        </playingTestCodeDetails>
                    </testCodeIdentifier>
                </subject>
            </registrationEvent>
        </subject>
    </controlActEvent>
</QDTM_IN300301QD>

JAVA CODE:

package com.parse;

import java.io.IOException;
import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;


public class ParseXPath {

    public String parseXML(String fileName) {
            fileName = "D://projects//Draft.xml";
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true); 
            DocumentBuilder builder;
            Document doc;
            try {

                builder = domFactory.newDocumentBuilder();
                doc = builder.parse(fileName);
                XPath xpath = XPathFactory.newInstance().newXPath();
                xpath.setNamespaceContext(new NamespaceContext(){public String getNamespaceURI(String prefix) {
                    return "urn:hl7-org:v3";
                }

                public String getPrefix(String namespaceURI) {
                    return null; // we are not using this.
                }

                public Iterator getPrefixes(String namespaceURI) {
                    return null; // we are not using this.
                }
                });

                String expr="//QDTM_IN300401QD/controlActEvent/subject/registrationEvent/subject/testCodeIdentifier/playingTestCodeDetails/code/translation[@codeSystemName='DOSCATALOGNAMEHTMLENABLED']/originalText/text()";

                String result = xpath.evaluate(expr, doc);
                System.out.println("Result -->  "+result); 
                return result;
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (XPathExpressionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return fileName;




         public static void main(String[] args) 
     throws ParserConfigurationException, SAXException, 
      IOException, XPathExpressionException {
         ParseBUXpath p = new ParseBUXpath();
         p.parseRelatedTestXML("test");



      }

}

I am facing this issue in Namespace thing in XML. When the xml is having "xmlns="urn:hl7-org:v3" then the xpath query doesnt get me the data. For supressing that i have written the code in java and removed the line from XML.

I need to parse the XML and get the data without deleting the namespace part from the XML. Is this a problem related to xsd or it is not getting the xsd mentioned?

4
  • Correct me if I am wrong "You want to get the namespace while parsing the XML document" right? Commented Jan 10, 2012 at 9:05
  • I need to get the data from XML using XPath expression and namespace in XML is blocking it to get the data.... why is it doing so.. for supressing that i have removed the line in XML and added code in Java code. Commented Jan 10, 2012 at 9:11
  • I just made below line change and it was working for me..: domFactory.setNamespaceAware(false);// made it true to false Correct me if i am getting something towards the wrong side... Commented Jan 10, 2012 at 13:17
  • @GOK - That's generally the wrong direction. Namespaces are important. See my answer. Commented Jan 11, 2012 at 20:26

2 Answers 2

1

You need to include the namespace in the expression, the namespace can be replaced by a "prefix" acting as a lookup for the full namespace uri.

String expr="//prefix:QDTM_IN300401QD/controlActEvent/...."

which you set up using namespace mapping, take a look at https://www.ibm.com/developerworks/library/x-javaxpathapi/index.html and https://xml.apache.org/xalan-j/xpath_apis.html#namespacecontext

If the xml only contains one namespace you could also try to use //*:elementname in your expression to simply ignore in what namespace the element name exists.

Take a look at http://www.w3schools.com/XML/xml_namespaces.asp to understand how namespaces are used and what problem they solve

Sign up to request clarification or add additional context in comments.

3 Comments

I dont understand this; like it is saying that we can use to create a NameSpaceContext of ours but i can have a number of expressions so for all that i need to create NameSpaceContext and add pre: in my expressions???
What you need to do is create one NameSpaceContext containing lookups for all your possible namespaces. In your example there is one default namespace xmlns="urn:hl7-org:v3", and one extra xmlns:xsi which is never used in the actual xml contents. When evaluating your expression it looks for anything ending with a ":", if it finds anything it calls getNamespaceURI(String prefix) to find out the full Uri, //pre:QDTM_IN.... the prefix variable becomes "pre", the full uri is expanded and the evaluation continues. A default namespace implicitly causes all elements to be prefixed with it.
+1 - This is the issue. The only reason I provided an additional answer is that there still seems to be some confusion.
0

The purpose of getNamespaceURI inside of the NamespaceContext is to associate each namespace in the source document with a unique prefix, so that the XPath engine knows which namespace an element belongs to whenever it encounters that prefix string in an XPath expression. The prefix here doesn't need to match the prefix (if any) for the same URI in the source XML; it just needs to provide a mapping from the prefix to the correct namespace.

So, if you were to write the expression like this:

//p:QDTM_IN300301QD/p:controlActEvent/p:subject/p:registrationEvent/p:subject
    /p:testCodeIdentifier/p:playingTestCodeDetails/p:code
        /p:translation[@codeSystemName='DOSCATALOGNAMEHTMLENABLED']
            /p:originalText/text()"

...then you'd write the corresponding getNamespaceURI like this:

public String getNamespaceURI(String prefix) {
    if ("p".equals(prefix)) {
        return "urn:hl7-org:v3";
    } 
    return null;
}

This is how the engine knows to look for an element in the urn:hl7-org:v3 namespace whenever it encounters the p prefix, which is the whole point. Othwerwise, how would the engine know that you didn't want some element named QDTM_IN300301QD in no namespace? Or an element with that name in some other namespace?

Note that the prefix name is arbitrary; it can be anything you want, as long as it's unique. That is, if you have other namespaces in your document, then you'll need to modify getNamespaceURI to be aware of those namespaces and assign a unique prefix to each of them.

Here is a complete (minimal) example:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); 
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("Draft.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
NamespaceContext ctx = new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        if ("p".equals(prefix)) {
            return "urn:hl7-org:v3";
        } 
        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("//p:QDTM_IN300301QD/p:controlActEvent" +
        "/p:subject/p:registrationEvent" + 
        "/p:subject/p:testCodeIdentifier/p:playingTestCodeDetails/p:code" +
        "/p:translation[@codeSystemName='DOSCATALOGNAMEHTMLENABLED']" +
        "/p:originalText/text()");      
System.out.println("[" + expr.evaluate(doc, XPathConstants.STRING));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.