Read inside a Specific Tag using XPath with multip

2020-08-01 20:00发布

问题:

<?xml version="1.0" encoding="UTF-8"?>
-<ADOXML adoversion="Version 5.1" username="kvarga" database="adonisdb" time="08:55"   date="30.11.2013" version="3.1">
-<MODELS>
-<MODEL version="" applib="ADONIS BPMS BP Library 5.1" libtype="bp" modeltype="Business process model" name="Product development" id="mod.25602">
 -<MODELATTRIBUTES>
<ATTRIBUTE name="Version number" type="STRING"> </ATTRIBUTE>
<ATTRIBUTE name="Author" type="STRING">kvarga</ATTRIBUTE>
<ATTRIBUTE name="Creation date" type="STRING">2013-11-30, 08:50</ATTRIBUTE>
<ATTRIBUTE name="Date last changed" type="STRING">2013-11-30, 08:54:46</ATTRIBUTE>

-<INSTANCE name="Business Opportunities census" id="obj.25615" class="Activity">
<ATTRIBUTE name="Position" type="STRING">NODE x:6.5cm y:10.5cm index:7</ATTRIBUTE>

<ATTRIBUTE name="External tool coupling" type="STRING"> </ATTRIBUTE>
<ATTRIBUTE name="Description" type="STRING">I WANT THIS PARA 1</ATTRIBUTE>


<ATTRIBUTE name="Version number" type="STRING"> </ATTRIBUTE>
<ATTRIBUTE name="Author" type="STRING">kvarga</ATTRIBUTE>
<ATTRIBUTE name="Creation date" type="STRING">2013-11-30, 08:50</ATTRIBUTE>
<ATTRIBUTE name="Date last changed" type="STRING">2013-11-30, 08:54:46</ATTRIBUTE>

-<INSTANCE name="Business Opportunities census" id="obj.25615" class="Activity">
<ATTRIBUTE name="Position" type="STRING">NODE x:6.5cm y:10.5cm index:7</ATTRIBUTE>
<ATTRIBUTE name="Description" type="STRING">I WANT THIS PARA 2</ATTRIBUTE>
</INSTANCE>


 </MODEL>

 </MODELS>

 </ADOXML>

Hye There I want to read this xml file and need to get the text inside the tag given as:

 <ATTRIBUTE name="Description" type="STRING">

I have been Trying to get the results using my code as:

 DocumentBuilderFactory builderFactory =
    DocumentBuilderFactory.newInstance();
  DocumentBuilder builder = null;
try {

builder = builderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = builder.parse(
        new FileInputStream("c:\\y.xml"));

        XPath xPath =  XPathFactory.newInstance().newXPath();

       String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[@name='Description'and @type='STRING']";
   System.out.println(expression);
   NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue()); 
}


} catch (ParserConfigurationException | SAXException | IOException e) {
System.out.print(e);
}       

There is a problem with my code cant figure out what!

My code works fine if i use XPath expression as:

String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[@type='STRING']";

It works fine but my specific Tag to read from is:

   <ATTRIBUTE name="Description" type="STRING"> I WANT THIS PARA 1 </ATTRIBUTE>

so that the output should be:

   I WANT THIS PARA 1
   I WANT THIS PARA 2

Thanks in advance

回答1:

Try this expression for your XPath.

String expression = "//ADOXML//MODELS//MODEL//MODELATTRIBUTES//ATTRIBUTE[@name='Description' and @type='STRING'] | //ADOXML//MODELS//MODEL//MODELATTRIBUTES//INSTANCE/ATTRIBUTE[@name='Description' and @type='STRING']";

It is displaying both Attributes tag with name = 'Description' 1) directly accessed under MODELATTRIBUTES tag and 2) under the INSTANCE tag



回答2:

I think that what you have is fine, you just need to add /text() to the end of your expression to get the text node from the element.

Also as you are accessing the text node directly you no longer need to call getFirstChild on the node, which could be problematic if there is more than one text node anyway!

You can also use eq instead of = when looking for the attribute values as they will always be atomic in your example. I also think that whilst the two forms are semantically equivalent, syntactically it looks better to use two predicates back to back rather than and (at least to me ;-))

String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[@name eq 'Description'][@type eq 'STRING']/text()";

System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
    System.out.println(nodeList.item(i).getNodeValue()); 
}


回答3:

According to my Given XML File my XPath Expression should be:

String expression = "/ADOXML/MODELS/MODEL/INSTANCE/ATTRIBUTE[@name='Description' and @type='STRING']";

and it works bingo!



回答4:

try this:

List<String> list = new ArrayList<>();
            try {
                XPathExpression expr =
                    xpath.compile(//ATTRIBUTE[@name='description']/text()");
                NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
                for (int i = 0; i < nodes.getLength(); i++)
                    list.add(nodes.item(i).getNodeValue());
            } catch (XPathExpressionException e) {
                e.printStackTrace();
            }
            return list;

more examples xpath with java:

public static String obtenirTextNodoMultiple(Document doc, String nodo)
  {
    String resultat = "";
    int i = 0;
    boolean trobat = true;
    try
    {
      if (doc != null)
        while ((resultat.equals("")) && (trobat)) {
          String valor = doc.getElementsByTagName(nodo).item(i).getTextContent();

          if (valor != "") {
            trobat = false;
            if (!trobat) resultat = valor;
          }
          i++;
        }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    return resultat;
  }

  public static String recValorFiltreFill(String pare*father*, String nodeComparar*node to compare*, String valorAComparar*value to compare*, Document doc, String nodo*node*)
  {
    String resultat = "";
    try {
      XPath xpath = XPathFactory.newInstance().newXPath();
      XPathExpression expr = null;

      if (doc != null)
      {
        if ((pare.equals("")) && (valorAComparar.equals(""))) {
          expr = xpath.compile("//" + nodo);
        }
        else if (valorAComparar.equals("")) {
          expr = xpath.compile("//" + pare + "/" + nodo);
        }
        else {
          expr = xpath.compile("//" + pare + "[" + nodeComparar + "='" + valorAComparar + "']/" + nodo);
        }

        resultat = (String)expr.evaluate(doc, XPathConstants.STRING);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    return resultat;
  }