File Coverage

lib/HTML/Object/XPath/NodeSet.pm
Criterion Covered Total %
statement 70 100 70.0
branch 5 8 62.5
condition 2 5 40.0
subroutine 22 34 64.7
pod 24 24 100.0
total 123 171 71.9


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/XPath/NodeSet.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::NodeSet;
15             BEGIN
16             {
17 8     8   55 use strict;
  8         19  
  8         277  
18 8     8   48 use warnings;
  8         18  
  8         230  
19             # use parent qw( Module::Generic );
20 8     8   47 use parent qw( Module::Generic::Array );
  8         25  
  8         51  
21 8     8   10248 use vars qw( $TRUE $FALSE $BASE_CLASS $DEBUG $VERSION );
  8         28  
  8         556  
22 8     8   52 use HTML::Object::XPath::Boolean;
  8         19  
  8         428  
23             use overload (
24 8         84 '""' => \&to_literal,
25             'bool' => \&to_boolean,
26 8     8   53 );
  8         17  
27 8     8   1029 our $TRUE = HTML::Object::XPath::Boolean->True;
28 8         50 our $FALSE = HTML::Object::XPath::Boolean->False;
29 8         18 our $BASE_CLASS = 'HTML::Object::XPath';
30 8         19 our $DEBUG = 0;
31 8         192 our $VERSION = 'v0.2.0';
32             };
33              
34 8     8   59 use strict;
  8         14  
  8         204  
35 8     8   45 use warnings;
  8         26  
  8         8196  
36              
37             sub new
38             {
39 2066     2066 1 4425 my $this = shift( @_ );
40 2066   66     11448 return( bless( [] => ( ref( $this ) || $this ) ) );
41             }
42              
43             sub append
44             {
45 875     875 1 1308 my $self = CORE::shift( @_ );
46 875         1453 my( $nodeset ) = @_;
47 875         2712 return( CORE::push( @$self, $nodeset->get_nodelist ) );
48             }
49              
50             # uses array index starting at 1, not 0
51             sub get_node
52             {
53 1218     1218 1 1916 my $self = CORE::shift( @_ );
54 1218         2164 my( $pos ) = @_;
55 1218         4959 return( $self->[ $pos - 1 ] );
56             }
57              
58 1043     1043 1 1430 sub get_nodelist { return( @{$_[0]} ); }
  1043         4087  
