Set differenza con XPath 1.0 - come faccio ad ottenere .//table senza .//table//table?

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

  •  20-09-2019
  •  | 
  •  

Domanda

Sto cercando di trovare tutti i tavoli sotto il mio nodo corrente , senza includendo anche le tabelle nidificate. In altre parole, se ho questo, voglio trovare "sì" e non "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>

C'è un modo semplice per fare questo in XPath 1.0? (In 2.0, sarebbe .//table except .//table//table, ma non ho un 2.0 come opzione.)

Modifica per favore, le risposte finora non sono rispettando l'idea di nodo del contesto corrente. Non so quanto in basso il primo strato di tavolo potrebbe essere (e potrebbe essere diverso), e anche io non so se potrei essere all'interno di un'altra tabella (o due o tre).

Letteralmente, voglio quello .//table except .//table//table in XPath 2.0 sarebbe stato, ma ho solo XPath 1.

È stato utile?

Soluzione 5

Dopo aver esaminato qui e altrove, la risposta sembra essere "non è possibile, ed è per questo che abbiamo XPath 2.0". Oh, bene.

Altri suggerimenti

Penso che si desidera bambino :: tavolo 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]

e la seconda 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>

Be ', se non ho capito male, il content_list può risolvere:

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

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

:)

Che dire .//table[not(.//table)]? Ci scusiamo per brevità, io sono sul mio telefono.

Non so come ottenere il nodo di contesto da valutare nei predicati nidificate, ma quello che vi serve è qualcosa di simile:

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

solo con la possibilità di fare riferimento al nodo contesto, invece di div

Modifica : se si imposta una variabile per il nodo di contesto,

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

allora si può fare riferimento a esso nel predicato XPath:

descendant::table[not(ancestor::table[ancestor::*[generate-id(.)=generate-id($contextNode)]])]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top