establecer la diferencia con XPath 1.0 - ¿cómo puedo obtener .//table sin .//table//table?
-
20-09-2019 - |
Pregunta
Estoy tratando de encontrar todas las tablas a mi nodo actual , sin que también incluye las tablas anidadas. En otras palabras, si lo he entendido, quiero encontrar "sí" y no "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>
¿Hay alguna forma fácil de hacer esto en XPath 1.0? (En la versión 2.0, que sería .//table except .//table//table
, pero no tengo un 2.0 como una opción.)
EDIT: por favor, las respuestas hasta el momento no están respetando la idea de nodo de contexto actual. No sé hasta qué punto abajo de la primera capa de la mesa podría ser (y que puede ser diferente), y yo también, no sé si yo podría estar dentro de otra tabla (o dos o tres).
Literalmente, yo quiero lo .//table except .//table//table
en XPath 2.0 sería, pero sólo tengo XPath 1.
Solución 5
Después de investigar aquí y en otras partes, la respuesta parece ser "no se puede, y es por eso que tenemos XPath 2.0". Oh, bueno.
Otros consejos
Creo que quieres child :: mesa de alias
#!/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]
y segunda parte
#!/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>
Bueno, si yo lo entiendo, la content_list puede resolver:
my $table_one = $tree->findnodes('/html//table')->[1];
for ( $table_one->content_list ) {
last if $_->exists('table');
print $_->as_text;
}
:)
¿Qué hay de .//table[not(.//table)]
? Lo sentimos por razones de brevedad, estoy en mi teléfono.
No sé cómo sacar el nodo de contexto a ser evaluado en los predicados anidados, pero lo que se necesita es algo como esto:
descendant::table[not(ancestor::table[ancestor::div])]
sólo con la capacidad de hacer referencia al nodo de contexto, en lugar de div
Editar : Si define una variable para el nodo de contexto,
<xsl:variable name="contextNode" select="." />
A continuación, se puede hacer referencia a ella en el predicado XPath:
descendant::table[not(ancestor::table[ancestor::*[generate-id(.)=generate-id($contextNode)]])]