XPath:生成从根节点到指定节点的相对表达式?

时间:2011-01-05 13:08:41

标签: java xpath xpath-2.0

如何生成所需的XPath表达式以从给定的根节点遍历到xml结构中的指定节点?

我将在运行时收到表的HTML片段。我必须根据某些条件找到所需的节点,并从表根节点到该节点形成一个XPath字符串并返回该节点。

事先不知道HTML表结构。 Java中是否有任何API在给定根节点和子节点的情况下返回XPath字符串?

4 个答案:

答案 0 :(得分:1)

我建议在Groovy中执行此操作,它提供GPATH(本质上是groovy语言的xpath实现。)Groovy语法非常简洁和强大,如我的blog和与Java语言无缝混合(groovy编译为java类文件)。

至于你想要实现的目标......以下内容应遍历整个HTML DOM结构并搜索具有特定id属性的“标记”(例如div)(例如unique_id_for_tag),其中每个条目都被处理关闭。

HTML.body.'**'.findAll {  it.name() == 'tag' && it["@id"] == 'tag_name' }.each { 
//"it" is the return value
if(it.td[0].text().toString().trim().contains('Hello')){
   var x = it.td[0].text().toString().trim();
}

答案 1 :(得分:1)

以下是实现此目的的一种方式(我知道)

  1. 创建XML的XML
  2. 使用“//”XPATH
  3. 获取指定节点的节点
  4. 从步骤2获得Node对象后,只需使用 getParentNode()遍历层次结构并构建xpath

答案 2 :(得分:1)

这不能(仅限)在纯XPath 1.0中完成。

XPath 2.0解决方案

if(not($vStart intersect $vTarget/ancestor::*))
  then ()
  else
   for $vPath in
      string-join
          ((for $x in
                $vTarget
                  /ancestor-or-self::*[. >> $vStart]
                    /concat(name(.),
                            for $n in name(.),
                                $cn in count(../*[name(.) eq $n])
                             return
                               if($cn ge 2)
                                 then concat('[', 
                                               count((preceding-sibling::*
                                                              [name() eq $n]) +1, 
                                             ']')
                                 else (),
                            '/'
                               )
               return $x),
              ''
           )
           return string-join((concat(name($vStart), '/'),$vPath), '')

根据以下XML文档评估此XPath 2.0表达式时

<table>
  <tr>
    <td><b>11</b></td>
    <td><i>12</i></td>
  </tr>
  <tr>
    <td><p><b>21</b></p></td>
    <td><p><b>221</b></p><p><b><i>222</i></b></p></td>
  </tr>
  <tr>
    <td><b>31</b></td>
    <td><i>32</i></td>
  </tr>
</table>

如果两个参数定义为

  <xsl:variable name="vStart" select="/*"/>
  <xsl:variable name="vTarget" select="/*/tr[2]/td[2]/p[2]/b/i"/>

然后上面评估XPath 2.0表达式的结果是:

table/tr[2]/td[2]/p[2]/b/i/

答案 3 :(得分:0)

如果您知道要尝试选择的根元素和子元素的名称,并且如果只有一个具有该名称的子元素,则可以使用“/ root // child”。但也许我误解了你想要实现的目标。你能举个例子吗?