File Coverage

blib/lib/XML/Stream/XPath/Op.pm
Criterion Covered Total %
statement 301 381 79.0
branch 54 86 62.7
condition 12 18 66.6
subroutine 49 59 83.0
pod 0 7 0.0
total 416 551 75.5


line stmt bran cond sub pod time code
1             ##############################################################################
2             #
3             # This library is free software; you can redistribute it and/or
4             # modify it under the terms of the GNU Library General Public
5             # License as published by the Free Software Foundation; either
6             # version 2 of the License, or (at your option) any later version.
7             #
8             # This library is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11             # Library General Public License for more details.
12             #
13             # You should have received a copy of the GNU Library General Public
14             # License along with this library; if not, write to the
15             # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16             # Boston, MA 02111-1307, USA.
17             #
18             # Jabber
19             # Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
20             #
21             ##############################################################################
22              
23              
24             ##############################################################################
25             #
26             # Op - Base Op class
27             #
28             ##############################################################################
29             package XML::Stream::XPath::Op;
30              
31 12     12   193 use 5.008;
  12         32  
  12         532  
32 12     12   51 use strict;
  12         22  
  12         344  
33 12     12   49 use warnings;
  12         17  
  12         354  
34 12     12   50 use vars qw( $VERSION );
  12         17  
  12         3390  
35              
36             $VERSION = "1.23_07";
37              
38             sub new
39             {
40 156     156 0 159 my $proto = shift;
41 156         249 return &allocate($proto,@_);
42             }
43              
44             sub allocate
45             {
46 765     765 0 592 my $proto = shift;
47 765         808 my $self = { };
48              
49 765         1398 bless($self,$proto);
50              
51 765         1272 $self->{TYPE} = shift;
52 765         1021 $self->{VALUE} = shift;
53            
54 765         1113 return $self;
55             }
56              
57             sub getValue
58             {
59 23     23 0 29 my $self = shift;
60 23         56 return $self->{VALUE};
61             }
62              
63             sub calcStr
64             {
65 40     40 0 44 my $self = shift;
66 40         108 return $self->{VALUE};
67             }
68              
69             sub getType
70             {
71 23     23 0 26 my $self = shift;
72 23         84 return $self->{TYPE};
73             }
74              
75              
76             sub isValid
77             {
78 32     32 0 37 my $self = shift;
79 32         29 my $ctxt = shift;
80 32         85 return 1;
81             }
82              
83             sub display
84             {
85 0     0 0 0 my $self = shift;
86 0         0 my $space = shift;
87 0 0       0 $space = "" unless defined($space);
88              
89 0         0 print $space,"OP: type($self->{TYPE}) value($self->{VALUE})\n";
90             }
91              
92              
93              
94             ##############################################################################
95             #
96             # PositionOp - class to handle [0] ops
97             #
98             ##############################################################################
99             package XML::Stream::XPath::PositionOp;
100              
101 12     12   69 use vars qw (@ISA);
  12         18  
  12         2291  
