File Coverage

blib/lib/Tree/XPathEngine/Expr.pm
Criterion Covered Total %
statement 215 277 77.6
branch 105 148 70.9
condition 36 51 70.5
subroutine 24 30 80.0
pod 11 11 100.0
total 391 517 75.6


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