59              
60             sub getChildNodes
61             {
62 1     1 1 2 my $self = CORE::shift( @_ );
63 1         3 return( map{ $_->getChildNodes } @$self );
  1         5  
64             }
65              
66             sub getElementById
67             {
68 0     0 1 0 my $self = CORE::shift( @_ );
69 0         0 return( map{ $_->getElementById } @$self );
  0         0  
70             }
71            
72             sub getRootNode
73             {
74 0     0 1 0 my $self = CORE::shift( @_ );
75 0         0 return( $self->[0]->getRootNode );
76             }
77              
78 0     0 1 0 sub new_literal { return( shift->_class_for( 'Literal' )->new( @_ ) ); }
79              
80 0     0 1 0 sub new_number { return( shift->_class_for( 'Number' )->new( @_ ) ); }
81              
82             sub pop
83             {
84 0     0 1 0 my $self = CORE::shift( @_ );
85 0         0 return( CORE::pop( @$self ) );
86             }
87              
88             sub prepend
89             {
90 0     0 1 0 my $self = CORE::shift( @_ );
91 0         0 my( $nodeset ) = @_;
92 0         0 return( CORE::unshift( @$self, $nodeset->get_nodelist ) );
93             }
94              
95             sub push
96             {
97 1464     1464 1 2035 my $self = CORE::shift( @_ );
98 1464         2585 my( @nodes ) = @_;
99 1464         4714 return( CORE::push( @$self, @nodes ) );
100             }
101              
102             sub remove_duplicates
103             {
104 52     52 1 122 my $self = CORE::shift( @_ );
105 52         99 my @unique;
106 52         122 my $last_node = 0;
107 52         198 foreach my $node ( @$self )
108             {
109 135 50       1653 CORE::push( @unique, $node ) unless( $node == $last_node );
110 135         333 $last_node = $node;
111             }
112 52         190 @$self = @unique;
113 52         290 return( $self );
114             }
115              
116             sub reverse
117             {
118 0     0 1 0 my $self = CORE::shift( @_ );
119 0         0 @$self = reverse( @$self );
120 0         0 return( $self );
121             }
122              
123             sub shift
124             {
125 0     0 1 0 my $self = CORE::shift( @_ );
126 0         0 return( CORE::shift( @$self ) );
127             }
128              
129             sub size
130             {
131 1999     1999 1 9077 my $self = CORE::shift( @_ );
132 1999         5873 return( scalar( @$self ) );
133             }
134              
135             sub sort
136             {
137 52     52 1 147 my $self = CORE::shift( @_ );
138 52         314 @$self = CORE::sort { $a->cmp( $b ) } @$self;
  116         3164  
139 52         745 return( $self );
140             }
141              
142             sub string_value
143             {
144 10     10 1 28 my $self = CORE::shift( @_ );
145 10 100       54 return( '' ) unless( @$self );
146 8         80 return( $self->[0]->string_value );
147             }
148              
149             sub string_values
150             {
151 2     2 1 7 my $self = CORE::shift( @_ );
152 2         9 return( map{ $_->string_value } @$self );
  4         30  
153             }
154              
155             sub to_boolean
156             {
157 763     763 1 1114 my $self = CORE::shift( @_ );
158 763 100       2719 return( ( @$self > 0 ) ? $TRUE : $FALSE );
159             }
160              
161             sub to_final_value
162             {
163 18     18 1 40 my $self = CORE::shift( @_ );
164 18         63 return( join( '', map{ $_->string_value } @$self ) );
  77         557  
165             }
166              
167             sub to_literal
168             {
169 0     0 1   my $self = CORE::shift( @_ );
170 0           return( $self->new_literal( join( '', map{ $_->string_value } @$self ) ) );
  0            
171             }
172              
173             sub to_number
174             {
175 0     0 1   my $self = CORE::shift( @_ );
176 0           return( $self->new_number( $self->to_literal ) );
177             }
178              
179             sub unshift
180             {
181 0     0 1   my $self = CORE::shift( @_ );
182 0           my( @nodes ) = @_;
183 0           return( CORE::unshift( @$self, @nodes ) );
184             }
185              
186             sub _class_for
187             {
188 0     0     my( $self, $mod ) = @_;
189 0           eval( "require ${BASE_CLASS}\::${mod};" );
190 0 0         die( $@ ) if( $@ );
191             # ${"${BASE_CLASS}\::${mod}\::DEBUG"} = $DEBUG;
192 0   0       eval( "\$${BASE_CLASS}\::${mod}\::DEBUG = " . ( $DEBUG // '' ) );
193 0           return( "${BASE_CLASS}::${mod}" );
194             }
195              
196             1;
197             # NOTE: POD
198             __END__
199              
200             =encoding utf-8
201              
202             =head1 NAME
203              
204             HTML::Object::XPath::NodeSet - HTML Object XPath Node Set
205              
206             =head1 SYNOPSIS
207              
208             use HTML::Object::XPath::NodeSet;
209             my $set = HTML::Object::XPath::NodeSet->new ||
210             die( HTML::Object::XPath::NodeSet->error, "\n" );
211              
212             my $results = $xp->find( '//someelement' );
213             if( !$results->isa( 'HTML::Object::XPath::NodeSet' ) )
214             {
215             print( "Found $results\n" );
216             exit;
217             }
218            
219             foreach my $context ( $results->get_nodelist )
220             {
221             my $newresults = $xp->find( './other/element', $context );
222             # ...
223             }
224              
225             =head1 VERSION
226              
227             v0.2.0
228              
229             =head1 DESCRIPTION
230              
231             This module contains an ordered list of L<nodes|HTML::Object::Element>. The nodes each take the same format as described in L<HTML::Object::XPath>.
232              
233             =head1 METHODS
234              
235             =head2 new
236              
237             You should never have to create a new NodeSet object, as it is all done for you by L<HTML::Object::XPath>.
238              
239             =head2 append
240              
241             Given a C<nodeset>, this appends the list of nodes in C<nodeset> to the end of the current list.
242              
243             =head2 get_node
244              
245             Provided with an integer representing a C<position> and this returns the node at C<position>.
246              
247             The node position in XPath is based at 1, not 0.
248              
249             =head2 get_nodelist
250              
251             Returns a list of nodes. See L<HTML::Object::XPath> for the format of the nodes.
252              
253             =head2 getChildNodes
254              
255             Returns a list of all elements' own child nodes by calling C<getChildNodes> on each one of them.
256              
257             =head2 getElementById
258              
259             Returns a list of all elements' own id by calling C<getElementById> on each one of them.
260              
261             =head2 getRootNode
262              
263             Returns the first element's value of C<getRootNode>
264              
265             =head2 new_literal
266              
267             Returns a new L<HTML::Object::XPath::Literal> object, passing it whatever arguments was provided.
268              
269             =head2 new_number
270              
271             Returns a new L<HTML::Object::XPath::Number> object, passing it whatever arguments was provided.
272              
273             =head2 pop
274              
275             Equivalent to perl's L<perlfunc/pop> function. This removes the last element from our stack and returns it.
276              
277             =head2 prepend
278              
279             Given a C<nodeset>, prepends the list of nodes in C<nodeset> to the front of the current list.
280              
281             =head2 push
282              
283             Provided with a list of nodes and this will add them to the stack in this object.
284              
285             Equivalent to perl's L<perlfunc/push> function.
286              
287             =head2 remove_duplicates
288              
289             This removes any duplicates there might be in our internal list of elements.
290              
291             =head2 reverse
292              
293             This method reverse the order of the elements in our internal list of elements.
294              
295             =head2 shift
296              
297             Equivalent to perl's L<perlfunc/shift> function.
298              
299             =head2 size
300              
301             Returns the number of nodes in the L<HTML::Object::XPath::NodeSet>.
302              
303             =head2 sort
304              
305             This method sorts all the elements by comparing them to one another using C<cmp>
306              
307             =head2 string_value
308              
309             Returns the string-value of the first node in the list.
310              
311             See the L<HTML::Object::XPath> specification for what "string-value" means.
312              
313             =head2 string_values
314              
315             Returns a list of the string-values of all the nodes in the list.
316              
317             =head2 to_boolean
318              
319             Returns L<true|HTML::Object::XPath::Boolean> if there are elements in our internal array of elements, or L<false|HTML::Object::XPath::Boolean> otherwise.
320              
321             =head2 to_final_value
322              
323             Returns a string resulting from the concatenation of each elements' string value.
324              
325             =head2 to_literal
326              
327             Returns the concatenation of all the string-values of all the nodes in the list.
328              
329             =head2 to_number
330              
331             Returns a new L<number object|HTML::Object::XPath::Number> from the value returned from L</to_literal>
332              
333             =head2 unshift
334              
335             Provided with a list of nodes and this will add them at the top of the stack in this object.
336              
337             Equivalent to perl's L<perlfunc/unshift> function.
338              
339             =head1 AUTHOR
340              
341             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
342              
343             =head1 SEE ALSO
344              
345             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>
346              
347             =head1 COPYRIGHT & LICENSE
348              
349             Copyright(c) 2021 DEGUEST Pte. Ltd.
350              
351             All rights reserved
352              
353             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
354              
355             =cut