Régler la différence avec XPath 1.0 - comment puis-je obtenir .//table sans .//table//table?

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

  •  20-09-2019
  •  | 
  •  

Question

Je suis en train de trouver toutes les tables ci-dessous mon noeud courant sans inclure aussi les tables imbriquées. Autrement dit, si j'ai, je veux trouver « oui » et non « non »:

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

Yat-il un moyen facile de le faire dans XPath 1.0? (En 2.0, il serait .//table except .//table//table, mais je ne pas de 2.0 en option.)

EDIT: s'il vous plaît, les réponses à ce jour ne respectent pas l'idée du noeud contexte actuel. Je ne sais pas jusqu'à quel point sur la première couche de table peut être (et il peut être différent), et je aussi ne sais pas si je pourrais être dans une autre table (ou deux ou trois).

Littéralement, je veux ce .//table except .//table//table dans XPath 2.0 serait, mais je ne XPath 1.

Était-ce utile?

La solution 5

Après avoir étudié ici et ailleurs, la réponse semble être « vous ne pouvez pas, et c'est la raison pour laquelle nous avons XPath 2.0 ». Eh bien.

Autres conseils

Je pense que vous voulez enfant :: table de ping-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]

et la seconde partie

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

Eh bien, si je comprends bien, le content_list peut résoudre:

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

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

:)

Qu'en est-il .//table[not(.//table)]? Désolé pour être bref, je suis sur mon téléphone.

Je ne sais pas comment obtenir le nœud de contexte à évaluer dans les prédicats imbriquées, mais ce que vous avez besoin est quelque chose comme ceci:

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

uniquement avec la possibilité de référencer le nœud de contexte, au lieu de div

EDIT : Si vous définissez une variable pour le noeud contextuel,

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

vous pouvez référencer dans le prédicat XPath:

descendant::table[not(ancestor::table[ancestor::*[generate-id(.)=generate-id($contextNode)]])]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top