102             @ISA = ( "XML::Stream::XPath::Op" );
103              
104             sub new
105             {
106 0     0   0 my $proto = shift;
107 0         0 my $self = $proto->allocate("POSITION","");
108 0         0 $self->{POS} = shift;
109              
110 0         0 return $self;
111             }
112              
113              
114             sub isValid
115             {
116 0     0   0 my $self = shift;
117 0         0 my $ctxt = shift;
118              
119 0         0 my @elems = $$ctxt->getList();
120 0         0 my @valid_elems;
121 0 0       0 if ($#elems+1 < $self->{POS})
122             {
123 0         0 return;
124             }
125              
126 0         0 push(@valid_elems, $elems[$self->{POS}-1]);
127              
128 0         0 $$ctxt->setList(@valid_elems);
129              
130 0         0 return 1;
131             }
132              
133              
134              
135             ##############################################################################
136             #
137             # ContextOp - class to handle [...] ops
138             #
139             ##############################################################################
140             package XML::Stream::XPath::ContextOp;
141              
142 12     12   60 use vars qw (@ISA);
  12         25  
  12         3197  
143             @ISA = ( "XML::Stream::XPath::Op" );
144              
145             sub new
146             {
147 92     92   100 my $proto = shift;
148 92         211 my $self = $proto->allocate("CONTEXT","");
149 92         165 $self->{OP} = shift;
150 92         184 return $self;
151             }
152              
153              
154             sub isValid
155             {
156 92     92   115 my $self = shift;
157 92         877 my $ctxt = shift;
158              
159 92         1206 my @elems = $$ctxt->getList();
160 92         108 my @valid_elems;
161 92         131 foreach my $elem (@elems)
162             {
163 132         304 my $tmp_ctxt = XML::Stream::XPath::Value->new($elem);
164 132         242 $tmp_ctxt->in_context(1);
165 132 100       336 if ($self->{OP}->isValid(\$tmp_ctxt))
166             {
167 23         56 push(@valid_elems,$elem);
168             }
169             }
170              
171 92         218 $$ctxt->setList(@valid_elems);
172            
173 92 100       192 if ($#valid_elems == -1)
174             {
175 75         215 return;
176             }
177              
178 17         61 return 1;
179             }
180              
181              
182             sub display
183             {
184 0     0   0 my $self = shift;
185 0         0 my $space = shift;
186 0 0       0 $space = "" unless defined($space);
187              
188 0         0 print "${space}OP: type(CONTEXT) op: \n";
189 0         0 $self->{OP}->display("$space ");
190             }
191              
192              
193              
194              
195             ##############################################################################
196             #
197             # AllOp - class to handle // ops
198             #
199             ##############################################################################
200             package XML::Stream::XPath::AllOp;
201              
202 12     12   63 use vars qw (@ISA);
  12         28  
  12         3322  
203             @ISA = ( "XML::Stream::XPath::Op" );
204              
205             sub new
206             {
207 14     14   17 my $proto = shift;
208 14         21 my $name = shift;
209 14         37 my $self = $proto->allocate("ALL",$name);
210 14         27 return $self;
211             }
212              
213              
214             sub isValid
215             {
216 14     14   20 my $self = shift;
217 14         14 my $ctxt = shift;
218              
219 14         31 my @elems = $$ctxt->getList();
220              
221 14 50       32 if ($#elems == -1)
222             {
223 0         0 return;
224             }
225              
226 14         15 my @valid_elems;
227            
228 14         19 foreach my $elem (@elems)
229             {
230 18         33 push(@valid_elems,$self->descend($elem));
231             }
232            
233 14         47 $$ctxt->setList(@valid_elems);
234              
235 14 50       39 if ($#valid_elems == -1)
236             {
237 0         0 return;
238             }
239              
240 14         52 return 1;
241             }
242              
243              
244             sub descend
245             {
246 344     344   265 my $self = shift;
247 344         268 my $elem = shift;
248              
249 344         233 my @valid_elems;
250            
251 344 100 66     870 if (($self->{VALUE} eq "*") || (&XML::Stream::GetXMLData("tag",$elem) eq $self->{VALUE}))
252             {
253 46         51 push(@valid_elems,$elem);
254             }
255            
256 344         543 foreach my $child (&XML::Stream::GetXMLData("child array",$elem,"*"))
257             {
258 326         474 push(@valid_elems,$self->descend($child));
259             }
260            
261 344         525 return @valid_elems;
262             }
263              
264              
265              
266             ##############################################################################
267             #
268             # NodeOp - class to handle ops based on node names
269             #
270             ##############################################################################
271             package XML::Stream::XPath::NodeOp;
272              
273 12     12   67 use vars qw (@ISA);
  12         19  
  12         3797  
274             @ISA = ( "XML::Stream::XPath::Op" );
275              
276             sub new
277             {
278 90     90   87 my $proto = shift;
279 90         84 my $name = shift;
280 90         75 my $is_root = shift;
281 90 50       153 $is_root = 0 unless defined($is_root);
282 90         189 my $self = $proto->allocate("NODE",$name);
283 90         113 $self->{ISROOT} = $is_root;
284 90         200 return $self;
285             }
286              
287              
288             sub isValid
289             {
290 77     77   71 my $self = shift;
291 77         60 my $ctxt = shift;
292              
293 77 50       139 if ($self->{ISROOT})
294             {
295 0         0 my $elem = $$ctxt->getFirstElem();
296 0 0       0 if (&XML::Stream::GetXMLData("tag",$elem) ne $self->{VALUE})
297             {
298 0         0 return;
299             }
300 0         0 return 1;
301             }
302              
303 77         66 my @valid_elems;
304              
305 77         158 foreach my $elem ($$ctxt->getList())
306             {
307 73         68 my $valid = 0;
308              
309 73         171 foreach my $child (&XML::Stream::GetXMLData("child array",$elem,"*"))
310             {
311 514 100 100     1250 if (($self->{VALUE} eq "*") ||
312             (&XML::Stream::GetXMLData("tag",$child) eq $self->{VALUE}))
313             {
314 108 50       215 if ($$ctxt->in_context())
315             {
316 0         0 $valid = 1;
317             }
318             else
319             {
320 108         183 push(@valid_elems,$child);
321             }
322             }
323             }
324 73 50       250 if ($valid)
325             {
326 0         0 push(@valid_elems,$elem);
327             }
328             }
329            
330 77         183 $$ctxt->setList(@valid_elems);
331              
332 77 100       161 if ($#valid_elems == -1)
333             {
334 10         22 return;
335             }
336              
337 67         197 return 1;
338             }
339              
340              
341             sub calcStr
342             {
343 2     2   3 my $self = shift;
344 2         4 my $elem = shift;
345 2         6 return &XML::Stream::GetXMLData("value",$elem);
346             }
347              
348              
349             ##############################################################################
350             #
351             # EqualOp - class to handle [ x = y ] ops
352             #
353             ##############################################################################
354             package XML::Stream::XPath::EqualOp;
355              
356 12     12   62 use vars qw (@ISA);
  12         20  
  12         4105  
357             @ISA = ( "XML::Stream::XPath::Op" );
358              
359             sub new
360             {
361 152     152   139 my $proto = shift;
362 152         295 my $self = $proto->allocate("EQUAL","");
363 152         274 $self->{OP_L} = shift;
364 152         210 $self->{OP_R} = shift;
365 152         338 return $self;
366             }
367              
368              
369             sub isValid
370             {
371 174     174   164 my $self = shift;
372 174         135 my $ctxt = shift;
373              
374 174         336 my $tmp_ctxt = XML::Stream::XPath::Value->new();
375 174         356 $tmp_ctxt->setList($$ctxt->getList());
376 174         348 $tmp_ctxt->in_context(0);
377            
378 174 100 66     349 if (!$self->{OP_L}->isValid(\$tmp_ctxt) || !$self->{OP_R}->isValid(\$tmp_ctxt))
379             {
380 148         182 return;
381             }
382              
383 26         33 my @valid_elems;
384 26         55 foreach my $elem ($tmp_ctxt->getList)
385             {
386 26 100       48 if ($self->{OP_L}->calcStr($elem) eq $self->{OP_R}->calcStr($elem))
387             {
388 9         19 push(@valid_elems,$elem);
389             }
390             }
391              
392 26 100       55 if ( $#valid_elems > -1)
393             {
394 9         24 @valid_elems = $$ctxt->getList();
395             }
396            
397 26         58 $$ctxt->setList(@valid_elems);
398              
399 26 100       56 if ($#valid_elems == -1)
400             {
401 17         71 return;
402             }
403              
404 9         28 return 1;
405             }
406              
407              
408             sub display
409             {
410 0     0   0 my $self = shift;
411 0         0 my $space = shift;
412 0 0       0 $space = "" unless defined($space);
413              
414 0         0 print $space,"OP: type(EQUAL)\n";
415 0         0 print $space," op_l: ";
416 0         0 $self->{OP_L}->display($space." ");
417            
418 0         0 print $space," op_r: ";
419 0         0 $self->{OP_R}->display($space." ");
420             }
421              
422              
423              
424             ##############################################################################
425             #
426             # NotEqualOp - class to handle [ x != y ] ops
427             #
428             ##############################################################################
429             package XML::Stream::XPath::NotEqualOp;
430              
431 12     12   140 use vars qw (@ISA);
  12         20  
  12         3747  
432             @ISA = ( "XML::Stream::XPath::Op" );
433              
434             sub new
435             {
436 2     2   4 my $proto = shift;
437 2         8 my $self = $proto->allocate("NOTEQUAL","");
438 2         8 $self->{OP_L} = shift;
439 2         5 $self->{OP_R} = shift;
440 2         4 return $self;
441             }
442              
443              
444             sub isValid
445             {
446 6     6   6 my $self = shift;
447 6         7 my $ctxt = shift;
448              
449 6         13 my $tmp_ctxt = XML::Stream::XPath::Value->new();
450 6         10 $tmp_ctxt->setList($$ctxt->getList());
451 6         12 $tmp_ctxt->in_context(0);
452            
453 6 50 33     12 if (!$self->{OP_L}->isValid(\$tmp_ctxt) || !$self->{OP_R}->isValid(\$tmp_ctxt))
454             {
455 0         0 return;
456             }
457              
458 6         7 my @valid_elems;
459 6         12 foreach my $elem ($tmp_ctxt->getList)
460             {
461 6 100       13 if ($self->{OP_L}->calcStr($elem) ne $self->{OP_R}->calcStr($elem))
462             {
463 4         8 push(@valid_elems,$elem);
464             }
465             }
466              
467 6 100       15 if ( $#valid_elems > -1)
468             {
469 4         10 @valid_elems = $$ctxt->getList();
470             }
471            
472 6         12 $$ctxt->setList(@valid_elems);
473              
474 6 100       12 if ($#valid_elems == -1)
475             {
476 2         10 return;
477             }
478              
479 4         13 return 1;
480             }
481              
482              
483             sub display
484             {
485 0     0   0 my $self = shift;
486 0         0 my $space = shift;
487 0 0       0 $space = "" unless defined($space);
488              
489 0         0 print $space,"OP: type(NOTEQUAL)\n";
490 0         0 print $space," op_l: ";
491 0         0 $self->{OP_L}->display($space." ");
492            
493 0         0 print $space," op_r: ";
494 0         0 $self->{OP_R}->display($space." ");
495             }
496              
497              
498              
499             ##############################################################################
500             #
501             # AttributeOp - class to handle @foo ops.
502             #
503             ##############################################################################
504             package XML::Stream::XPath::AttributeOp;
505              
506 12     12   123 use vars qw (@ISA);
  12         23  
  12         3754  
507             @ISA = ( "XML::Stream::XPath::Op" );
508              
509             sub new
510             {
511 164     164   183 my $proto = shift;
512 164         166 my $name = shift;
513 164         355 my $self = $proto->allocate("ATTRIBUTE",$name);
514 164         307 return $self;
515             }
516              
517              
518             sub isValid
519             {
520 198     198   190 my $self = shift;
521 198         182 my $ctxt = shift;
522              
523 198         381 my @elems = $$ctxt->getList();
524 198         209 my @valid_elems;
525             my @values;
526 0         0 my %attribs;
527            
528 198         280 foreach my $elem (@elems)
529             {
530 206 100       394 if ($self->{VALUE} ne "*")
531             {
532 204 100       495 if (&XML::Stream::GetXMLData("value",$elem,"",$self->{VALUE}))
533             {
534 48         90 $self->{VAL} = $self->calcStr($elem);
535 48         67 push(@valid_elems,$elem);
536 48         98 push(@values,$self->{VAL});
537             }
538             }
539             else
540             {
541 2         7 my %attrib = &XML::Stream::GetXMLData("attribs",$elem);
542 2 50       8 if (scalar(keys(%attrib)) > 0)
543             {
544 2         3 push(@valid_elems,$elem);
545 2         6 foreach my $key (keys(%attrib))
546             {
547 2         8 $attribs{$key} = $attrib{$key};
548             }
549             }
550             }
551             }
552              
553 198         482 $$ctxt->setList(@valid_elems);
554 198         440 $$ctxt->setValues(@values);
555 198         462 $$ctxt->setAttribs(%attribs);
556              
557 198 100       449 if ($#valid_elems == -1)
558             {
559 150         403 return;
560             }
561            
562 48         204 return 1;
563             }
564              
565              
566             sub getValue
567             {
568 0     0   0 my $self = shift;
569 0         0 return $self->{VAL};
570             }
571              
572              
573             sub calcStr
574             {
575 72     72   60 my $self = shift;
576 72         52 my $elem = shift;
577 72         143 return &XML::Stream::GetXMLData("value",$elem,"",$self->{VALUE});
578             }
579              
580              
581              
582              
583             ##############################################################################
584             #
585             # AndOp - class to handle [ .... and .... ] ops
586             #
587             ##############################################################################
588             package XML::Stream::XPath::AndOp;
589              
590 12     12   65 use vars qw (@ISA);
  12         24  
  12         2680  
591             @ISA = ( "XML::Stream::XPath::Op" );
592              
593             sub new
594             {
595 4     4   7 my $proto = shift;
596 4         12 my $self = $proto->allocate("AND","and");
597 4         8 $self->{OP_L} = shift;
598 4         7 $self->{OP_R} = shift;
599 4         7 return $self;
600             }
601              
602              
603             sub isValid
604             {
605 18     18   17 my $self = shift;
606 18         17 my $ctxt = shift;
607              
608 18         25 my $opl = $self->{OP_L}->isValid($ctxt);
609 18         32 my $opr = $self->{OP_R}->isValid($ctxt);
610            
611 18 100 100     54 if ($opl && $opr)
612             {
613 4         9 return 1;
614             }
615             else
616             {
617 14         39 return;
618             }
619             }
620              
621              
622             sub display
623             {
624 0     0   0 my $self = shift;
625 0         0 my $space = shift;
626 0 0       0 $space = "" unless defined($space);
627              
628 0         0 print $space,"OP: type(AND)\n";
629 0         0 print $space," op_l: \n";
630 0         0 $self->{OP_L}->display($space." ");
631            
632 0         0 print $space," op_r: \n";
633 0         0 $self->{OP_R}->display($space." ");
634             }
635              
636              
637              
638             ##############################################################################
639             #
640             # OrOp - class to handle [ .... or .... ] ops
641             #
642             ##############################################################################
643             package XML::Stream::XPath::OrOp;
644              
645 12     12   60 use vars qw (@ISA);
  12         18  
  12         4037  
646             @ISA = ( "XML::Stream::XPath::Op" );
647              
648             sub new
649             {
650 68     68   82 my $proto = shift;
651 68         155 my $self = $proto->allocate("OR","or");
652 68         93 $self->{OP_L} = shift;
653 68         96 $self->{OP_R} = shift;
654 68         138 return $self;
655             }
656              
657              
658             sub isValid
659             {
660 68     68   75 my $self = shift;
661 68         74 my $ctxt = shift;
662              
663 68         142 my @elems = $$ctxt->getList();
664 68         118 my @valid_elems;
665              
666 68         91 foreach my $elem (@elems)
667             {
668 68         161 my $tmp_ctxt_l = XML::Stream::XPath::Value->new($elem);
669 68         127 $tmp_ctxt_l->in_context(1);
670 68         136 my $tmp_ctxt_r = XML::Stream::XPath::Value->new($elem);
671 68         151 $tmp_ctxt_r->in_context(1);
672              
673 68         179 my $opl = $self->{OP_L}->isValid(\$tmp_ctxt_l);
674 68         245 my $opr = $self->{OP_R}->isValid(\$tmp_ctxt_r);
675            
676 68 50 33     490 if ($opl || $opr)
677             {
678 0         0 push(@valid_elems,$elem);
679             }
680             }
681              
682 68         190 $$ctxt->setList(@valid_elems);
683            
684 68 50       208 if ($#valid_elems == -1)
685             {
686 68         233 return;
687             }
688              
689 0         0 return 1;
690             }
691              
692              
693             sub display
694             {
695 0     0   0 my $self = shift;
696 0         0 my $space = shift;
697 0 0       0 $space = "" unless defined($space);
698              
699 0         0 print "${space}OP: type(OR)\n";
700 0         0 print "$space op_l: ";
701 0         0 $self->{OP_L}->display("$space ");
702            
703 0         0 print "$space op_r: ";
704 0         0 $self->{OP_R}->display("$space ");
705             }
706              
707              
708              
709             ##############################################################################
710             #
711             # FunctionOp - class to handle xxxx(...) ops
712             #
713             ##############################################################################
714             package XML::Stream::XPath::FunctionOp;
715              
716 12     12   65 use vars qw (@ISA);
  12         19  
  12         9943  
717             @ISA = ( "XML::Stream::XPath::Op" );
718              
719             sub new
720             {
721 23     23   30 my $proto = shift;
722 23         25 my $function = shift;
723 23         68 my $self = $proto->allocate("FUNCTION",$function);
724 23         39 $self->{CLOSED} = 0;
725 23         43 return $self;
726             }
727              
728              
729             sub addArg
730             {
731 6     6   7 my $self = shift;
732 6         7 my $arg = shift;
733              
734 6         6 push(@{$self->{ARGOPS}},$arg);
  6         41  
735             }
736              
737              
738             sub isValid
739             {
740 35     35   44 my $self = shift;
741 35         40 my $ctxt = shift;
742              
743 35         33 my $result;
744 35         2939 eval("\$result = &{\$XML::Stream::XPath::FUNCTIONS{\$self->{VALUE}}}(\$ctxt,\@{\$self->{ARGOPS}});");
745 35         169 return $result;
746             }
747              
748              
749             sub calcStr
750             {
751 14     14   13 my $self = shift;
752 14         14 my $elem = shift;
753            
754 14         13 my $result;
755 14         717 eval("\$result = &{\$XML::Stream::XPath::VALUES{\$self->{VALUE}}}(\$elem);");
756 14         46 return $result;
757              
758             }
759              
760              
761             sub display
762             {
763 0     0   0 my $self = shift;
764 0         0 my $space = shift;
765 0 0       0 $space = "" unless defined($space);
766              
767 0         0 print $space,"OP: type(FUNCTION)\n";
768 0         0 print $space," $self->{VALUE}(\n";
769 0         0 foreach my $arg (@{$self->{ARGOPS}})
  0         0  
770             {
771 0         0 print $arg,"\n";
772 0         0 $arg->display($space." ");
773             }
774 0         0 print "$space )\n";
775             }
776              
777              
778             sub function_name
779             {
780 14     14   24 my $ctxt = shift;
781 14         19 my (@args) = @_;
782              
783 14         43 my @elems = $$ctxt->getList();
784 14         13 my @valid_elems;
785             my @valid_values;
786 14         24 foreach my $elem (@elems)
787             {
788 14         34 my $text = &value_name($elem);
789 14 50       34 if (defined($text))
790             {
791 14         15 push(@valid_elems,$elem);
792 14         33 push(@valid_values,$text);
793             }
794             }
795              
796 14         36 $$ctxt->setList(@valid_elems);
797 14         37 $$ctxt->setValues(@valid_values);
798            
799 14 50       39 if ($#valid_elems == -1)
800             {
801 0         0 return;
802             }
803              
804 14         115 return 1;
805             }
806              
807              
808             sub function_not
809             {
810 6     6   8 my $ctxt = shift;
811 6         12 my (@args) = @_;
812              
813 6         32 my @elems = $$ctxt->getList();
814 6         6 my @valid_elems;
815 6         12 foreach my $elem (@elems)
816             {
817 6         128 my $tmp_ctxt = XML::Stream::XPath::Value->new($elem);
818 6         9 $tmp_ctxt->in_context(1);
819 6 100       10 if (!($args[0]->isValid(\$tmp_ctxt)))
820             {
821 2         8 push(@valid_elems,$elem);
822             }
823             }
824              
825 6         14 $$ctxt->setList(@valid_elems);
826            
827 6 100       13 if ($#valid_elems == -1)
828             {
829 4         28 return;
830             }
831              
832 2         29 return 1;
833             }
834              
835              
836             sub function_text
837             {
838 7     7   13 my $ctxt = shift;
839 7         14 my (@args) = @_;
840              
841 7         28 my @elems = $$ctxt->getList();
842 7         9 my @valid_elems;
843             my @valid_values;
844 7         19 foreach my $elem (@elems)
845             {
846 12         28 my $text = &value_text($elem);
847 12 50       30 if (defined($text))
848             {
849 12         19 push(@valid_elems,$elem);
850 12         21 push(@valid_values,$text);
851             }
852             }
853              
854 7         22 $$ctxt->setList(@valid_elems);
855 7         22 $$ctxt->setValues(@valid_values);
856            
857 7 50       25 if ($#valid_elems == -1)
858             {
859 0         0 return;
860             }
861              
862 7         61 return 1;
863             }
864              
865              
866             sub function_startswith
867             {
868 8     8   10 my $ctxt = shift;
869 8         12 my (@args) = @_;
870              
871 8         24 my @elems = $$ctxt->getList();
872 8         9 my @valid_elems;
873 8         13 foreach my $elem (@elems)
874             {
875 8         13 my $val1 = $args[0]->calcStr($elem);
876 8         19 my $val2 = $args[1]->calcStr($elem);
877              
878 8 100       28 if (substr($val1,0,length($val2)) eq $val2)
879             {
880 4         8 push(@valid_elems,$elem);
881             }
882             }
883              
884 8         21 $$ctxt->setList(@valid_elems);
885            
886 8 100       18 if ($#valid_elems == -1)
887             {
888 4         20 return;
889             }
890              
891 4         21 return 1;
892             }
893              
894              
895             sub value_name
896             {
897 20     20   22 my $elem = shift;
898 20         55 return &XML::Stream::GetXMLData("tag",$elem);
899             }
900              
901              
902             sub value_text
903             {
904 20     20   23 my $elem = shift;
905 20         47 return &XML::Stream::GetXMLData("value",$elem);
906             }
907              
908              
909              
910             $XML::Stream::XPath::FUNCTIONS{'name'} = \&function_name;
911             $XML::Stream::XPath::FUNCTIONS{'not'} = \&function_not;
912             $XML::Stream::XPath::FUNCTIONS{'text'} = \&function_text;
913             $XML::Stream::XPath::FUNCTIONS{'starts-with'} = \&function_startswith;
914              
915             $XML::Stream::XPath::VALUES{'name'} = \&value_name;
916             $XML::Stream::XPath::VALUES{'text'} = \&value_text;
917              
918             1;
919              
920