2012-05-05 59 views
2

首先,我必须说我发现Xpath是一个非常好的解析器,并且在将其与其他解析器进行比较时,我觉得它非常强大。如何使用Xpath检索节点之后的XML树节点?

考虑下面的代码:

DocumentBuilderFactory domFactory = 
    DocumentBuilderFactory.newInstance(); 
    domFactory.setNamespaceAware(true); 
    DocumentBuilder builder = domFactory.newDocumentBuilder(); 
    Document doc = builder.parse("input.xml"); 
    XPath xpath = XPathFactory.newInstance().newXPath(); 

如果我想找到回合1 &门1,这里的first节点:

<Game> 
    <Round> 
     <roundNumber>1</roundNumber> 
     <Door> 
      <doorName>abd11</doorName> 
      <Value> 
       <xVal1>0</xVal1> 
       <xVal2>25</xVal2> 
       <pVal>0.31</pVal> 
      </Value> 
      <Value> 
       <xVal1>25</xVal1> 
       <xVal2>50</xVal2> 
       <pVal>0.04</pVal> 
      </Value> 
      <Value> 
       <xVal1>50</xVal1> 
       <xVal2>75</xVal2> 
       <pVal>0.19</pVal> 
      </Value> 
      <Value> 
       <xVal1>75</xVal1> 
       <xVal2>100</xVal2> 
       <pVal>0.46</pVal> 
      </Value> 
     </Door> 
     <Door> 
      <doorName>vvv1133</doorName> 
      <Value> 
       <xVal1>60</xVal1> 
       <xVal2>62</xVal2> 
       <pVal>1.0</pVal> 
      </Value> 
     </Door> 
    </Round> 
    <Round> 
     <roundNumber>2</roundNumber> 
     <Door> 
      <doorName>eee</doorName> 
      <Value> 
       <xVal1>0</xVal1> 
       <xVal2>-25</xVal2> 
       <pVal>0.31</pVal> 
      </Value> 
      <Value> 
       <xVal1>-25</xVal1> 
       <xVal2>-50</xVal2> 
       <pVal>0.04</pVal> 
      </Value> 
      <Value> 
       <xVal1>-50</xVal1> 
       <xVal2>-75</xVal2> 
       <pVal>0.19</pVal> 
      </Value> 
      <Value> 
       <xVal1>-75</xVal1> 
       <xVal2>-100</xVal2> 
       <pVal>0.46</pVal> 
      </Value> 
     </Door> 
     <Door> 
      <doorName>cc</doorName> 
      <Value> 
       <xVal1>-60</xVal1> 
       <xVal2>-62</xVal2> 
       <pVal>0.3</pVal> 
      </Value> 
      <Value> 
       <xVal1>-70</xVal1> 
       <xVal2>-78</xVal2> 
       <pVal>0.7</pVal> 
      </Value> 
     </Door> 
    </Round> 
</Game> 

我会做到这一点:

XPathExpression expr = xpath.compile("//Round[1]/Door[1]/Value[1]/*/text()");  
    Object result = expr.evaluate(doc, XPathConstants.NODESET); 
    NodeList nodes = (NodeList) result; 

如果我想second第1回合的节点&门1,则:我这样做是使用一个循环,因为我不知道我有多么Value-nodes有,这意味着我这怎么能使用一个循环,其中每个迭代我取回3做

XPathExpression expr = xpath.compile("//Round[1]/Door[1]/Value[2]/*/text()"); 

但怎么办(我的意思是xVal1,xVal2pVal值)Value节点的更多值!

询问这种情况的原因是:

  1. 我不知道我是多么Round -s有

  2. 我不知道我是多么Value -s有

  3. 我不想每次都宣布了新的XPathExpression

谢谢。

+0

使用XPath的count()函数查找节点的数量,然后使用(嵌套)循环: –

+0

为什么不使用多个表达式?是不是你想要的东西(例如首先得到回合,然后门,然后值的列表) – erikxiv

+0

@erikxiv:问题是每个回合有2个字段,一个是“roundNumber”,第二个是“门”。现在只有一个查询,即XPathExpression,我只能得到但不是两个?因为从我现在看到的情况来看,我必须做2个查询 - 一个用于“roundNumber”字段,另一个用于每个回合的“门”......等等 – ron

回答

7

选项1 - 遍历文档中的所有Value元素。只需要进行一次评估,但很难知道该值属于哪个Round或Door元素。

NodeList result = (NodeList) xpath.evaluate("//Round/Door/Value/*/text()", doc, XPathConstants.NODESET); 

选项2 - 遍历每一轮中,门和单独值的元素。需要更多评估,但上下文很容易知道。如果需要索引,则很容易为循环添加计数器。

// Get all rounds and iterate over them 
NodeList rounds = (NodeList) xpath.evaluate("//Round", doc, XPathConstants.NODESET); 
for (Node round : rounds) { 
    // Get all doors and iterate over them 
    NodeList doors = (NodeList) xpath.evaluate("Door", round, XPathConstants.NODESET); 
    for (Node door : doors) { 
    // Get all values and iterate over them 
    NodeList values = (NodeList) xpath.evaluate("Value/*/text()", door, XPathConstants.NODESET); 
    for (Node value : values) { 
     // Do something 
    } 
    } 
} 

选项3 - 做你的要求根据以上的一些组合

请注意,我已经去除了表达编译步骤缩短的例子。应该重新添加以提高性能。

+0

哪个'NodeList'类使用的是实现'Iterable'? – majorbanzai

+0

@majorbanzai您是否想过增强的for-loops语法?我怀疑你是对的,因为'NodeList'不是'Iterable',代码示例将不起作用。虽然... – erikxiv

+0

Nodelist不能像这样迭代。 – viruskimera