Always provide identical root
authorJiri Palecek <[email protected]>
Fri, 23 Mar 2012 20:06:11 +0000 (23 21:06 +0100)
committerJiri Palecek <jirka@debian>
Fri, 13 Apr 2012 12:59:07 +0000 (13 14:59 +0200)
Fixes some corner cases like the number of roots etc.

lib/HTML/TreeBuilder/XPath.pm
t/HTML-TreeBuilder-XPath.t

index a071be7..16144e2 100644 (file)
@@ -120,6 +120,21 @@ sub find_xpath           { my( $elt, $path)= @_; return xp->find(
 sub matches              { my( $elt, $path)= @_; return xp->matches( $elt, $path, $elt);        }
 sub set_namespace        { my $elt= shift; xp->new->set_namespace( @_); }
 
+{
+    my %roots;
+    sub DESTROY {
+        my $self = shift;
+        delete $roots{$self};
+        $self->SUPER::DESTROY if $self->can("SUPER::DESTROY");
+    }
+
+    sub getParentNode
+    { my $elt= shift;
+      return $elt->{_parent} if $elt->{_parent};
+      return $roots{$elt} //= bless { _root => $elt }, 'HTML::TreeBuilder::XPath::Root';
+    }
+}
+
 sub getRootNode
   { my $elt= shift;
     # The parent of root is a HTML::TreeBuilder::XPath::Root
@@ -127,10 +142,6 @@ sub getRootNode
     return $elt->root->getParentNode; # I like this one!
   }
 
-sub getParentNode
-  { my $elt= shift;
-    return $elt->{_parent} || bless { _root => $elt }, 'HTML::TreeBuilder::XPath::Root';
-  }
 sub getName             { return shift->tag;   }
 sub getLocalName        { (my $name= $_[0]->tag) =~ s{^.*:}{}; $name; }
 sub getNextSibling      { my( $elt)= @_; 
index e218794..cdf78b3 100644 (file)
@@ -3,7 +3,7 @@
 
 #########################
 
-use Test::More tests => 30;
+use Test::More tests => 31;
 BEGIN { use_ok('HTML::TreeBuilder::XPath') };
 
 #########################
@@ -36,6 +36,8 @@ is( $html->findvalue( '//*[@id="foo"]/@*'), 'myspanfoo', '2 atts on same element
 is( $html->findvalue( '//*[@id="foo"]/@id|//*[@id="foo"]/@class'), 'myspanfoo', '2 atts on same element');
 is( $html->findvalue( '//*[@id="foo"]/@class|//*[@id="foo"]/@id'), 'myspanfoo', '2 atts on same element (unsorted)');
 
+is( $html->findvalue( 'count(/|/)' ), 1, 'count roots');
+
 is( $html->findvalue( '//b'), 'boldall', '2 texts');
 is( join( '|', $html->findvalues( '//b')), 'bold|all', '2 texts with findvalues');
 is( join( '|', $html->findnodes_as_strings( '//b')), 'bold|all', '2 texts with findnodes_as_strings');