简体   繁体   中英

DOM Parser query in JAVA

<subjectOf typeCode="SUBJ">
    <annotation classCode="ACT" moodCode="EVN">
        <realmCode code="QD" />
        <code code="SPECIALNOTE"></code>
        <text><![CDATA[<strong>** New York State approval pending. This test is not available for New York State patient testing **</br> ]]></text>
    </annotation>
</subjectOf>
<subjectOf typeCode="SUBJ">
    <annotation classCode="ACT" moodCode="EVN">
        <realmCode code="QD" />
        <code code="PREFERREDSPECIMEN"></code>
        <text><![CDATA[2 mL Second void urine <strong>or </strong>2-hour urine <strong>or </strong>&nbsp;2 mL Urine with no preservative]]></text>
    </annotation>
</subjectOf>

In DOM parsing, how can I traverse through the above XML and get the <text> tag value depending upon a <code> tag attribute having a given value. For example, I want to get the following text:

<strong> ** New York State approval pending. This test is not available for New York State patient testing ** </br>

...based on the <code> tag with a code attribute where value="SPECIALNOTE" .

public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {      
    DocumentBuilderFactory domFactory =  DocumentBuilderFactory.newInstance();          
    domFactory.setNamespaceAware(true);      
    DocumentBuilder builder = domFactory.newDocumentBuilder();     
    Document doc = builder.parse("xml.xml");     
    XPath xpath = XPathFactory.newInstance().newXPath();        // XPath Query for showing all nodes value     

    XPathExpression expr = xpath.compile("/testCodeIdentifier/subjectOf/subjectOf/annotation/code[@code='SPECIALNOTE']");      
    Object result = expr.evaluate(doc, XPathConstants.NODESET);     
    NodeList nodes = (NodeList) result;     
    for (int i = 0; i < nodes.getLength(); i++) {      
        System.out.println("........"+nodes.item(i).getNodeValue()+"........");      
        }   
    } 
}

Appreciate the help in advance...

Fix your XPath expression like this:

/testCodeIdentifier/subjectOf/annotation[code/@code='SPECIALNOTE']/text

You could then, for instance, access the CDATA content using

Node.getTextContent();

UPDATE : The above XPath seemed correct at the time I posted it. In the meantime, you have completely changed your XML code and now, the XPath would read

/testCodeIdentifier/subjectOf/code/subjectOf/annotation[code/@code='SPECIALNOTE']/text

Or, because I am guessing that this question is so messy, it's still wrong, just do:

//annotation[code/@code='SPECIALNOTE']/text

First, your XPath expression has an error; subjectOf is repeated unnecessarily:

/subjectOf/subjectOf

Now, assuming you really do need a reference to the code node that precedes the target text element, then use the following:

XPathExpression expr = xpath.compile(
    "/testCodeIdentifier/subjectOf/annotation/code[@code='SPECIALNOTE']");
Node node = (Node) expr.evaluate(doc, XPathConstants.NODE);
System.out.println(getNextElementSibling(node).getTextContent());

Where getNextElementSibling is defined as follows:

public static Node getNextElementSibling(Node node) {
    Node next = node;
    do {
        next = next.getNextSibling();
    } while ((next != null) && (next.getNodeType() != Node.ELEMENT_NODE));
    return next;
}

A couple of notes about this:

  • The reason that getNextSibling did not originally work for you is (most likely) because the next sibling of the referenced code element is a text node, not an element node. (The whitespace between code and text is significant.) That's why we need getNextElementSibling .
  • We're selecting a single node, so we're using XPathConstants.NODE instead if XPathConstants.NODELIST

Note that you should probably just do as @Lukas suggests and modify your XPath expression to directly select the target text.

Here's how to get the text directly (as a String):

XPathExpression expr = xpath.compile(
    "/testCodeIdentifier/subjectOf/annotation[code/@code='SPECIALNOTE']/text/text()");
String text = (String) expr.evaluate(doc, XPathConstants.STRING);
System.out.println(text);

Here's how to first get a reference to the element and then retrieve the contents of its CDATA section:

XPathExpression expr = xpath.compile(
    "/testCodeIdentifier/subjectOf/annotation[code/@code='SPECIALNOTE']/text");
Node text = (Node) expr.evaluate(doc, XPathConstants.NODE);
System.out.println(text.getTextContent());

Finally i have got the answer for my question by myself.... Below code is being working for my XML to be parsed...

  XPath xpath = XPathFactory.newInstance().newXPath();
   // XPath Query for showing all nodes value
  XPathExpression expr = xpath.compile("//testCodeIdentifier/subjectOf/order/subjectOf/annotation/code[@code='SPECIALNOTE']/following-sibling::text/text()");

  Object result = expr.evaluate(doc, XPathConstants.NODESET);
  NodeList nodes = (NodeList) result;
  for (int i = 0; i < nodes.getLength(); i++) {

      System.out.println(nodes.item(i).getNodeValue()); 

  }

Thank you people who have ansewered in this post but this is a possible solution for it. Have a mark on it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM