2010-01-13 8 views
4

J'essaie de trouver toutes les tables ci-dessous mon nœud actuel sans inclure également les tables imbriquées. Autrement dit, si j'ai, je veux trouver « oui » et non « non »:Définir la différence avec XPath 1.0 - comment puis-je obtenir .//table sans .//table//table?

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

est-il un moyen facile de le faire dans XPath 1.0? (En 2.0, il serait .//table except .//table//table, mais je ne l'ai pas 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'où la première couche de la table pourrait être (et elle pourrait différer), et je 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.

+0

Je pense qu'il est impossible d'écrire seulement un XPath 1.0 parce que j'ai besoin d'utiliser un contexte plusieurs fois et ce n'est pas autorisé. Puis-je utiliser deux XPath, un XPath pour obtenir la valeur de la variable et un XPath pour obtenir les tables requises? – Gaim

+0

Vous en avez fait un CW pour quelle raison? C'est une question assez délicate qui aura une bonne réponse, ce n'est pas un candidat pour CW. – AnthonyWJones

+0

Qu'est-ce qu'un "CW"? Et à qui vous adressez-vous comme "vous" là-bas? Moi? Comment en ai-je fait un "CW"? :) –

Répondre

0

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 ». Tant pis.

0

Je pense que vous voulez enfant :: Table alias Table

#!/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 deuxième 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> 
+0

Non, ne respectant pas le nœud de contexte. –

0

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

:)

+0

Non. Cela ne respecte pas le nœud de contexte. –

0

Qu'en est-il de .//table[not(.//table)]? Désolé pour la brièveté, je suis sur mon téléphone.

+0

Non, cela trouve toutes les tables qui n'ont pas de tables. Je veux toutes les tables qui ne sont pas dans les tables. –

+0

OK, qu'en est-il de .//table[not(ancestor::table)]? Cependant, cela risque fort d'être inefficace, à moins que vous ne le fassiez dans quelque chose comme eXist, qui a les index pour le supporter. –

+0

Non. Cela trouve toutes les tables tant qu'elles ne se trouvent pas dans la table * any *. Mais considérez ce qui se passe si notre nœud de contexte est déjà dans une table. Ça ne trouverait * rien *. Non, pas la réponse. –

0

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 noeud contextuel , au lieu de div

EDIT: Si vous définissez une variable pour le nœud de contexte,

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

alors vous pouvez faire référence dans le prédicat XPath:

descendant::table[not(ancestor::table[ancestor::*[generate-id(.)=generate-id($contextNode)]])] 
+0

Ouais, cela ne fonctionnera toujours pas, car il va exclure toutes les tables qui se trouvent dans n'importe quelle table qui se trouvent dans n'importe quelle div. :) Ne pas respecter le contexte à nouveau. –

+0

Mis à jour ma réponse. Ce n'est pas XPATH pur, mais une solution XPATH 1.0 (et XSLT 1.0). –

+0

Oui, pas de XSLT ici. Donc ça ne le fait pas non plus. {Soupir}. –