Найти узлы до состояния, используя XPath - PullRequest
2 голосов
/ 24 июля 2011

Какое выражение следует использовать, чтобы найти все td узлы после одного, который содержит текст Foo или Bar и остановиться перед следующим <td colspan="4"> с неизвестным текстом. Спасибо.

<td colspan="4">Foo || Bar</td>
<td rowspan="4">TEXT1</td>
<td valign="top">TEXT2</td>
<td valign="top">TEXT3</td>
...
<td colspan="4">VARIABLE</td>
...

UPDATE:

use strict; 
use warnings;
use autodie;
use utf8;
use WWW::Mechanize;
use HTML::TreeBuilder::XPath;

my $url = 'www.perl.org';

my $mech = WWW::Mechanize->new;
$mech->agent_alias( 'Windows Mozilla' );
$mech->get( $url );

my $tree= HTML::TreeBuilder::XPath->new;

$tree->parse($mech->content);

for my $nodes ($tree->findnodes('//td[
                            preceding-sibling::td
                            [contains(., "Foo") or contains(., "Bar")] 
                            and following-sibling::td[@colspan="4"]
                            ]')) {

    print $nodes->as_text;

}

Ответы [ 2 ]

1 голос
/ 24 июля 2011

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

//td[
      preceding-sibling::td
            [contains(., 'Foo') or contains(., 'Bar')] 
      and following-sibling::td[@colspan = 4]
]

Будет возвращено:

<td rowspan="4">TEXT1</td>
<td valign="top">TEXT2</td>
<td valign="top">TEXT3</td>
0 голосов
/ 24 июля 2011

Хорошо, с XPath 2.0 и XQuery 1.0 есть операторы << и >>, которые полезны для выражения таких условий, как, например, у вас. с XQuery вы можете красиво написать

let $tr := <tr>
<td colspan="4">Foo || Bar</td>
<td rowspan="4">TEXT1</td>
<td valign="top">TEXT2</td>
<td valign="top">TEXT3</td>
.....
<td colspan="4">VARIABLE</td>
</tr>
let $td1 := $tr/td[contains(., 'Foo') or contains(., 'Bar')][1]
let $td2 := $td1/following-sibling::td[@colspan = 4][1]
return $tr/td[. >> $td1 and . << $td2]

чтобы найти 'td элементы "между" этими двумя другими td элементами.

Очевидно, что в XPath 2.0 у вас нет функции let и return, поэтому вам нужно будет попытаться объединить все в одно выражение:

$tr/td[. >> $tr/td[contains(., 'Foo') or contains(., 'Bar')][1] and . << $tr/td[contains(., 'Foo') or contains(., 'Bar')][1]/following-sibling::td[@colspan = 4][1]]

, где $tr - это узел контекста.

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