establecer la diferencia con XPath 1.0 - ¿cómo puedo obtener .//table sin .//table//table?

StackOverflow https://stackoverflow.com/questions/2058705

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

¿Fue útil?

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)]])]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top