繁体   English   中英

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

[英]XPath: generate a relative expression from a root node to a specified node?

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

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

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

我建议在Groovy中提供这个,它提供GPATH (本质上是groovy语言的xpath实现。)Groovy语法非常简洁和强大,如我的博客中所述,并与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. 创建XML的DOM
  2. 使用“//”XPATH获取指定节点的节点
  3. 从步骤2获得Node对象后,只需使用getParentNode()遍历层次结构并构建xpath即可

这不能(仅)在纯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/

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM