XPath: сгенерировать относительное выражение от корневого узла к указанному узлу? - PullRequest
3 голосов
/ 05 января 2011

Как мне сгенерировать требуемое выражение XPath для прохождения от указанного корневого узла к указанному узлу вниз по структуре XML?

Я получу HTML-фрагмент таблицы во время выполнения.Мне нужно найти нужный узел на основе некоторых критериев и сформировать строку XPath от корневого узла таблицы до этого узла и вернуть ее.

Структура таблицы HTML заранее неизвестна.Есть ли какой-либо API в Java, который возвращает строку XPath, заданную корневым узлом и дочерним узлом?

Ответы [ 4 ]

1 голос
/ 05 января 2011

Это не может быть сделано (только) в чистом 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), '')

Когда это выражение XPath 2.0 сравнивается со следующим XML-документом :

<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/
1 голос
/ 05 января 2011

Ниже приведен один из способов (который я знаю) для достижения этого

  1. Создание DOM XML
  2. Получение узла указанного узла с использованием "//"XPATH
  3. Как только вы получите объект Node из шага 2, вам нужно просто пройти по иерархии, используя getParentNode () и создать xpath
1 голос
/ 05 января 2011

Я бы порекомендовал сделать это в Groovy , который обеспечивает GPATH (по сути, реализация xpath для языка groovy.) Синтаксис Groovy очень лаконичен и мощен, как описано в моем blog и легко смешивается с языком Java (groovy компилируется в файлы классов java).

Что касается того, чего вы пытаетесь достичь ... следующее должно пройти по всей структуре HTML DOM и найти «тег» (например, div) с определенным атрибутом id (например, 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();
}
0 голосов
/ 05 января 2011

Если вам известны имена корневого элемента и дочернего элемента, который вы пытаетесь выбрать, и если существует только один дочерний элемент с таким именем, вы можете использовать просто «/ root // child».Но, возможно, я неправильно понял, чего вы пытались достичь.Не могли бы вы привести пример?

...