File Coverage

lib/HTML/Object/XPath/Function.pm
Criterion Covered Total %
statement 108 259 41.7
branch 17 92 18.4
condition 1 5 20.0
subroutine 23 45 51.1
pod 34 34 100.0
total 183 435 42.0


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/XPath/Function.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2021/12/05
7             ## Modified 2022/09/18
8             ## All rights reserved
9             ##
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package HTML::Object::XPath::Function;
15             BEGIN
16             {
17 8     8   62 use strict;
  8         21  
  8         301  
18 8     8   74 use warnings;
  8         21  
  8         260  
19 8     8   43 use parent qw( Module::Generic );
  8         30  
  8         45  
20 8     8   537 use vars qw( $TRUE $FALSE $BASE_CLASS $DEBUG $VERSION );
  8         263  
  8         556  
21 8     8   56 use HTML::Object::XPath::Boolean;
  8         24  
  8         604  
22 8     8   204 our $TRUE = HTML::Object::XPath::Boolean->True;
23 8         209 our $FALSE = HTML::Object::XPath::Boolean->False;
24 8         33 our $BASE_CLASS = 'HTML::Object::XPath';
25 8         18 our $DEBUG = 0;
26 8         183 our $VERSION = 'v0.2.0';
27             };
28              
29 8     8   58 use strict;
  8         16  
  8         181  
30 8     8   44 use warnings;
  8         13  
  8         26382  
