3

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

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

HTML 表格结构事先是未知的。Java中是否有任何API可以返回给定根节点和子节点的XPath字符串?

4

4 回答 4

1

以下是实现这一目标的一种方法(我知道)

  1. 创建 XML 的 DOM
  2. 使用“//”XPATH获取指定节点的Node
  3. 从第 2 步获得 Node 对象后,只需使用getParentNode()遍历层次结构并构建 xpath
于 2011-01-05T13:54:40.723 回答
1

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

至于您要实现的目标...以下内容应遍历整个 HTML DOM 结构并搜索具有特定 id 属性(例如 unique_id_for_tag)的“标签”(例如 div),每个条目都由闭包处理.

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();
}
于 2011-01-05T13:45:24.917 回答
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/
于 2011-01-05T14:30:19.677 回答
0

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

于 2011-01-05T13:47:26.290 回答