Setzen Sie den Unterschied mit XPath 1.0 - Wie bekomme ich .//table ohne ./table//table?

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

  •  20-09-2019
  •  | 
  •  

Frage

Ich versuche alle Tische zu finden Unter meinem aktuellen Knoten ohne auch die verschachtelten Tische einzubeziehen. Mit anderen Worten, wenn ich das habe, möchte ich "Ja" und nicht "Nein" finden:

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

Gibt es eine einfache Möglichkeit, dies in XPath 1.0 zu tun? (In 2.0 wäre es .//table except .//table//table, aber ich habe keine 2.0 als Option.)

BEARBEITEN: Bitte respektieren die bisherigen Antworten die Idee des aktuellen Kontextknotens nicht. Ich weiß nicht, wie weit die erste Tischschicht sein könnte (und es kann sich unterscheiden), und ich weiß auch nicht, ob ich in einer anderen Tabelle (oder zwei oder drei) sein könnte.

Buchstäblich will ich was was .//table except .//table//table In XPath 2.0 wäre es, aber ich habe nur XPath 1.

War es hilfreich?

Lösung 5

Nachdem wir es hier und anderswo untersucht haben, scheint die Antwort "Sie können nicht, und deshalb haben wir XPath 2.0". Nun ja.

Andere Tipps

Ich denke, Sie wollen Kind :: Tabelle alias Tisch

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

und zweiter Teil

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

Nun, wenn ich es verstehe, kann die content_list lösen:

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

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

:)

Wie wäre es mit .//table[not(.//table)]? Entschuldigung für Kürze, ich bin auf meinem Handy.

Ich weiß nicht, wie man den Kontextknoten in den verschachtelten Prädikaten bewertet, aber was Sie brauchen, ist ungefähr so:

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

Nur mit der Fähigkeit, auf den Kontextknoten statt zu verweisen, statt auf div

BEARBEITEN: Wenn Sie eine Variable für den Kontextknoten festlegen,

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

Dann können Sie es im XPath -Prädikat verweisen:

descendant::table[not(ancestor::table[ancestor::*[generate-id(.)=generate-id($contextNode)]])]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top