【问题标题】:How to select all child nodes from a parent node from xml if there are many parents node with same name?如果有许多同名的父节点,如何从xml中选择父节点的所有子节点?
【发布时间】:2015-03-16 09:30:30
【问题描述】:

<?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>

问题: 我有那个 xml,它将从外部系统传给我,它可以有大量的 invoice 节点,一个 invoice 节点可以有大量的“代码”节点。我想读取所有“发票”节点的code 节点并将它们保存在这样的数组中:

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;

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

【问题讨论】:

  • xpath 通过的节点有 2 个,如果只需要一个节点,可以从节点获取。 nodes.item(0);
  • 请再看一遍问题,我做了一些修改

标签: java xml xpath


【解决方案1】:

它将同时提供,因为有两张发票尝试将 id 提供给您的 xml,例如

<invoices>
  <invoice name="invoice1">
    <obs>
    <ob>
     <code>ABC</code>
    </ob>
    </obs>
  </invoice>
<invoice name="invoice2">
    <obs>
    <ob>
     <code>DEF</code>
    </ob>
    </obs>
  </invoice>
</invoices>

然后

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

【讨论】:

  • 我无法更改 xml。有什么方法可以计算编号。特定 'inovice' 节点中的 'ob' 节点数?
  • 我真的不知道检查这是否有效 count(//invoices/invoice/obs/ob)
【解决方案2】:

你可以试试这个 xpath:

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

【讨论】:

    【解决方案3】:

    您的 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);
    

    【讨论】:

    • 但在我的情况下它不起作用。我不知道我的 xml 中的值是什么。所以我无法比较。
    • 您说,我想读取特定“发票”节点NodeList codeNodes = (NodeList) xpathExp.evaluate(document, XPathConstants.NODESET); 内的所有“代码”节点,这将给出所有代码节点,而您说,我想读取节点“代码”哪个值是 'ABC' if(code.getTextContent().equals("ABC")) 这可以解决问题。用更多的文字清楚地解释您的疑问,这可能有助于提供好的答案。
    • 好的,我的问题是,我有那个 xml,它会从外部系统传给我,它可以有大量的“发票”节点,一个“发票”节点可以有大量的“代码节点。我想读取所有“发票”节点的“代码”节点并将它们保存在这样的数组中:invoice[1].code[1]=ABC invoice[1].code[2]=123 invoice[2] .code[1]=DEF 希望对你有帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多