2010-01-13 4 views
4

Я пытаюсь найти все таблицы ниже моего текущего узла без включения вложенных таблиц. Другими словами, если у меня есть это, я хочу найти «да», а не «нет»:Установить разницу с XPath 1.0 - как мне получить .//table без .//table//table?

<table> <!-- outer table - no --> 
    <tr><td> 
    <div> <!-- *** context node *** --> 
     <table> <!-- yes --> 
     <tr><td> 
      <table> ... </table> <!-- no --> 
     </td></tr> 
     </table> 
     <table> <!-- yes --> 
     <tr><td> 
      <table> ... </table> <!-- no --> 
     </td></tr> 
     </table> 
    </div> 
    </td></tr> 
</table> 

Есть ли простой способ сделать это в XPath 1.0? (В версии 2.0 было бы .//table except .//table//table, но я не имею 2.0 в качестве опции.)

EDIT: пожалуйста, ответы до сих пор не уважающие идею текущего узла контекста. Я не знаю, насколько далеко может быть первый слой таблицы (и может отличаться), и я также не знаю, могу ли я быть внутри другой таблицы (или двух или трех).

Буквально, я хочу, что .//table except .//table//table в XPath 2.0 будет, но у меня есть только XPath 1.

+0

Я думаю, что невозможно написать только один XPath 1.0, потому что мне нужно использовать один контекст несколько раз, и это запрещено. Могу ли я использовать два XPaths, один XPath для получения значения переменной и 2-й XPath для получения требуемых таблиц? – Gaim

+0

Вы сделали это CW по какой причине? Это довольно сложный вопрос, который будет иметь правильный ответ, а не кандидат на CW. – AnthonyWJones

+0

Что такое «CW»? И кто вы обращаетесь как «вы» там? Меня? Как я сделал это «CW»? :) –

ответ

0

После изучения его здесь и в других местах, то ответ, кажется, «вы не можете, и именно поэтому у нас есть XPath 2.0». Ну что ж.

0

Я думаю, что вы хотите ребенка :: таблица ака таблица

#!/usr/bin/perl -- 
use strict; 
use warnings; 

use HTML::TreeBuilder; 
{ 
    my $tree = HTML::TreeBuilder->new(); 

    $tree->parse(<<'__HTML__'); 
<table> <!-- outer table - no --> 
    <tr><td> 
    <div> <!-- *** context node *** --> 
     <table> <!-- yes --> 
     <tr><td> 
      <table> ... </table> <!-- no --> 
     </td></tr> 
     </table> 
     <table> <!-- yes --> 
     <tr><td> 
      <table> ... </table> <!-- no --> 
     </td></tr> 
     </table> 
    </div> 
    </td></tr> 
</table> 
__HTML__ 

    sub HTML::Element::addressx { 
    return join(
     '/', 
     '/', # // ROOT 
     reverse( # so it starts at the top 
     map { 
      my $n = $_->pindex() || '0'; 
      my $t = $_->tag; 
      $t . '['. $n .']' 
      }   # so that root's undef -> '0' 
      $_[0], # self and... 
     $_[0]->lineage 
    ) 
    ); 
    } ## end sub HTML::Element::addressx 

    for my $td ($tree->look_down(_tag => qr/div|table/i)) { 
    print $td->addressx, "\n"; 
    } 
    $tree->delete; 
    undef $tree; 
} 
__END__ 
//html[0]/body[1]/table[0] 
//html[0]/body[1]/table[0]/tr[0]/td[0]/div[0] 
//html[0]/body[1]/table[0]/tr[0]/td[0]/div[0]/table[0] 
//html[0]/body[1]/table[0]/tr[0]/td[0]/div[0]/table[0]/tr[0]/td[0]/table[0] 
//html[0]/body[1]/table[0]/tr[0]/td[0]/div[0]/table[1] 
//html[0]/body[1]/table[0]/tr[0]/td[0]/div[0]/table[1]/tr[0]/td[0]/table[0] 

и вторая часть

#!/usr/bin/perl -- 

use strict; 
use warnings; 

use HTML::TreeBuilder::XPath; 

my $tree = HTML::TreeBuilder::XPath->new; 
$tree->parse_content(<<'__HTML__'); 
<table> <!-- outer table - no --> 
    <tr><td> 
    <div> <!-- *** context node *** --> 
     <table> <!-- yes --> 
     <tr><td> 
      <table> ... </table> <!-- no --> 
     </td></tr> 
     </table> 
     <table> <!-- yes --> 
     <tr><td> 
      <table> ... </table> <!-- no --> 
     </td></tr> 
     </table> 
    </div> 
    </td></tr> 
</table> 
__HTML__ 



#~ for my $result ($tree->findnodes(q{//html[0]/body[1]/table[0]/tr[0]/td[0]/div[0]})) { 
for my $result ($tree->findnodes(q{/html/body/table/tr/td/div})) { 
    print $result->as_HTML,"\n\n"; 
    for my $table($result->findnodes(q{table})){ ## child::table 
     print "$table\n"; 
     print $table->as_HTML,"\n\n\n"; 
    } 

} 

__END__ 
<div><table><tr><td><table><tr><td> ... </td></tr></table></td></tr></table><table><tr><td><table><tr><td> ... </td></tr></table></td></tr></table></div> 


HTML::Element=HASH(0xc6c964) 
<table><tr><td><table><tr><td> ... </td></tr></table></td></tr></table> 



HTML::Element=HASH(0xc6cbf4) 
<table><tr><td><table><tr><td> ... </td></tr></table></td></tr></table> 
+0

Нет, не соблюдая контекстный узел. –

0

Ну, если я понимаю, content_list может решить:

my $table_one = $tree->findnodes('/html//table')->[1]; 

for ($table_one->content_list) { 
    last if $_->exists('table'); 
    print $_->as_text; 
} 

:)

+0

Нет. Это не соответствует узлу контекста. –

0

Что относительно .//table[not(.//table)]? Извините за краткость, я нахожусь по телефону.

+0

Нет, это находит все таблицы, в которых нет таблиц. Я хочу, чтобы все таблицы были не в таблицах. –

+0

OK, как насчет .//table[not(ancestor::table)]? Это, скорее всего, будет неэффективным, хотя, если вы не делаете это в чем-то вроде eXist, у которого есть индексы для его поддержки. –

+0

Нет. Это находит все таблицы, если они не находятся в * любой * таблице. Но подумайте, что произойдет, если наш контекстный узел уже находится внутри таблицы. Он ничего не нашел *. Нет, не ответ. –

0

Я не знаю, как получить узел контекста, чтобы оценить в вложенных предикатах, но то, что вам нужно, это что-то вроде этого:

descendant::table[not(ancestor::table[ancestor::div])] 

только с возможностью ссылаться на узле контекста вместо div

EDIT: Если вы установите переменную для узла контекста,

<xsl:variable name="contextNode" select="." /> 

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

descendant::table[not(ancestor::table[ancestor::*[generate-id(.)=generate-id($contextNode)]])] 
+0

Да, это все равно не сработает, поскольку оно будет исключать любые таблицы, которые находятся внутри любой таблицы, находящейся внутри любого div. :) Не уважая контекст снова. –

+0

Обновлен мой ответ. Это не чистый XPATH, а XPATH 1.0 (и XSLT 1.0). –

+0

Да, здесь нет XSLT. Так что это тоже не делается. {Вздох}. –