如果有多个父节点具有相同名称,如何从xml中选择父节点中的所有子节点?

时间:2015-03-16 09:30:31

标签: java xml xpath



<?xml version="1.0" encoding="UTF-8"?>
<invoice>
        <obs>
        <ob>
         <code>ABC</code>
        </ob>
        <ob>
         <code>123</code>
        </ob>
        </obs>
      </invoice>
    <invoice>
        <obs>
        <ob>
         <code>DEF</code>
        </ob>
        </obs>
      </invoice>
    </invoices>
&#13;
&#13;
&#13;

问题: 我有来自外部系统的xml,它可以有大量invoice个节点,一个invoice节点可以有大量的代码&#39;节点。我想阅读所有&#39;发票的code个节点&#39;节点并将它们保存在这样的数组中:

invoice[1].code[1]=ABC 
invoice[1].code[2]=123 
invoice[2].code[1]=DEF

如何在JAVA中使用XPathExpression执行此操作。我的代码在下面不起作用。

expr = xpath.compile("//invoices/invoice/obs/ob/code/text()");

 result1=expr.evaluate(dc, XPathConstants.NODESET);

nodes =(NodeList)result1;

如果节点数很高,请给出一些通用解决方案。

3 个答案:

答案 0 :(得分:0)

它会同时给出两个发票,试着给你的xml提供id,如

&#13;
&#13;
<invoices>
  <invoice name="invoice1">
    <obs>
    <ob>
     <code>ABC</code>
    </ob>
    </obs>
  </invoice>
<invoice name="invoice2">
    <obs>
    <ob>
     <code>DEF</code>
    </ob>
    </obs>
  </invoice>
</invoices>
&#13;
&#13;
&#13;

然后

&#13;
&#13;
expr = xpath.compile("//invoices[@name='invoice1']/invoice/obs/ob/code/text()");
&#13;
&#13;
&#13;

答案 1 :(得分:0)

xpath传递了2个节点。你可以试试这个。

    String xml = "<invoices><invoice><obs><ob><code>ABC</code></ob><ob><code>111</code></ob></obs></invoice><invoice><obs><ob><code>DEF</code></ob></obs></invoice></invoices>";
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder =factory.newDocumentBuilder();
    Document document  = builder.parse(new InputSource(new StringReader(xml)));
    XPathFactory xpathFactory = XPathFactory.newInstance();

    Map<String,List<String>> invoiceCodeMap = new LinkedHashMap<>();
    XPathExpression invoiceXpathExp = xpathFactory.newXPath().compile("//invoices/invoice");
    NodeList invoiceNodes = (NodeList) invoiceXpathExp.evaluate(document, XPathConstants.NODESET);
    //Iterate Invoice nodes
    for(int invoiceIndex=0;invoiceIndex<invoiceNodes.getLength();invoiceIndex++){
        String invoiceID = "invoice"+(invoiceIndex+1);
        List<String> codeList = new ArrayList<>();
        XPathExpression codeXpathExp = xpathFactory.newXPath().compile("obs/ob/code/text()");
        NodeList codeNodes = (NodeList) codeXpathExp.evaluate(invoiceNodes.item(invoiceIndex), XPathConstants.NODESET);
        for(int codeIndex=0;codeIndex<codeNodes.getLength();codeIndex++){
            Node code = codeNodes.item(codeIndex);
            codeList.add(code.getTextContent());
        }
        invoiceCodeMap.put(invoiceID, codeList);
    }
    System.out.println(invoiceCodeMap);

答案 2 :(得分:0)

你可以尝试这个xpath:

//invoices/invoice[descendant::code[.='ABC']]/obs/ob/code