2016-02-29 84 views
0

我想在XML文件中搜索文本值并返回每个搜索结果的位置。Java中的Xpath - 返回搜索结果标记位置

Asuming我有这个XML文件:

<tag> 
    <tag> 
     <tag>333</tag> 
    </tag> 

    <tag> 
     <tag> 
      <tag>333</tag> 
     </tag> 
    </tag> 
</tag> 

我会寻找值“333”:

String expression = "//tag[text()=333]/ancestor::*"; 
NodeList email = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); 
String resultString = ""; 
for(int i=0; i< email.getLength();i++){ 

     Element labTest = (Element) email.item(i); 
     resultString += labTest.toString().replace("[tag: null]","tag[0]") + " "; 
    } 

我希望它返回什么是每片含2个的位置节点元素。搜索333的输出将是:

tag[0] tag[0] 
tag[0] tag[0] tag[0] 

目前搜索返回:

tag[0] tag[0] tag[0] tag[0] 

我怎样才能做到这一点?我应该以不同的方式解决问题吗?

回答

1
  1. 祖先不会被选中两次。所以根<tag>将只被选择一次。

  2. 每次迭代选择一个祖先标签;线分隔符不会自动添加。

  3. 为了获得洞察力,请为标签添加一个关卡属性(<tag l='0'>,为每个关卡添加一个更深的关卡)并输出关卡。假设你从0开始为根,并且你输出的级别你会看到输出为0112


运动,我做了下面的代码片段。第一个输出将显示所选级别的输出顺序。第二个会输出你在你的问题中需要的东西。

import java.io.StringReader; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 
import org.xml.sax.InputSource; 

public class XPathTags { 
    private static String xml1= 
"<tag l='0'>"+ 
" <tag l='1'>"+ 
"  <tag l='2'>333</tag>"+ 
" </tag>"+ 
" <tag l='1'>"+ 
"  <tag l='2'>"+ 
"   <tag l='3'>333</tag>"+ 
"  </tag>"+ 
" </tag>"+ 
"</tag>"; 

    private static String xml2= 
"<tag>"+ 
" <tag>"+ 
"  <tag>333</tag>"+ 
" </tag>"+ 
" <tag>"+ 
"  <tag>"+ 
"   <tag>333</tag>"+ 
"  </tag>"+ 
" </tag>"+ 
"</tag>"; 

    private static String xpathExpr1= 
"//tag[text()=333]/ancestor::*/@l"; 
    private static String xpathExpr2= 
"//tag[text()=333]"; 

    public static void main(String[] args) { 
     try { 
      XPath xpath = XPathFactory.newInstance().newXPath(); 
      XPathExpression expr = xpath.compile(xpathExpr1); 
      NodeList nodeList = (NodeList) expr.evaluate(new InputSource(new StringReader(xml1)),XPathConstants.NODESET); 
      String resultString = ""; 
      for(int i = 0; i != nodeList.getLength(); ++i) { 
       resultString += nodeList.item(i).getNodeValue(); 
      } 
      System.out.println(resultString); 

      resultString = ""; 
      expr = xpath.compile(xpathExpr2); 
      XPathExpression anc = xpath.compile("ancestor::*"); 
      nodeList = (NodeList) expr.evaluate(new InputSource(new StringReader(xml2)),XPathConstants.NODESET); 
      for(int i = 0; i != nodeList.getLength(); ++i) { 
       Node n = (Node) nodeList.item(i); 
       NodeList ancestors = (NodeList) anc.evaluate(n,XPathConstants.NODESET); 
       for(int j = 0; j != ancestors.getLength(); ++j) 
        resultString += ancestors.item(j).toString().replace("[tag: null]", "tag[0]"); 
       resultString += System.lineSeparator(); 
      } 
      System.out.println(resultString); 

     } catch (XPathExpressionException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

输出:

0112 
tag[0]tag[0] 
tag[0]tag[0]tag[0] 
+0

非常感谢的片段,并解释!我现在明白了:D – IvanSt

+0

@IvanSt做了一个小修改......在第二部分,内部循环应该选择'ancestors.item(j)'而不是'ancestors.item(i)'。 –

2

XPath节点集是一个没有重复的集合,所以你的代码不是你想要的。因此

  1. 选择"//tag[text()=333]/
  2. 对每个节点的选择ancestor::*并创建该结果集的输出字符串。