Subject: | descendant order is not correct and id() causes runtime error in some situation |
I found two bugs and wrote a patch for them.
#1 axis_descendant returns descendants in incorrect order.
#2 calling id() function in some situations causes an error(Can't locate
object method "getElementById" via package "XML::XPathEngine::NodeSet")
while evaluating like following XPath: (id("me")//*)[1]/@attr .
From this XPath, XPathEngine constructs token tree that is
Expr-LocationPath-Expr-Expr-LocationPath-Expr-Function-Expr.
Function::evaluate expects its first argument is HTML::Element or
XML::XPathEngine::NodeSet which contains HTML::Element. But in this
case, its first argument is XML::XPathEngine::NodeSet which contains
XML::XPathEngine::NodeSet(and this NodeSet contains HTML::Elemenet).
Here is a patch and some tests addressed for these tow problem. Please
consider applying this patch.
thanks.
Subject: | xpathEngine.diff |
Only in XML-XPathEngine-0.09: Makefile.PL
diff -EbBw --strip-trailing-cr --exclude=CVS --exclude='*.o' --exclude=.svn -ruw XML-XPathEngine-0.09/lib/XML/XPathEngine/Function.pm XML-XPathEngine-0.09-me/lib/XML/XPathEngine/Function.pm
--- XML-XPathEngine-0.09/lib/XML/XPathEngine/Function.pm 2007-01-22 04:29:05.000000000 +0900
+++ XML-XPathEngine-0.09-me/lib/XML/XPathEngine/Function.pm 2008-04-14 23:23:41.000000000 +0900
@@ -49,7 +49,7 @@
sub evaluate {
my $self = shift;
my $node = shift;
- if ($node->isa('XML::XPathEngine::NodeSet')) {
+ while ($node->isa('XML::XPathEngine::NodeSet')) {
$node = $node->get_node(1);
}
my @params;
@@ -117,6 +117,9 @@
my $string = $self->string($node, $params[0]);
$_ = $string->value; # get perl scalar
my @ids = split; # splits $_
+ if ( $node->isa('HTML::TreeBuilder::XPath::Attribute') ) {
+ $node = ($node->getParentNode->getRootNode->getChildNodes)->[0];
+ }
foreach my $id (@ids) {
if (my $found = $node->getElementById($id)) {
$results->push($found);
diff -EbBw --strip-trailing-cr --exclude=CVS --exclude='*.o' --exclude=.svn -ruw XML-XPathEngine-0.09/lib/XML/XPathEngine/Step.pm XML-XPathEngine-0.09-me/lib/XML/XPathEngine/Step.pm
--- XML-XPathEngine-0.09/lib/XML/XPathEngine/Step.pm 2008-01-18 21:41:31.000000000 +0900
+++ XML-XPathEngine-0.09-me/lib/XML/XPathEngine/Step.pm 2008-04-14 22:11:58.000000000 +0900
@@ -245,11 +245,11 @@
my @stack = $context->getChildNodes;
while (@stack) {
- my $node = pop @stack;
+ my $node = shift @stack;
if (node_test($self, $node)) {
- $results->unshift($node);
+ $results->push($node);
}
- push @stack, $node->getChildNodes;
+ unshift @stack, $node->getChildNodes;
}
}
@@ -260,11 +260,11 @@
my @stack = ($context);
while (@stack) {
- my $node = pop @stack;
+ my $node = shift @stack;
if (node_test($self, $node)) {
- $results->unshift($node);
+ $results->push($node);
}
- push @stack, $node->getChildNodes;
+ unshift @stack, $node->getChildNodes;
}
}
Only in XML-XPathEngine-0.09: pm_to_blib
diff -EbBw --strip-trailing-cr --exclude=CVS --exclude='*.o' --exclude=.svn -ruw XML-XPathEngine-0.09/t/01_basic.t XML-XPathEngine-0.09-me/t/01_basic.t
--- XML-XPathEngine-0.09/t/01_basic.t 2008-04-11 16:47:19.000000000 +0900
+++ XML-XPathEngine-0.09-me/t/01_basic.t 2008-04-14 23:37:54.000000000 +0900
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 15;
+use Test::More tests => 21;
use XML::XPathEngine;
BEGIN { push @INC, './t'; }
@@ -35,8 +35,8 @@
is( $xp->findvalue( '//kid1[@att1=~/v[345]/]', $tree), 'vkid3vkid5', "match on attributes");
-is( $xp->findvalue( '//@*', $tree), 'v1v1vvvxv2vvvxv3vvvxv4vvvxv5vvvx', 'match all attributes');
-is( $xp->findvalue( '//@*[parent::*/@att1=~/v[345]/]', $tree), 'v3v4v5', 'match all attributes with a test');
+is( $xp->findvalue( '//@*', $tree), 'v1v11vvvxv22vvvxv33vvvxv44vvvxv55vvvx', 'match all attributes');
+is( $xp->findvalue( '//@*[parent::*/@att1=~/v[345]/]', $tree), 'v33v44v55', 'match all attributes with a test');
is( $xp->findvalue( '//kid1[@att1="v3"]/following::gkid2[1]', $tree), 'gkid2 4', "following axis[1]");
is( $xp->findvalue( '//kid1[@att1="v3"]/following::gkid2[2]', $tree), 'gkid2 5', "following axis[2]");
@@ -45,14 +45,21 @@
is( $xp->findvalue( '//kid1[@att1="v3"]/preceding::gkid2[2]', $tree), 'gkid2 1', "preceding axis[1]");
is( $xp->findvalue( '//kid1[@att1="v3"]/preceding::gkid2', $tree), 'gkid2 1gkid2 2', "preceding axis");
is( $xp->findvalue( 'count(//kid1)', $tree), '3', 'preceding count');
+is( $xp->findvalue( '(.//*)[2]/@*', $tree), 'vkid1', '(descendant::*)[2]');
+is( $xp->findvalue( 'id("1")/@att1', $tree), 'v1', 'id()');
+is( $xp->findvalue( 'substring-after(//kid1[1]/@att1, "v")', $tree), '1', 'substring-after');
+is( $xp->findvalue( 'id("1")//*[1]/@att2', $tree), 'vv', 'id descendants attribute');
+is( $xp->findvalue( '(id("1")//*)[1]/@att2', $tree), 'vv', 'grouped id descendants attribute');
+is( $xp->findvalue( 'substring-after((id("1")//*[1])/@att2, "v")', $tree), 'v', 'substring-after(id())');
sub init_tree
{ my $tree = tree->new( 'att', name => 'tree', value => 'tree');
my $root = tree->new( 'att', name => 'root', value => 'root_value', att1 => 'v1');
$root->add_as_last_child_of( $tree);
+ my $id = 0;
foreach (1..5)
- { my $kid= tree->new( 'att', name => 'kid' . $_ % 2, value => "vkid$_", att1 => "v$_");
+ { my $kid= tree->new( 'att', name => 'kid' . $_ % 2, value => "vkid$_", att1 => "v$_", id => ++$id);
$kid->add_as_last_child_of( $root);
my $gkid1= tree->new( 'att', name => 'gkid' . $_ % 2, value => "gvkid$_", att2 => "vv");
$gkid1->add_as_last_child_of( $kid);
@@ -82,6 +89,17 @@
sub isElementNode { return 1; }
sub get_pos { return shift->pos; }
sub getAttributes { return wantarray ? @{shift->attributes} : shift->attributes; }
+sub getElementById
+ {
+ my $elt = shift;
+ my $id = shift;
+ foreach ( @{$elt->attributes} ) {
+ $_->getName eq 'id' and $_->getValue eq $id and return $elt;
+ }
+ foreach ( $elt->getChildNodes ) {
+ return $_->getElementById($id);
+ }
+}
sub as_xml
{ my $elt= shift;
return "<" . $elt->getName . join( "", map { " " . $_->getName . '="' . $_->getValue . '"' } $elt->getAttributes) . '>'