File Coverage

blib/lib/XML/XPathEngine/Expr.pm
Criterion Covered Total %
statement 107 308 34.7
branch 49 178 27.5
condition 13 51 25.4
subroutine 15 32 46.8
pod 0 30 0.0
total 184 599 30.7


line stmt bran cond sub pod time code
1             # $Id: Expr.pm,v 1.20 2003/01/26 19:33:24 matt Exp $
2              
3             package XML::XPathEngine::Expr;
4 2     2   11 use strict;
  2         14  
  2         3609  
5              
6             sub new {
7 208     208 0 416 my $class = shift;
8 208         260 my ($pp) = @_;
9 208         1128 bless { predicates => [], pp => $pp }, $class;
10             }
11              
12             sub as_string {
13 0     0 0 0 my $self = shift;
14 0         0 local $^W; # Use of uninitialized value! grrr
15 0         0 my $string = "(" . $self->{lhs}->as_string;
16 0 0       0 $string .= " " . $self->{op} . " " if defined $self->{op};
17 0 0       0 $string .= $self->{rhs}->as_string if defined $self->{rhs};
18 0         0 $string .= ")";
19 0         0 foreach my $predicate (@{$self->{predicates}}) {
  0         0  
20 0         0 $string .= "[" . $predicate->as_string . "]";
21             }
22 0         0 return $string;
23             }
24              
25             sub as_xml {
26 0     0 0 0 my $self = shift;
27 0         0 local $^W; # Use of uninitialized value! grrr
28 0         0 my $string;
29 0 0       0 if (defined $self->{op}) {
30 0         0 $string .= $self->op_xml();
31             }
32             else {
33 0         0 $string .= $self->{lhs}->as_xml();
34             }
35 0         0 foreach my $predicate (@{$self->{predicates}}) {
  0         0  
36 0         0 $string .= "\n" . $predicate->as_xml() . "\n";
37             }
38 0         0 return $string;
39             }
40              
41             sub op_xml {
42 0     0 0 0 my $self = shift;
43 0         0 my $op = $self->{op};
44              
45 0         0 my $tag;
46 0         0 for ($op) {
47 0 0       0 /^or$/ && do {
48 0         0 $tag = "Or";
49             };
50 0 0       0 /^and$/ && do {
51 0         0 $tag = "And";
52             };
53 0 0       0 /^=$/ && do {
54 0         0 $tag = "Equals";
55             };
56 0 0       0 /^!=$/ && do {
57 0         0 $tag = "NotEquals";
58             };
59 0 0       0 /^<=$/ && do {
60 0         0 $tag = "LessThanOrEquals";
61             };
62 0 0       0 /^>=$/ && do {
63 0         0 $tag = "GreaterThanOrEquals";
64             };
65 0 0       0 /^>$/ && do {
66 0         0 $tag = "GreaterThan";
67             };
68 0 0       0 /^<$/ && do {
69 0         0 $tag = "LessThan";
70             };
71 0 0       0 /^\+$/ && do {
72 0         0 $tag = "Plus";
73             };
74 0 0       0 /^-$/ && do {
75 0         0 $tag = "Minus";
76             };
77 0 0       0 /^div$/ && do {
78 0         0 $tag = "Div";
79             };
80 0 0       0 /^mod$/ && do {
81 0         0 $tag = "Mod";
82             };
83 0 0       0 /^\*$/ && do {
84 0         0 $tag = "Multiply";
85             };
86 0 0       0 /^\|$/ && do {
87 0         0 $tag = "Union";
88             };
89             }
90            
91 0         0 return "<$tag>\n" . $self->{lhs}->as_xml() . $self->{rhs}->as_xml() . "\n";
92             }
93              
94             sub set_lhs {
95 148     148 0 225 my $self = shift;
96 148         399 $self->{lhs} = $_[0];
97             }
98              
99             sub set_op {
100 25     25 0 33 my $self = shift;
101 25         78 $self->{op} = $_[0];
102             }
103              
104             sub set_rhs {
105 25     25 0 36 my $self = shift;
106 25         78 $self->{rhs} = $_[0];
107             }
108              
109             sub push_predicate {
110 2     2 0 4 my $self = shift;
111            
112 2         10 die "Only 1 predicate allowed on FilterExpr in W3C XPath 1.0"
113 2 50       3 if @{$self->{predicates}};
114            
115 2         4 push @{$self->{predicates}}, $_[0];
  2         8  
116             }
117              
118 0     0 0 0 sub get_lhs { $_[0]->{lhs}; }
119 0     0 0 0 sub get_rhs { $_[0]->{rhs}; }
120 0     0 0 0 sub get_op { $_[0]->{op}; }
121              
122             sub evaluate {
123 503     503 0 739 my $self = shift;
124 503         574 my $node = shift;
125            
126             # If there's an op, result is result of that op.
127             # If no op, just resolve Expr
128            
129             # warn "Evaluate Expr: ", $self->as_string, "\n";
130            
131 503         535 my $results;
132            
133 503 100       934 if ($self->{op}) {
134 134 50       315 die ("No RHS of ", $self->as_string) unless $self->{rhs};
135 134         229 $results = $self->op_eval($node);
136             }
137             else {
138 369         1077 $results = $self->{lhs}->evaluate($node);
139             }
140            
141 497 100       716 if (my @predicates = @{$self->{predicates}}) {
  497         1456  
142 2 50       11 if (!$results->isa('XML::XPathEngine::NodeSet')) {
143 0         0 die "Can't have predicates execute on object type: " . ref($results);
144             }
145            
146             # filter initial nodeset by each predicate
147 2         3 foreach my $predicate (@{$self->{predicates}}) {
  2         5  
148 2         9 $results = $self->filter_by_predicate($results, $predicate);
149             }
150             }
151            
152 497         1048 return $results;
153             }
154              
155             sub op_eval {
156 134     134 0 154 my $self = shift;
157 134         170 my $node = shift;
158            
159 134         185 my $op = $self->{op};
160            
161 134         231 for ($op) {
162 134 100       309 /^or$/ && do {
163 5         15 return op_or($node, $self->{lhs}, $self->{rhs});
164             };
165 129 100       280 /^and$/ && do {
166 10         25 return op_and($node, $self->{lhs}, $self->{rhs});
167             };
168 119 100       259 /^=~$/ && do {
169 47         118 return op_match($node, $self->{lhs}, $self->{rhs});
170             };
171 72 50       125 /^!~$/ && do {
172 0         0 return op_not_match($node, $self->{lhs}, $self->{rhs});
173             };
174 72 100       217 /^=$/ && do {
175 71         175 return op_equals($node, $self->{lhs}, $self->{rhs});
176             };
177 1 50       4 /^!=$/ && do {
178 0         0 return op_nequals($node, $self->{lhs}, $self->{rhs});
179             };
180 1 50       5 /^<=$/ && do {
181 0         0 return op_le($node, $self->{lhs}, $self->{rhs});
182             };
183 1 50       4 /^>=$/ && do {
184 0         0 return op_ge($node, $self->{lhs}, $self->{rhs});
185             };
186 1 50       6 /^>$/ && do {
187 1         7 return op_gt($node, $self->{lhs}, $self->{rhs});
188             };
189 0 0       0 /^<$/ && do {
190 0         0 return op_lt($node, $self->{lhs}, $self->{rhs});
191             };
192 0 0       0 /^\+$/ && do {
193 0         0 return op_plus($node, $self->{lhs}, $self->{rhs});
194             };
195 0 0       0 /^-$/ && do {
196 0         0 return op_minus($node, $self->{lhs}, $self->{rhs});
197             };
198 0 0       0 /^div$/ && do {
199 0         0 return op_div($node, $self->{lhs}, $self->{rhs});
200             };
201 0 0       0 /^mod$/ && do {
202 0         0 return op_mod($node, $self->{lhs}, $self->{rhs});
203             };
204 0 0       0 /^\*$/ && do {
205 0         0 return op_mult($node, $self->{lhs}, $self->{rhs});
206             };
207 0 0       0 /^\|$/ && do {
208 0         0 return op_union($node, $self->{lhs}, $self->{rhs});
209             };
210            
211 0         0 die "No such operator, or operator unimplemented in ", $self->as_string, "\n";
212             }
213             }
214              
215             # Operators
216              
217 2     2   1217 use XML::XPathEngine::Boolean;
  2         6  
  2         6128  
