Выражение Xpath для доступа к родителю или брату с помощью модуля HTML :: TreeBuilder :: XPath - PullRequest
2 голосов
/ 14 октября 2011

Я хочу выбрать родительский или родной узел для узла, используя модуль Perl HTML :: TreeBuilder :: XPath. Давайте возьмем пример HTML следующим образом:

<tbody>
    <tr>
        <td class="c1">Match_Text</td>
        <td class="c2">Extact_Text</td>
    </tr>
    <tr>
        <td class="c1"></td>
        <td class="c2"></td>
    </tr>
</tbody>

Поэтому я хочу извлечь текст "Match_Text"для этого я даю выражение xpath как:

'/html/body//td[@class="c1"]="Match_Text"/../td[@class="c2"]'

, которое является допустимым выражением для моего варианта использования.

Но похоже, что переход к родительскому элементу не реализован, и я получаю следующую ошибку из модуля perl:

axis axis_parent не реализован [Не удается найти метод объекта "getParentNode" через пакет "XML :: XPathEngine :: Literal" в /usr/local/share/perl/5.10.1/XML/XPathEngine / Step.pm, строка 326.]

Может кто-нибудь предложить альтернативное выражение Xpath, которое может работать для моего варианта использования (доступ к родителю / брату узла).Обратите внимание, что я хочу сделать это только с использованием выражения Xpath и не хочу создавать DOM и явно проходить по дереву.

Ответы [ 3 ]

3 голосов
/ 14 октября 2011

Сообщение об ошибке вводит в заблуждение. Проблема не в отсутствии поддержки, а в том, что вы пытаетесь найти родителя логического значения, возвращенного сравнением. У него его нет.

Вы можете использовать

//*[ td[@class="c1" and text()="Match_Text"] ]/td[@class="c2"]

//td[@class="c1" and text()="Match_Text"]/following-sibling::*

//td[@class="c1" and text()="Match_Text"]/following-sibling::td[@class="c2"]

//td[@class="c1" and text()="Match_Text"]/../td[@class="c2"]
0 голосов
/ 14 октября 2011

Я хочу выбрать родителя или брата узла, используя HTML :: TreeBuilder :: XPath Perl модуль.

В любом случае, если вы хотите иметь выражение XPath, которое выбирает несколько узлов, и вы знаете отдельное выражение XPath для каждого из них, вы можете просто использовать стандартный оператор объединения XPath |, как показано ниже:

 (/*/body//*[td[@class="c1"and . = 'Match_Text']])[1]
|
  (/*/body//*[td[@class="c1"and . = 'Match_Text']])[1]
               /td[[@class="c1"and not(. = 'Match_Text')]

В этом выражении XPath первый операнд оператора | является родительским элементом ссылочного узла, а второй аргумент оператора объединения - это выражение, которое выбирает все дочерние элементы этого родителя, чье строковое значение отличается от это ссылочного узла.

В результате выбирается объединение двух наборов узлов.

0 голосов
/ 14 октября 2011

Я не видел ни одного рабочего выражения, подобного этому.На самом деле, я думаю, что ошибка связана с тем, что выражение неправильно составлено и разбирается.

В любом случае, здесь есть две альтернативы для вашей цели - хотя и не проверенные с указанным модулем Perl:

//td[@class="c1" and text()="Match_Text"]/../td[@class="c2"]
//td[@class="c2" and ../td[@class="c1" and text()="Match_Text"]]

Проверено на shell-tools и online-toolz .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...