31              
32             sub init
33             {
34 25     25 1 2111 my $self = shift( @_ );
35             # XPath Parser -> HTML::Object::XPath
36 25         210 $self->{pp} = shift( @_ );
37 25         75 $self->{name} = shift( @_ );
38 25         47 $self->{params} = shift( @_ );
39 25         42 $self->{_init_strict_use_sub} = 1;
40 25 50       85 $self->SUPER::init( @_ ) || return( $self->pass_error );
41 25         1577 return( $self );
42             }
43              
44             sub as_string
45             {
46 0     0 1 0 my $self = shift( @_ );
47 0         0 my $string = $self->{name} . '(';
48 0         0 my $second;
49 0         0 foreach( @{$self->{params}} )
  0         0  
50             {
51 0 0       0 $string .= ',' if( $second++ );
52 0         0 $string .= $_->as_string;
53             }
54 0         0 $string .= ')';
55 0         0 return( $string );
56             }
57              
58             sub as_xml
59             {
60 0     0 1 0 my $self = shift( @_ );
61 0         0 my $string = sprintf( '<Function name="%s"', $self->{name} );
62 0         0 my $params = '';
63 0         0 foreach( @{$self->{params}} )
  0         0  
64             {
65 0         0 $params .= '<Param>' . $_->as_xml . "</Param>\n";
66             }
67 0 0       0 if( $params )
68             {
69 0         0 $string .= ">\n$params</Function>\n";
70             }
71             else
72             {
73 0         0 $string .= " />\n";
74             }
75 0         0 return( $string );
76             }
77              
78             sub boolean
79             {
80 0     0 1 0 my $self = shift( @_ );
81 0         0 my( $node, @params ) = @_;
82 0 0       0 die( "boolean: Incorrect number of parameters\n" ) if( @params != 1 );
83 0         0 return( $params[0]->to_boolean );
84             }
85              
86             sub ceiling
87             {
88 0     0 1 0 my $self = shift( @_ );
89 0         0 my( $node, @params ) = @_;
90 0         0 require POSIX;
91 0         0 my $num = $self->number( $node, @params );
92 0         0 return( $self->new_number( POSIX::ceil( $num->value ) ) );
93             }
94              
95             sub concat
96             {
97 8     8 1 16 my $self = shift( @_ );
98 8         19 my( $node, @params ) = @_;
99 8 50       27 die( "concat: Too few parameters\n" ) if( @params < 2 );
100             # TODO: Check for improvement
101 8         22 my $string = join( '', map{ $_->string_value } @params );
  24         62  
102 8         54 return( $self->new_literal( $string ) );
103             }
104              
105             sub contains
106             {
107 8     8 1 23 my $self = shift( @_ );
108 8         18 my( $node, @params ) = @_;
109 8 50       37 die( "starts-with: incorrect number of params\n" ) unless( @params == 2 );
110 8         29 my $value = $params[1]->string_value;
111 8 100       21 if( $params[0]->string_value =~ /(.*?)\Q$value\E(.*)/ )
112             {
113 4         24 return( $TRUE );
114             }
115 4         19 return( $FALSE );
116             }
117              
118             sub count
119             {
120 20     20 1 38 my $self = shift( @_ );
121 20         36 my( $node, @params ) = @_;
122 20 50       80 die( "count: Parameter must be a NodeSet\n" ) unless( $params[0]->isa( 'HTML::Object::XPath::NodeSet' ) );
123 20         58 return( $self->new_number( $params[0]->size ) );
124             }
125              
126             sub evaluate
127             {
128 50     50 1 96 my $self = shift( @_ );
129 50         69 my $node = shift( @_ );
130 50         278 while( $node->isa( 'HTML::Object::XPath::NodeSet' ) )
131             {
132 6         13 $node = $node->get_node(1);
133             }
134 50         77 my @params;
135 50         73 foreach my $param ( @{$self->{params}} )
  50         170  
136             {
137 76         198 my $results = $param->evaluate( $node );
138 76         205 push( @params, $results );
139             }
140 50         220 return( $self->_execute( $self->{name}, $node, @params ) );
141             }
142              
143             sub false
144             {
145 0     0 1 0 my $self = shift( @_ );
146 0         0 my( $node, @params ) = @_;
147 0 0       0 die( "true: function takes no parameters\n" ) if( @params > 0 );
148 0         0 return( $FALSE );
149             }
150              
151             sub floor
152             {
153 0     0 1 0 my $self = shift( @_ );
154 0         0 my( $node, @params ) = @_;
155 0         0 require POSIX;
156 0         0 my $num = $self->number( $node, @params );
157 0         0 return( $self->new_number( POSIX::floor( $num->value ) ) );
158             }
159              
160             sub id
161             {
162 4     4 1 16 my $self = shift( @_ );
163 4         22 my( $node, @params ) = @_;
164 4 50       14 die( "id: Function takes 1 parameter\n" ) unless( @params == 1 );
165 4         18 my $results = $self->new_nodeset();
166 4 50       30 if( $self->_is_a( $params[0] => 'HTML::Object::XPath::NodeSet' ) )
167             {
168             # result is the union of applying id() to the
169             # string value of each node in the nodeset.
170 0         0 foreach my $node ( $params[0]->get_nodelist )
171             {
172 0         0 my $string = $node->string_value;
173 0         0 $results->append( $self->id( $node, $self->new_literal( $string ) ) );
174             }
175             }
176             # The actual id() function...
177             else
178             {
179 4         200 my $string = $self->string( $node, $params[0] );
180             # get perl scalar
181             # $_ = $string->value;
182             # split $_
183             # my @ids = split;
184             # die( "Splitting '", $string->value, "' with result: '", join( "', '", @ids ), "'\n" );
185 4         15 my @ids = split( /[[:blank:]]/, $string->value );
186 4 50       27 if( $node->isAttributeNode )
187             {
188 0         0 warn( "calling \($node->getParentNode->getRootNode->getChildNodes)->[0] on attribute node\n" );
189 0         0 $node = ( $node->getParentNode->getRootNode->getChildNodes )->[0];
190             }
191 4         23 foreach my $id ( @ids )
192             {
193 4 50       13 if( my $found = $node->getElementById( $id ) )
194             {
195 4         535 $results->push( $found );
196             }
197             }
198             }
199 4         19 return( $results );
200             }
201              
202             sub lang
203             {
204 0     0 1 0 my $self = shift( @_ );
205 0         0 my( $node, @params ) = @_;
206 0 0       0 die( "lang: function takes 1 parameter\n" ) if( @params != 1 );
207 0         0 my $lang = $node->findvalue( '(ancestor-or-self::*[@xml:lang]/@xml:lang)[1]' );
208 0         0 my $lclang = lc( $params[0]->string_value );
209             # warn("Looking for lang($lclang) in $lang\n");
210 0 0       0 if( substr( lc( $lang ), 0, length( $lclang ) ) eq $lclang )
211             {
212 0         0 return( $TRUE );
213             }
214             else
215             {
216 0         0 return( $FALSE );
217             }
218             }
219              
220             sub last
221             {
222 0     0 1 0 my $self = shift( @_ );
223 0         0 my( $node, @params ) = @_;
224 0 0       0 die( "last: function doesn't take parameters\n" ) if( scalar( @params ) );
225 0         0 return( $self->new_number( $self->{pp}->_get_context_size ) );
226             }
227              
228             sub local_name
229             {
230 0     0 1 0 my $self = shift( @_ );
231 0         0 my( $node, @params ) = @_;
232 0 0       0 if( @params > 1 )
    0          
233             {
234 0         0 die( "name() function takes one or no parameters\n" );
235             }
236             elsif( @params )
237             {
238 0         0 my $nodeset = shift( @params );
239 0         0 $node = $nodeset->get_node(1);
240             }
241 0         0 return( $self->new_literal( $node->getLocalName ) );
242             }
243              
244             sub name
245             {
246 0     0 1 0 my $self = shift( @_ );
247 0         0 my( $node, @params ) = @_;
248 0 0       0 if( @params > 1 )
    0          
249             {
250 0         0 die( "name() function takes one or no parameters\n" );
251             }
252             elsif( @params )
253             {
254 0         0 my $nodeset = shift( @params );
255 0         0 $node = $nodeset->get_node(1);
256             }
257 0         0 return( $self->new_literal( $node->getName ) );
258             }
259              
260             sub namespace_uri
261             {
262 0     0 1 0 my $self = shift( @_ );
263 0         0 my( $node, @params ) = @_;
264 0         0 die( "namespace-uri: Function not supported\n" );
265             }
266              
267 22     22 1 76 sub new_literal { return( shift->_class_for( 'Literal' )->new( @_ ) ); }
268              
269 4     4 1 14 sub new_nodeset { return( shift->_class_for( 'NodeSet' )->new( @_ ) ); }
270              
271 20     20 1 59 sub new_number { return( shift->_class_for( 'Number' )->new( @_ ) ); }
272              
273             sub normalize_space
274             {
275 8     8 1 18 my $self = shift( @_ );
276 8         21 my( $node, @params ) = @_;
277 8 50       28 die( "normalize-space: Wrong number of params\n" ) if( @params > 1 );
278 8         17 my $str;
279 8 50       20 if( @params )
280             {
281 8         34 $str = $params[0]->string_value;
282             }
283             else
284             {
285 0         0 $str = $node->string_value;
286             }
287             # $str =~ s/^\s*//;
288             # $str =~ s/\s*$//;
289 8         5643 $str =~ s/^[[:blank:]\h]+|[[:blank:]\h]+$//g;
290             # $str =~ s/\s+/ /g;
291 8         63 $str =~ s/[[:blank:]\h]+/ /g;
292 8         62 return( $self->new_literal( $str ) );
293             }
294              
295             sub not
296             {
297 0     0 1 0 my $self = shift( @_ );
298 0         0 my( $node, @params ) = @_;
299 0 0       0 $params[0] = $params[0]->to_boolean unless( $params[0]->isa( 'HTML::Object::XPath::Boolean' ) );
300 0 0       0 return( $params[0]->value ? $FALSE : $TRUE );
301             }
302              
303             sub number
304             {
305 0     0 1 0 my $self = shift( @_ );
306 0         0 my( $node, @params ) = @_;
307 0 0       0 die( "number: Too many parameters\n" ) if( @params > 1 );
308 0 0       0 if( @params )
309             {
310 0 0       0 if( $params[0]->isa( 'HTML::Object::XPath::Node' ) )
311             {
312 0         0 return( $self->new_number( $params[0]->string_value ) );
313             }
314 0         0 return( $params[0]->to_number );
315             }
316 0         0 return( $self->new_number( $node->string_value ) );
317             }
318              
319             sub position
320             {
321 0     0 1 0 my $self = shift( @_ );
322 0         0 my( $node, @params ) = @_;
323 0 0       0 if( scalar( @params ) )
324             {
325 0         0 die( "position: function doesn't take parameters [ ", @params, " ]\n" );
326             }
327             # return pos relative to axis direction
328 0         0 return( $self->new_number( $self->{pp}->_get_context_pos ) );
329             }
330              
331             sub round
332             {
333 0     0 1 0 my $self = shift( @_ );
334 0         0 my( $node, @params ) = @_;
335 0         0 my $num = $self->number( $node, @params );
336 0         0 require POSIX;
337             # Yes, I know the spec says do not do this...
338             # return( $self->new_number( POSIX::floor( $num->value + 0.5 ) ) );
339 0         0 return( $self->new_number( CORE::sprintf( '%.*f', $num->value ) ) );
340             }
341              
342             sub starts_with
343             {
344 0     0 1 0 my $self = shift( @_ );
345 0         0 my( $node, @params ) = @_;
346 0 0       0 die( "starts-with: incorrect number of params\n" ) unless( @params == 2 );
347 0         0 my( $string1, $string2 ) = ( $params[0]->string_value, $params[1]->string_value );
348 0 0       0 if( substr( $string1, 0, length( $string2 ) ) eq $string2 )
349             {
350 0         0 return( $TRUE );
351             }
352 0         0 return( $FALSE );
353             }
354              
355             sub string
356             {
357 4     4 1 9 my $self = shift( @_ );
358 4         10 my( $node, @params ) = @_;
359 4 50       14 die( "string: Too many parameters\n" ) if( @params > 1 );
360 4 50       13 if( @params )
361             {
362 4         15 return( $self->new_literal( $params[0]->string_value ) );
363             }
364            
365             # TODO - this MUST be wrong! - not sure now. -matt
366 0         0 return( $self->new_literal( $node->string_value ) );
367             # default to nodeset with just $node in.
368             }
369              
370             sub string_length
371             {
372 0     0 1 0 my $self = shift( @_ );
373 0         0 my( $node, @params ) = @_;
374 0 0       0 die( "string-length: Wrong number of params\n" ) if( @params > 1 );
375 0 0       0 if( @params )
376             {
377 0         0 return( $self->new_number( length( $params[0]->string_value ) ) );
378             }
379             else
380             {
381 0         0 return( $self->new_number( length( $node->string_value ) ) );
382             }
383             }
384              
385             sub substring
386             {
387 0     0 1 0 my $self = shift( @_ );
388 0         0 my( $node, @params ) = @_;
389 0 0 0     0 die( "substring: Wrong number of parameters\n" ) if( @params < 2 || @params > 3 );
390 0         0 my( $str, $offset, $len );
391 0         0 $str = $params[0]->string_value;
392 0         0 $offset = $params[1]->value;
393             # uses 1 based offsets
394 0         0 $offset--;
395 0 0       0 if( @params == 3 )
396             {
397 0         0 $len = $params[2]->value;
398 0         0 return( $self->new_literal( substr( $str, $offset, $len ) ) );
399             }
400             else
401             {
402 0         0 return( $self->new_literal( substr( $str, $offset ) ) );
403             }
404             }
405              
406             sub substring_after
407             {
408 2     2 1 6 my $self = shift( @_ );
409 2         7 my( $node, @params ) = @_;
410 2 50       7 die( "starts-with: incorrect number of params\n" ) unless( @params == 2 );
411 2         10 my $long = $params[0]->string_value;
412 2         35 my $short = $params[1]->string_value;
413 2 50       34 if( $long =~ m{\Q$short\E(.*)$} )
414             {
415 2         8 return( $self->new_literal( $1 ) );
416             }
417             else
418             {
419 0         0 return( $self->new_literal( '' ) );
420             }
421             }
422              
423             sub substring_before
424             {
425 0     0 1 0 my $self = shift( @_ );
426 0         0 my( $node, @params ) = @_;
427 0 0       0 die( "starts-with: incorrect number of params\n" ) unless( @params == 2 );
428 0         0 my $long = $params[0]->string_value;
429 0         0 my $short = $params[1]->string_value;
430 0 0       0 if( $long =~ m{^(.*?)\Q$short} )
431             {
432 0         0 return( $self->new_literal( $1 ) );
433             }
434             else
435             {
436 0         0 return( $self->new_literal( '' ) );
437             }
438             }
439              
440             sub sum
441             {
442 0     0 1 0 my $self = shift( @_ );
443 0         0 my( $node, @params ) = @_;
444 0 0       0 die( "sum: Parameter must be a NodeSet\n" ) unless( $params[0]->isa( 'HTML::Object::XPath::NodeSet' ) );
445 0         0 my $sum = 0;
446 0         0 foreach my $node ( $params[0]->get_nodelist )
447             {
448 0         0 $sum += $self->number( $node )->value;
449             }
450 0         0 return( $self->new_number( $sum ) );
451             }
452              
453             sub translate
454             {
455 0     0 1 0 my $self = shift( @_ );
456 0         0 my( $node, @params ) = @_;
457 0 0       0 die( "translate: Wrong number of params\n" ) if( @params != 3 );
458 0         0 local $_ = $params[0]->string_value;
459 0         0 my $find = $params[1]->string_value;
460 0         0 my $repl = $params[2]->string_value;
461 0         0 $repl= substr( $repl, 0, length( $find ) );
462 0         0 my %repl;
463 0         0 @repl{split( //, $find )} = split( //, $repl );
464 0         0 s{(.)}
465 0 0       0 {
    0          
466             CORE::exists( $repl{$1} ) ? defined( $repl{$1} ) ? $repl{$1} : '' : $1
467 0         0 }ges;
468             return( $self->new_literal( $_ ) );
469             }
470              
471             sub true
472 0     0 1 0 {
473 0         0 my $self = shift( @_ );
474 0 0       0 my( $node, @params ) = @_;
475 0         0 die( "true: function takes no parameters\n" ) if( @params > 0 );
476             return( $TRUE );
477             }
478              
479             sub _class_for
480 46     46   103 {
481 46         2450 my( $self, $mod ) = @_;
482 46 50       193 eval( "require ${BASE_CLASS}\::${mod};" );
483             die( $@ ) if( $@ );
484 46   50     1939 # ${"${BASE_CLASS}\::${mod}\::DEBUG"} = $DEBUG;
485 46         410 eval( "\$${BASE_CLASS}\::${mod}\::DEBUG = " . ( $DEBUG // 0 ) );
486             return( "${BASE_CLASS}::${mod}" );
487             }
488              
489             sub _execute
490 50     50   100 {
491 50         135 my $self = shift( @_ );
492 50         141 my( $name, $node, @params ) = @_;
493 8     8   74 $name =~ s/-/_/g;
  8         22  
  8         484  
494 50         228 no strict 'refs';
495             return( $self->$name( $node, @params ) );
496             }
497              
498             1;
499             # NOTE: POD
500             __END__
501              
502             =encoding utf-8
503              
504             =head1 NAME
505              
506             HTML::Object::XPath::Function - HTML Object XPath Functions
507              
508             =head1 SYNOPSIS
509              
510             use HTML::Object::XPath::Function;
511             my $func = HTML::Object::XPath::Function->new ||
512             die( HTML::Object::XPath::Function->error, "\n" );
513              
514             =head1 VERSION
515              
516             v0.2.0
517              
518             =head1 DESCRIPTION
519              
520             This module implements various XPath functions described below.
521              
522             =head1 CONSTRUCTOR
523              
524             Provided with a L<XPath object|HTML::Object::XPath>, a function C<name> and function C<parameters> and this will instantiate a new L<HTML::Object::Function> object and return it.
525              
526             =head1 METHODS
527              
528             =head2 as_string
529              
530             Returns a string representation of this function object.
531              
532             =head2 as_xml
533              
534             Returns a xml representation of this function object.
535              
536             =head2 boolean
537              
538             Provided with a L<node object|HTML::Object::Element> and a list of parameters and this will return the first parameter as a L<boolean object|HTML::Object::XPath::Booleab>. It will raise an exception if there are more than one arguments provided.
539              
540             =head2 ceiling
541              
542             Provided with a L<node object|HTML::Object::Element> and an optional parameter, and this will return the L<ceiling|POSIX/ceil> of the string value of the node or that of the parameter provided, if any.
543              
544             It returns its value as a new L<number object|HTML::Object::XPath::Number>. It will raise an exception if more than one parameter was provided.
545              
546             =head2 concat
547              
548             Provided with a L<node object|HTML::Object::Element> and a list of 2 parameters or more and this will return a new L<literal object|HTML::Object::XPath::Literal> from the concatenation of each parameter string value.
549              
550             =head2 contains
551              
552             Provided with a L<node object|HTML::Object::Element> and a list of exactly 2 parameters and this will return L<true|HTML::Object::XPath::Boolean> if the first parameter match the second one as a regular expression, or returns L<false|HTML::Object::XPath::Boolean> otherwise.
553              
554             =head2 count
555              
556             Provided with a L<node object|HTML::Object::Element> and a L<node set|HTML::Object::XPath::NodeSet> and this will return the size of the node set as a L<number|HTML::Object::XPath::Number>
557              
558             =head2 evaluate
559              
560             Provided with a L<node object|HTML::Object::Element> and this will evaluate the node using each parameter set during object instantiation and add the result for each in a new array.
561              
562             It will then return the execution of the function name on the node passing it the list of previously collected results.
563              
564             =head2 false
565              
566             Returns L<false|HTML::Object::XPath::Boolean> and it will raise an exception if any arguments was provided.
567              
568             =head2 floor
569              
570             Provided with a L<node object|HTML::Object::Element> and an optional parameter, and this will return the L<floor|
571             POSIX/floor> of the string value of the node or that of the parameter provided, if any.
572              
573             It returns its value as a new L<number object|HTML::Object::XPath::Number>. It will raise an exception if more than one parameter was provided.
574              
575             =head2 id
576              
577             Provided with a L<node object|HTML::Object::Element> and 1 parameter, and this will return a new L<node set|HTML::Object::XPath::NodeSet> of L<element object|HTML::Object::Element> who match the id found in the node provided.
578              
579             =head2 lang
580              
581             Provided with a L<node object|HTML::Object::Element> and 1 parameter, and this will return L<true|HTML::Object::XPath::Boolean> if the node lang, if any at all, match the one provide as a parameter, otherwise it returns L<false|HTML::Object::XPath::Boolean>.
582              
583             =head2 last
584              
585             This takes no argument and returns the size, as a L<number|HTML::Object::XPath::Number> of the nodes in the context set in XPath.
586              
587             =head2 local_name
588              
589             Provided with a L<node object|HTML::Object::Element> and optionally some parameter and this will return the local name of the node, or that of the first parameter provided, if any, as a L<literal object|HTML::Object::XPath::Literal>
590              
591             =head2 name
592              
593             Provided with a L<node object|HTML::Object::Element> and optionally some parameter and this will return the name of the node, or that of the first parameter provided, if any, as a L<literal object|HTML::Object::XPath::Literal>
594              
595             =head2 namespace_uri
596              
597             This is an unsupported function and it will raise an exception when called.
598              
599             =head2 new_literal
600              
601             Returns a new L<literal object|HTML::Object::XPath::Literal> passing it whatever arguments was provided.
602              
603             =head2 new_nodeset
604              
605             Returns a new L<node set object|HTML::Object::XPath::NodeSet> passing it whatever arguments was provided.
606              
607             =head2 new_number
608              
609             Returns a new L<number object|HTML::Object::XPath::Number> passing it whatever arguments was provided.
610              
611             =head2 normalize_space
612              
613             Provided with a L<node object|HTML::Object::Element> and optionally some parameter and this will take the string value of the node, or that of the first parameter, if any at al, and remove any leading or trailing spaces as well as replacing multiple spaces by just one space, and return the new string as a L<literal object|HTML::Object::XPath::Literal>
614              
615             =head2 not
616              
617             Provided with a L<node object|HTML::Object::Element> and one parameter and this will return L<true|HTML::Object::XPath::Boolean> if the value of the first parameter is B<not> true, or L<false|HTML::Object::XPath::Boolean> otherwise.
618              
619             =head2 number
620              
621             Provided with a L<node object|HTML::Object::Element> and optionally one parameter and this will return the node string value, or that of the parameter provided, if any, as a new L<number object|HTML::Object::XPath::Number>
622              
623             =head2 position
624              
625             Returns th context position as a L<number|HTML::Object::XPath::Number>. It will raise an exception if any parameter was provided.
626              
627             =head2 round
628              
629             =head2 starts_with
630              
631             Provided with a L<node object|HTML::Object::Element> and two parameters and this will return L<true|HTML::Object::XPath::Boolean> if the string value of the second parameter is at the beginning of the first parameter, or L<false|HTML::Object::XPath::Boolean> otherwise.
632              
633             =head2 string
634              
635             Provided with a L<node object|HTML::Object::Element> and one parameter and this returns the parameter string value as a new L<literal object|HTML::Object::XPath::Literal>
636              
637             It will raise an exception if more than one parameter was provided.
638              
639             =head2 string_length
640              
641             Provided with a L<node object|HTML::Object::Element> and optionally one parameter and this will return the size, as a L<number|HTML::Object::XPath::Number>, of the string value of the node or that of the parameter if any was provided.
642              
643             =head2 substring
644              
645             Provided with a L<node object|HTML::Object::Element> and two or three parameters and this returns the substring of of the first parameter as a value, at offset specified by the second parameter, and optionally for a length defined by a third parameter, if any. If no third parameter is provided, then it will be until the end of the string.
646              
647             It returns the substring as a new L<literal object|HTML::Object::XPath::Literal>. It will raise an exception if less than 2 or more than 3 parameters were provided.
648              
649             =head2 substring_after
650              
651             Provided with a L<node object|HTML::Object::Element> and two parameters and this will return the string that follows the string value of the second parameter in the first one up to its end.
652              
653             It returns the substring as a new L<literal object|HTML::Object::XPath::Literal>. It will raise an exception if less or more than 2 parameters were provided.
654              
655             =head2 substring_before
656              
657             Provided with a L<node object|HTML::Object::Element> and two parameters and this will return the string that precede the string value of the second parameter in the first one up to its start.
658              
659             It returns the substring as a new L<literal object|HTML::Object::XPath::Literal>. It will raise an exception if less or more than 2 parameters were provided.
660              
661             =head2 sum
662              
663             Provided with a L<node object|HTML::Object::Element> and a parameters that must be a L<node set|HTML::Object::XPath::NodeSet> and this will return the cumulative string value of each node as a number.
664              
665             It returns the resulting total as a new L<number> object|HTML::Object::XPath::Number>. It will raise an exception if the parameter provided is not a L<HTML::Object::XPath::NodeSet> object.
666              
667             =head2 translate
668              
669             Provided with a L<node object|HTML::Object::Element> and three parameters, and this will search in the first parameter for any occurrence of characters found in the second parameter and replace them with their alternative at the exact same position in string in the third parameter.
670              
671             It returns the substring as a new L<literal object|HTML::Object::XPath::Literal>. It will raise an exception if less or more than 3 parameters were provided.
672              
673             =head2 true
674              
675             Returns L<true|HTML::Object::XPath::Boolean> and it will raise an exception if any arguments was provided.
676              
677             =head1 AUTHOR
678              
679             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
680              
681             =head1 SEE ALSO
682              
683             L<HTML::Object::XPath>, L<HTML::Object::XPath::Boolean>, L<HTML::Object::XPath::Expr>, L<HTML::Object::XPath::Function>, L<HTML::Object::XPath::Literal>, L<HTML::Object::XPath::LocationPath>, L<HTML::Object::XPath::NodeSet>, L<HTML::Object::XPath::Number>, L<HTML::Object::XPath::Root>, L<HTML::Object::XPath::Step>, L<HTML::Object::XPath::Variable>
684              
685             =head1 COPYRIGHT & LICENSE
686              
687             Copyright(c) 2021 DEGUEST Pte. Ltd.
688              
689             All rights reserved
690              
691             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
692              
693             =cut