218              
219             sub op_or {
220 5     5 0 9 my ($node, $lhs, $rhs) = @_;
221 5 50       23 if($lhs->evaluate($node)->to_boolean->value) {
222 5         15 return XML::XPathEngine::Boolean->True;
223             }
224             else {
225 0         0 return $rhs->evaluate($node)->to_boolean;
226             }
227             }
228              
229             sub op_and {
230 10     10 0 14 my ($node, $lhs, $rhs) = @_;
231 10 50       20 if( ! $lhs->evaluate($node)->to_boolean->value ) {
232 0         0 return XML::XPathEngine::Boolean->False;
233             }
234             else {
235 10         20 return $rhs->evaluate($node)->to_boolean;
236             }
237             }
238              
239             sub op_match
240 47     47 0 103 { my ($node, $lhs, $rhs) = @_;
241              
242 47         88 my $lh_results = $lhs->evaluate($node);
243 47         93 my $rh_results = $rhs->evaluate($node);
244 47         123 my $rh_value = $rh_results->string_value;
245              
246 47 50       155 if ($lh_results->isa('XML::XPathEngine::NodeSet') )
247 47         107 { foreach my $lhnode ($lh_results->get_nodelist)
248 21 100       49 { if ($lhnode->string_value=~ m/$rh_value/) # / is important here, regexp is / delimited
249 12         158 { return XML::XPathEngine::Boolean->True; }
250             }
251 35         216 return XML::XPathEngine::Boolean->False;
252             }
253             else
254 0 0       0 { return $lh_results->string_value =~ m/$rh_value/ ?
255             XML::XPathEngine::Boolean->True : XML::XPathEngine::Boolean->False;
256             }
257             }
258            
259             sub op_not_match
260 0     0 0 0 { my ($node, $lhs, $rhs) = @_;
261              
262 0         0 my $lh_results = $lhs->evaluate($node);
263 0         0 my $rh_results = $rhs->evaluate($node);
264 0         0 my $rh_value = $rh_results->string_value;
265            
266 0 0       0 if ($lh_results->isa('XML::XPathEngine::NodeSet') )
267 0         0 { foreach my $lhnode ($lh_results->get_nodelist)
268 0 0       0 { if ($lhnode->string_value!~ m/$rh_value/)
269 0         0 { return XML::XPathEngine::Boolean->True; }
270             }
271 0         0 return XML::XPathEngine::Boolean->False;
272             }
273             else
274 0 0       0 { return $lh_results->string_value !~ m/$rh_value/ ?
275             XML::XPathEngine::Boolean->True : XML::XPathEngine::Boolean->False;
276             }
277             }
278              
279              
280             sub op_equals {
281 71     71 0 111 my ($node, $lhs, $rhs) = @_;
282              
283 71         150 my $lh_results = $lhs->evaluate($node);
284 71         147 my $rh_results = $rhs->evaluate($node);
285            
286 68 50 66     1265 if ($lh_results->isa('XML::XPathEngine::NodeSet') &&
    100 66        
      33        
      66        
287             $rh_results->isa('XML::XPathEngine::NodeSet')) {
288             # True if and only if there is a node in the
289             # first set and a node in the second set such
290             # that the result of performing the comparison
291             # on the string-values of the two nodes is true.
292 0         0 foreach my $lhnode ($lh_results->get_nodelist) {
293 0         0 foreach my $rhnode ($rh_results->get_nodelist) {
294 0 0       0 if ($lhnode->string_value eq $rhnode->string_value) {
295 0         0 return XML::XPathEngine::Boolean->True;
296             }
297             }
298             }
299 0         0 return XML::XPathEngine::Boolean->False;
300             }
301             elsif (($lh_results->isa('XML::XPathEngine::NodeSet') ||
302             $rh_results->isa('XML::XPathEngine::NodeSet')) &&
303             (!$lh_results->isa('XML::XPathEngine::NodeSet') ||
304             !$rh_results->isa('XML::XPathEngine::NodeSet'))) {
305             # (that says: one is a nodeset, and one is not a nodeset)
306            
307 61         74 my ($nodeset, $other);
308 61 50       169 if ($lh_results->isa('XML::XPathEngine::NodeSet')) {
309 61         68 $nodeset = $lh_results;
310 61         239 $other = $rh_results;
311             }
312             else {
313 0         0 $nodeset = $rh_results;
314 0         0 $other = $lh_results;
315             }
316            
317             # True if and only if there is a node in the
318             # nodeset such that the result of performing
319             # the comparison on (string_value($node))
320             # is true.
321 61 100       378 if ($other->isa('XML::XPathEngine::Number')) {
    50          
    0          
322 5         13 foreach my $node ($nodeset->get_nodelist) {
323 5 100       13 if ($node->string_value == $other->value) {
324 3         9 return XML::XPathEngine::Boolean->True;
325             }
326             }
327             }
328             elsif ($other->isa('XML::XPathEngine::Literal')) {
329 56         148 foreach my $node ($nodeset->get_nodelist) {
330 50 100       112 if ($node->string_value eq $other->value) {
331 29         80 return XML::XPathEngine::Boolean->True;
332             }
333             }
334             }
335             elsif ($other->isa('XML::XPathEngine::Boolean')) {
336 0 0       0 if ($nodeset->to_boolean->value == $other->value) {
337 0         0 return XML::XPathEngine::Boolean->True;
338             }
339             }
340              
341 29         90 return XML::XPathEngine::Boolean->False;
342             }
343             else { # Neither is a nodeset
344 7 50 33     83 if ($lh_results->isa('XML::XPathEngine::Boolean') ||
    50 33        
345             $rh_results->isa('XML::XPathEngine::Boolean')) {
346             # if either is a boolean
347 0 0       0 if ($lh_results->to_boolean->value == $rh_results->to_boolean->value) {
348 0         0 return XML::XPathEngine::Boolean->True;
349             }
350 0         0 return XML::XPathEngine::Boolean->False;
351             }
352             elsif ($lh_results->isa('XML::XPathEngine::Number') ||
353             $rh_results->isa('XML::XPathEngine::Number')) {
354             # if either is a number
355 7         16 local $^W; # 'number' might result in undef
356 7 100       24 if ($lh_results->to_number->value == $rh_results->to_number->value) {
357 3         10 return XML::XPathEngine::Boolean->True;
358             }
359 4         15 return XML::XPathEngine::Boolean->False;
360             }
361             else {
362 0 0       0 if ($lh_results->to_literal->value eq $rh_results->to_literal->value) {
363 0         0 return XML::XPathEngine::Boolean->True;
364             }
365 0         0 return XML::XPathEngine::Boolean->False;
366             }
367             }
368             }
369              
370             sub op_nequals {
371 0     0 0 0 my ($node, $lhs, $rhs) = @_;
372 0 0       0 if (op_equals($node, $lhs, $rhs)->value) {
373 0         0 return XML::XPathEngine::Boolean->False;
374             }
375 0         0 return XML::XPathEngine::Boolean->True;
376             }
377              
378             sub op_le {
379 0     0 0 0 my ($node, $lhs, $rhs) = @_;
380 0         0 op_ge($node, $rhs, $lhs);
381             }
382              
383             sub op_ge {
384 0     0 0 0 my ($node, $lhs, $rhs) = @_;
385              
386 0         0 my $lh_results = $lhs->evaluate($node);
387 0         0 my $rh_results = $rhs->evaluate($node);
388            
389 0 0 0     0 if ($lh_results->isa('XML::XPathEngine::NodeSet') &&
    0 0        
      0        
      0        
390             $rh_results->isa('XML::XPathEngine::NodeSet')) {
391              
392 0         0 foreach my $lhnode ($lh_results->get_nodelist) {
393 0         0 foreach my $rhnode ($rh_results->get_nodelist) {
394 0         0 my $lhNum = XML::XPathEngine::Number->new($lhnode->string_value);
395 0         0 my $rhNum = XML::XPathEngine::Number->new($rhnode->string_value);
396 0 0       0 if ($lhNum->value >= $rhNum->value) {
397 0         0 return XML::XPathEngine::Boolean->True;
398             }
399             }
400             }
401 0         0 return XML::XPathEngine::Boolean->False;
402             }
403             elsif (($lh_results->isa('XML::XPathEngine::NodeSet') ||
404             $rh_results->isa('XML::XPathEngine::NodeSet')) &&
405             (!$lh_results->isa('XML::XPathEngine::NodeSet') ||
406             !$rh_results->isa('XML::XPathEngine::NodeSet'))) {
407             # (that says: one is a nodeset, and one is not a nodeset)
408              
409 0 0       0 if ($lh_results->isa('XML::XPathEngine::NodeSet')) {
410 0         0 foreach my $node ($lh_results->get_nodelist) {
411 0 0       0 if ($node->to_number->value >= $rh_results->to_number->value) {
412 0         0 return XML::XPathEngine::Boolean->True;
413             }
414             }
415             }
416             else {
417 0         0 foreach my $node ($rh_results->get_nodelist) {
418 0 0       0 if ( $lh_results->to_number->value >= $node->to_number->value) {
419 0         0 return XML::XPathEngine::Boolean->True;
420             }
421             }
422             }
423 0         0 return XML::XPathEngine::Boolean->False;
424             }
425             else { # Neither is a nodeset
426 0 0 0     0 if ($lh_results->isa('XML::XPathEngine::Boolean') ||
427             $rh_results->isa('XML::XPathEngine::Boolean')) {
428             # if either is a boolean
429 0 0       0 if ($lh_results->to_boolean->to_number->value
430             >= $rh_results->to_boolean->to_number->value) {
431 0         0 return XML::XPathEngine::Boolean->True;
432             }
433             }
434             else {
435 0 0       0 if ($lh_results->to_number->value >= $rh_results->to_number->value) {
436 0         0 return XML::XPathEngine::Boolean->True;
437             }
438             }
439 0         0 return XML::XPathEngine::Boolean->False;
440             }
441             }
442              
443             sub op_gt {
444 1     1 0 3 my ($node, $lhs, $rhs) = @_;
445              
446 1         3 my $lh_results = $lhs->evaluate($node);
447 1         5 my $rh_results = $rhs->evaluate($node);
448            
449 1 50 33     40 if ($lh_results->isa('XML::XPathEngine::NodeSet') &&
    50 33        
      0        
      33        
450             $rh_results->isa('XML::XPathEngine::NodeSet')) {
451              
452 0         0 foreach my $lhnode ($lh_results->get_nodelist) {
453 0         0 foreach my $rhnode ($rh_results->get_nodelist) {
454 0         0 my $lhNum = XML::XPathEngine::Number->new($lhnode->string_value);
455 0         0 my $rhNum = XML::XPathEngine::Number->new($rhnode->string_value);
456 0 0       0 if ($lhNum->value > $rhNum->value) {
457 0         0 return XML::XPathEngine::Boolean->True;
458             }
459             }
460             }
461 0         0 return XML::XPathEngine::Boolean->False;
462             }
463             elsif (($lh_results->isa('XML::XPathEngine::NodeSet') ||
464             $rh_results->isa('XML::XPathEngine::NodeSet')) &&
465             (!$lh_results->isa('XML::XPathEngine::NodeSet') ||
466             !$rh_results->isa('XML::XPathEngine::NodeSet'))) {
467             # (that says: one is a nodeset, and one is not a nodeset)
468              
469 0 0       0 if ($lh_results->isa('XML::XPathEngine::NodeSet')) {
470 0         0 foreach my $node ($lh_results->get_nodelist) {
471 0 0       0 if ($node->to_number->value > $rh_results->to_number->value) {
472 0         0 return XML::XPathEngine::Boolean->True;
473             }
474             }
475             }
476             else {
477 0         0 foreach my $node ($rh_results->get_nodelist) {
478 0 0       0 if ( $lh_results->to_number->value > $node->to_number->value) {
479 0         0 return XML::XPathEngine::Boolean->True;
480             }
481             }
482             }
483 0         0 return XML::XPathEngine::Boolean->False;
484             }
485             else { # Neither is a nodeset
486 1 50 33     15 if ($lh_results->isa('XML::XPathEngine::Boolean') ||
487             $rh_results->isa('XML::XPathEngine::Boolean')) {
488             # if either is a boolean
489 0 0       0 if ($lh_results->to_boolean->value > $rh_results->to_boolean->value) {
490 0         0 return XML::XPathEngine::Boolean->True;
491             }
492             }
493             else {
494 1 50       6 if ($lh_results->to_number->value > $rh_results->to_number->value) {
495 0         0 return XML::XPathEngine::Boolean->True;
496             }
497             }
498 1         6 return XML::XPathEngine::Boolean->False;
499             }
500             }
501              
502             sub op_lt {
503 0     0 0 0 my ($node, $lhs, $rhs) = @_;
504 0         0 op_gt($node, $rhs, $lhs);
505             }
506              
507             sub op_plus {
508 0     0 0 0 my ($node, $lhs, $rhs) = @_;
509 0         0 my $lh_results = $lhs->evaluate($node);
510 0         0 my $rh_results = $rhs->evaluate($node);
511            
512 0         0 my $result =
513             $lh_results->to_number->value
514             +
515             $rh_results->to_number->value
516             ;
517 0         0 return XML::XPathEngine::Number->new($result);
518             }
519              
520             sub op_minus {
521 0     0 0 0 my ($node, $lhs, $rhs) = @_;
522 0         0 my $lh_results = $lhs->evaluate($node);
523 0         0 my $rh_results = $rhs->evaluate($node);
524            
525 0         0 my $result =
526             $lh_results->to_number->value
527             -
528             $rh_results->to_number->value
529             ;
530 0         0 return XML::XPathEngine::Number->new($result);
531             }
532              
533             sub op_div {
534 0     0 0 0 my ($node, $lhs, $rhs) = @_;
535 0         0 my $lh_results = $lhs->evaluate($node);
536 0         0 my $rh_results = $rhs->evaluate($node);
537              
538 0         0 my $result = eval {
539 0         0 $lh_results->to_number->value
540             /
541             $rh_results->to_number->value
542             ;
543             };
544 0 0       0 if ($@) {
545             # assume divide by zero
546             # This is probably a terrible way to handle this!
547             # Ah well... who wants to live forever...
548 0         0 return XML::XPathEngine::Literal->new('Infinity');
549             }
550 0         0 return XML::XPathEngine::Number->new($result);
551             }
552              
553             sub op_mod {
554 0     0 0 0 my ($node, $lhs, $rhs) = @_;
555 0         0 my $lh_results = $lhs->evaluate($node);
556 0         0 my $rh_results = $rhs->evaluate($node);
557            
558 0         0 my $result =
559             $lh_results->to_number->value
560             %
561             $rh_results->to_number->value
562             ;
563 0         0 return XML::XPathEngine::Number->new($result);
564             }
565              
566             sub op_mult {
567 0     0 0 0 my ($node, $lhs, $rhs) = @_;
568 0         0 my $lh_results = $lhs->evaluate($node);
569 0         0 my $rh_results = $rhs->evaluate($node);
570            
571 0         0 my $result =
572             $lh_results->to_number->value
573             *
574             $rh_results->to_number->value
575             ;
576 0         0 return XML::XPathEngine::Number->new($result);
577             }
578              
579             sub op_union {
580 0     0 0 0 my ($node, $lhs, $rhs) = @_;
581 0         0 my $lh_result = $lhs->evaluate($node);
582 0         0 my $rh_result = $rhs->evaluate($node);
583            
584 0 0 0     0 if ($lh_result->isa('XML::XPathEngine::NodeSet') &&
585             $rh_result->isa('XML::XPathEngine::NodeSet')) {
586 0         0 my %found;
587 0         0 my $results = XML::XPathEngine::NodeSet->new;
588 0         0 foreach my $lhnode ($lh_result->get_nodelist) {
589 0         0 $found{"$lhnode"}++;
590 0         0 $results->push($lhnode);
591             }
592 0         0 foreach my $rhnode ($rh_result->get_nodelist) {
593 0 0       0 $results->push($rhnode)
594             unless exists $found{"$rhnode"};
595             }
596 0         0 return $results->sort->remove_duplicates;
597             }
598 0         0 die "Both sides of a union must be Node Sets\n";
599             }
600              
601             sub filter_by_predicate {
602 2     2 0 4 my $self = shift;
603 2         4 my ($nodeset, $predicate) = @_;
604            
605             # See spec section 2.4, paragraphs 2 & 3:
606             # For each node in the node-set to be filtered, the predicate Expr
607             # is evaluated with that node as the context node, with the number
608             # of nodes in the node set as the context size, and with the
609             # proximity position of the node in the node set with respect to
610             # the axis as the context position.
611            
612 2 50       6 if (!ref($nodeset)) { # use ref because nodeset has a bool context
613 0         0 die "No nodeset!!!";
614             }
615            
616             # warn "Filter by predicate: $predicate\n";
617            
618 2         7 my $newset = XML::XPathEngine::NodeSet->new();
619            
620 2         9 for(my $i = 1; $i <= $nodeset->size; $i++) {
621             # set context set each time 'cos a loc-path in the expr could change it
622 18         49 $self->{pp}->_set_context_set($nodeset);
623 18         53 $self->{pp}->_set_context_pos($i);
624 18         42 my $result = $predicate->evaluate($nodeset->get_node($i));
625 18 50       132 if ($result->isa('XML::XPathEngine::Boolean')) {
    50          
626 0 0       0 if ($result->value) {
627 0         0 $newset->push($nodeset->get_node($i));
628             }
629             }
630             elsif ($result->isa('XML::XPathEngine::Number')) {
631 18 100       49 if ($result->value == $i) {
632 2         5 $newset->push($nodeset->get_node($i));
633             }
634             }
635             else {
636 0 0       0 if ($result->to_boolean->value) {
637 0         0 $newset->push($nodeset->get_node($i));
638             }
639             }
640             }
641            
642 2         7 return $newset;
643             }
644              
645             1;