如何使用XPath选择多个XML元素?

时间:2018-02-05 07:11:57

标签: java xml xpath

假设以下XML:

<response>
<header>
<resultCode>0000</resultCode>
<resultMsg>OK</resultMsg>
</header>
<body>
<items>
 <item>
  <addr1>America</addr1>
  <addr2>(Atlanta)</addr2>
 </item>
 <item>
  <addr1>Canada</addr1>
  <addr2>(Toronto)</addr2>
 </item>
 <item>
  <addr1>France</addr1>
  <addr2>(Paris)</addr2>
 </item>
 </items>
</body>
</response>

我想使用XPath选择几个XML元素。 所以,我在下面编写了JAVA代码。

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                .parse(urlBuilder.toString());

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

NodeList items = (NodeList) xpath.evaluate("//item", doc, XPathConstants.NODESET );
NodeList addrAll= (NodeList) xpath.evaluate("//item/addr1 | //item/addr2", doc, XPathConstants.NODESET);

System.out.println("length:"+addrAll.getLength());      
for(int tmp=0; tmp<addrAll.getLength();tmp++){
    System.out.println(addrAll.item(tmp).getTextContent());
}

结果是:

    length:6
    America
    (Atlanta)
    Canada
    (Toronto)
    France
    (Paris)

但是,这不是我想要的。 我的预期输出:

length:3    
America (Atlanta)
Canada (Toronto)
France (Paris)

我希望你理解我的问题。 如何编辑我的代码呢?

3 个答案:

答案 0 :(得分:0)

这不是xpath的工作原理;它检索它指定的信息,但不会连接多个数据点。

为此,您可以使用xslt,也可以创建两个xpath,每个addrX部分一个,然后将Java客户端代码组合起来。

如何更新Java代码取决于几个方面,例如每个item是否始终包含addr1addr2

如果你可以依赖它,你可以这样做:

System.out.println("length:"+addrAll.getLength());      
for(int tmp=0; tmp<addrAll.getLength();tmp+=2){
    String country = addrAll.item(tmp).getTextContent();
    String city = addrAll.item(tmp+1).getTextContent();
    System.out.printf("%s %s\n", country, city);
}

答案 1 :(得分:0)

XPath 1.0提供了一组有限的数据类型:字符串,布尔值,数字和节点集。您想要的答案是三个字符串的序列,它们与现有节点不对应,并且XPath 1.0中没有这样的字符串作为三个字符串的序列。

如果您在Java世界中,那么我们没有理由将自己限制在XPath 1.0中。 XPath 2.0扩展了类型系统以允许一系列字符串,因此您可以使用//item/concat(addr1, ' ', addr2)//item/string-join(*, ' ')等表达式来获得答案。

XPath 2.0已经存在了十多年 - 是时候向前迈进了!您可能还会考虑使用比DOM更现代的树模型:JDOM2和XOM非常容易使用。

答案 2 :(得分:0)

List<WebElement> items = wd.findElements(By.xpath("//items/item"));
System.out.println("length: " + items.size());
items.forEach(item -> System.out.println(item.getText()));

输出:

length: 3 
America (Atlanta) 
Canada (Toronto) 
France (Paris)

您可以放入列表或地图。