File Coverage

blib/lib/XML/TinyXML/Selector/XPath/Functions.pm
Criterion Covered Total %
statement 49 93 52.6
branch 25 40 62.5
condition 13 18 72.2
subroutine 12 29 41.3
pod 0 26 0.0
total 99 206 48.0


line stmt bran cond sub pod time code
1             # Internal use only
2             package XML::TinyXML::Selector::XPath::Functions;
3              
4 4     4   15661 use strict;
  4         9  
  4         168  
5 4     4   18 use warnings;
  4         8  
  4         110  
6 4     4   3762 use POSIX qw(:sys_types_h);
  4         62305  
  4         27  
7              
8             our $VERSION = "0.34";
9              
10             # NODE FUNCTIONS
11              
12             sub last {
13 2     2 0 5 my ($class, $context) = @_;
14 2 50       7 return scalar(@{$context->items})
  2         95  
15             if ($context);
16             }
17              
18             sub position {
19 6     6 0 11 my ($class, $context) = @_;
20 6         10 my $cnt = 0;
21 6         5 return map { ++$cnt => $_ } @{$context->items};
  12         53  
  6         27  
22             }
23              
24             sub count {
25 0     0 0 0 my ($class, $context, $items) = @_;
26 0         0 return scalar(@{$items});
  0         0  
27             }
28              
29             sub id {
30 0     0 0 0 my ($class, $context, $id, $cnode) = @_;
31 0 0       0 foreach my $child ($cnode?$cnode->children:$context->{xml}->rootNodes) {
32 0         0 my @selection;
33 0 0 0     0 if ($child->attributes->{id} and $child->attributes->{id} eq $id) {
34 0         0 return $child;
35             }
36 0         0 return id($class, $context, $child);
37             }
38             }
39              
40             sub local_name {
41 0     0 0 0 my ($class, $context, $items) = @_;
42 0 0       0 return map { $_->name } $items?@$items:@{$context->items};
  0         0  
  0         0  
43             }
44              
45             sub name {
46             # XXX - out of spe
47 0     0 0 0 return local_name(@_);
48             }
49              
50             # STRING FUNCTIONS
51              
52             sub string {
53 0     0 0 0 my ($class, $context, $items) = @_;
54 0 0       0 return map { $_->value } $items?@$items:@{$context->items};
  0         0  
  0         0  
55             }
56              
57             sub concat {
58 0     0 0 0 my ($class, $context, $str1, $str2) = @_;
59 0         0 return $str1.$str2;
60             }
61              
62             sub starts_with {
63 2     2 0 6 my ($class, $context, $str1, $str2) = @_;
64 2 100       34 return ($str1 =~ /^$str2/)?1:0;
65             }
66              
67             sub contains {
68 2     2 0 6 my ($class, $context, $str1, $str2) = @_;
69 2 100       38 return ($str1 =~ /$str2/)?1:0;
70             }
71              
72             sub substring_before {
73 1     1 0 4 my ($class, $context, $str1, $str2) = @_;
74 1         18 my ($match) = $str1 =~ /(.*?)$str2/;
75 1         6 return $match;
76             }
77              
78             sub substring_after {
79 2     2 0 6 my ($class, $context, $str1, $str2) = @_;
80 2         32 my ($match) = $str1 =~ /$str2(.*)/;
81 2         10 return $match;
82             }
83              
84             sub substring {
85 10     10 0 24 my ($class, $context, $str, $offset, $length) = @_;
86             # handle edge cases as defined in XPath spec
87             # [ http://www.w3.org/TR/xpath ]
88 10 100 100     65 if ($length and $length =~ /(\S+)\s+(\S+)\s+(\S+)/) {
89 3         17 $length = $context->operators->{$2}->($1, $3);
90 3 100 33     24 return "" if(!defined($length) and $offset !~ /^-[0-9]+$/);
91             } else {
92 7 100 100     60 $length = round($class, $context, $length)
93             if ($length and $length =~ /\./);
94             }
95 8 100 100     46 if ($offset and $offset =~ /(\S+)\s+(\S+)\s+(\S+)/) {
96 3         28 $offset = $context->operators->{$2}->($1, $3);
97 3 100       17 return "" unless(defined($offset));
98             } else {
99 5 100       15 $offset = round($class, $context, $offset)
100             if ($offset =~ /\./);
101 5 100 100     19 $length-- if ($length and $offset == 0);
102             }
103 7 100       17 $offset-- if ($offset > 0);
104 7 100       37 return defined($length)
105             ? substr($str, $offset, $length)
106             : substr($str, $offset);
107             }
108              
109             sub string_length {
110 0     0 0 0 my ($class, $context, $str) = @_;
111 0         0 return length($str);
112             }
113              
114             sub normalize_space {
115 0     0 0 0 my ($class, $context, $str) = @_;
116 0         0 $str =~ s/(^\s+|\s+$)//g;
117 0         0 return $str;
118             }
119              
120             sub translate {
121 2     2 0 7 my ($class, $context, $str, $tfrom, $tto) = @_;
122              
123 2         9 my @from = split(//, $tfrom);
124 2         7 my @to = split(//, $tto);
125 2         7 foreach my $i (0..$#from) {
126 7 100       13 if ($to[$i]) {
127 6         64 $str =~ s/$from[$i]/$to[$i]/g;
128             } else {
129 1         10 $str =~ s/$from[$i]//g;
130             }
131             }
132 2         12 return $str;
133             }
134              
135             # BOOLEAN FUNCTIONS
136              
137             sub boolean {
138 0     0 0 0 my ($class, $context, $item) = @_;
139 0 0       0 return $item?1:0;
140             }
141              
142             sub not {
143 0     0 0 0 my ($class, $context, $item) = @_;
144 0 0       0 return !$item?1:0;
145             }
146              
147             sub true {
148 0     0 0 0 return 1;
149             }
150              
151             sub falce {
152 0     0 0 0 return 0;
153             }
154              
155             sub lang {
156 0     0 0 0 my ($class, $context, $lang) = @_;
157             # TODO - implement;
158 0         0 warn __PACKAGE__."::lang() unimplemented";
159             }
160              
161             # NUMBER FUNCTIONS
162              
163             sub number {
164 0     0 0 0 my ($class, $context, $item) = @_;
165 0         0 return 0+$item; # force numeric context
166             }
167              
168             sub sum {
169 0     0 0 0 my ($class, $context, $items) = @_;
170 0         0 my $res = 0;
171 0 0       0 if ($items) {
172 0         0 $res += $_->value for (@$items);
173             }
174 0         0 return $res;
175             }
176              
177             sub floor {
178 0     0 0 0 my ($class, $context, $number) = @_;
179 0         0 return POSIX::floor($number);
180             }
181              
182             sub ceil {
183 0     0 0 0 my ($class, $context, $number) = @_;
184 0         0 return POSIX::ceil($number);
185             }
186              
187             sub round {
188 2     2 0 3 my ($class, $context, $number) = @_;
189 2         7 return int($number + .5 * ($number <=> 0));
190             }
191              
192             1;