Set the difference with XPath 1.0 - how do I get it. // table without .// table // table?

I am trying to find all tables under my current node , not including nested tables. In other words, if I have this, I want to find yes, not no:

<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> 

Is there an easy way to do this in XPath 1.0? (In version 2.0 it will be .//table except .//table//table , but I don't have version 2.0 as an option.)

EDIT:, the answers do not yet correspond to the idea of ​​the current context node. I don’t know how far the first layer of the table can be (and it can be different), and I also don’t know if I can be inside another table (or two or three).

Literally, I want what .//table except .//table//table in XPath 2.0 will be, but I only have XPath 1.

+4
source share
5 answers

After exploring this here and elsewhere, the answer seems to be "you cannot, and therefore we have XPath 2.0." Oh good.

0
source

I think you want child :: table aka table

 #!/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 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] 

and second part

 #!/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
source

Well, if I understand this, content_list can solve:

 my $table_one = $tree->findnodes('/html//table')->[1]; for ( $table_one->content_list ) { last if $_->exists('table'); print $_->as_text; } 

:)

0
source

What about .//table[not(.//table)] ? Sorry for the brevity, I am on my phone.

0
source

I don't know how to get the node context to be evaluated in nested predicates, but what you need is something like this:

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

only with the ability to refer to the node context instead of the strike strike div >

EDIT : if you set a variable for the node context,

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

then you can reference it in the XPATH predicate:

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

All Articles