Skip Menu |

This queue is for tickets about the XML-XPath CPAN distribution.

Report information
The Basics
Id: 30819
Status: resolved
Priority: 0/
Queue: XML-XPath

People
Owner: MANWAR [...] cpan.org
Requestors: tokuhirom [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.20
Fixed in: 1.21



Subject: substring function is invalid.
I think substring() function's behavior is definitely invalid. http://www.w3.org/TR/1999/REC-xpath-19991116#function-substring I want valid function. follow is a patch. === XPath/Function.pm ================================================================== --- XPath/Function.pm (revision 7248) +++ XPath/Function.pm (local) @@ -239,11 +239,51 @@ my ($str, $offset, $len); $str = $params[0]->string_value; $offset = $params[1]->value; - $offset--; # uses 1 based offsets + + if ($offset eq 'NaN') { + return XML::XPath::Literal->new(''); + } + + require POSIX; if (@params == 3) { $len = $params[2]->value; + + if ($len eq 'NaN') { + return XML::XPath::Literal->new(''); + } + + if ($offset eq '-Infinity' && $len eq 'Infinity') { + return XML::XPath::Literal->new(''); + } + + $offset--; # uses 1 based offsets + + $offset = POSIX::floor($offset + 0.5); # round. + + if ($offset < 0) { + if ($len ne 'Infinity') { + $len += $offset; + } + $offset = 0; + } + + if ($len eq 'Infinity') { + $len = length($str); + } + + $len = POSIX::floor($len + 0.5); # round. + + return XML::XPath::Literal->new(substr($str, $offset, $len)); + } else { + $offset--; # uses 1 based offsets + $offset = POSIX::floor($offset + 0.5); # round. + + if ($offset < 0) { + $offset = 0; + } + + return XML::XPath::Literal->new(substr($str, $offset)); } - return XML::XPath::Literal->new(substr($str, $offset, $len)); } sub string_length { === t/32substring.t ================================================================== --- t/32substring.t (revision 7248) +++ t/32substring.t (local) @@ -0,0 +1,34 @@ +use strict; +use warnings; +use Test::More tests => 12; +use XML::XPath; + +my $xp = XML::XPath->new(ioref => *DATA); +ok($xp); + +my $cases = <<'...'; +substring("12345", 2, 3) returns "234" +substring("12345", 2) returns "2345" +substring("12345", -2) returns "12345" +substring("12345", 1.5, 2.6) returns "234" +substring("12345", 0 div 0, 3) returns "" +substring("12345", 1, 0 div 0) returns "" +substring("12345", -1 div 0, 1 div 0) returns "" +substring("12345", -42, 1 div 0) returns "12345" +substring("12345", 0, 1 div 0) returns "12345" +substring("12345", 0, 3) returns "12" +substring("12345", -1, 4) returns "12" +... + +for my $case (split /\n/, $cases) { + next unless $case; + + my ($xpath, $expected) = split / returns /, $case; + $expected =~ s/"//g; + is $xp->findvalue($xpath), $expected, $case; +} + +# see http://www.w3.org/TR/1999/REC-xpath-19991116#function-substring + +__END__ +<p></p>
Hi, Thanks for raising the issue and providing patch with test. Much appreciated. I will get it patched soon. Many Thanks. Best Regards, Mohammad S Anwar
Hi, XML::XPath has been patched and uploaded. The supplied test script was failing even after applying the supplied patch. Therefore I tweaked it a bit. Best Regards, Mohammad S Anwar