File Coverage

lib/HTML/Object/DOM/NodeIterator.pm
Criterion Covered Total %
statement 28 31 90.3
branch n/a
condition n/a
subroutine 10 13 76.9
pod 4 4 100.0
total 42 48 87.5


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/DOM/NodeIterator.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2021/12/20
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::DOM::NodeIterator;
15             BEGIN
16             {
17 2     2   3271 use strict;
  2         4  
  2         61  
18 2     2   13 use warnings;
  2         5  
  2         68  
19 2     2   15 use parent qw( HTML::Object::DOM::NodeIteratorShared );
  2         4  
  2         12  
20 2     2   120 use vars qw( $VERSION );
  2         3  
  2         82  
21             # To import its constants
22 2     2   12 use HTML::Object::DOM::Node;
  2         4  
  2         14  
23 2     2   650 use HTML::Object::DOM::NodeFilter qw( :all );
  2         6  
  2         9  
24 2     2   767 our $VERSION = 'v0.2.0';
25             };
26              
27 2     2   14 use strict;
  2         4  
  2         41  
28 2     2   13 use warnings;
  2         4  
  2         286  
29              
30             # Note: method init is inherited
31              
32 0     0 1 0 sub detach { return; }
33              
34             # Note: property expandEntityReferences read-only is inherited
35              
36             # Note: property filter read-only inherited
37              
38             # Note: method nextNode is inherited
39              
40             # Note: property pointerBeforeReferenceNode read-only
41 0     0 1 0 sub pointerBeforeReferenceNode : lvalue { return( shift->_set_get_boolean( 'pointerbeforereferencenode', @_ ) ); }
42              
43 0     0 1 0 sub pos { return( shift->{_relative_pos} ); }
44              
45             # Note: method previousNode is inherited
46              
47             # Note: property referenceNode read-only
48             sub referenceNode
49             {
50 7     7 1 993 my $self = shift( @_ );
51 7         22 my $elems = $self->_elements;
52 7         6127 return( $elems->index( $self->{_pos} ) );
53             }
54              
55             # Note: property root read-only is inherited
56              
57             # Note: property whatToShow read-only is inherited
58              
59             1;
60             # NOTE: POD
61             __END__
62              
63             =encoding utf-8
64              
65             =head1 NAME
66              
67             HTML::Object::DOM::NodeIterator - HTML Object DOM Node Iterator Class
68              
69             =head1 SYNOPSIS
70              
71             With just one argument, this default to search for everything (C<SHOW_ALL>) and to use the default filter, which always returns C<FILTER_ACCEPT>
72              
73             use HTML::Object::DOM::NodeIterator;
74             my $nodes = HTML::Object::DOM::NodeIterator->new( $root_node ) ||
75             die( HTML::Object::DOM::NodeIterator->error, "\n" );
76              
77             Or, passing an anonymous subroutine as the filter
78              
79             my $nodes = HTML::Object::DOM::NodeIterator->new(
80             $root_node,
81             $what_to_show_bit,
82             sub{ return( FILTER_ACCEPT ); }
83             ) || die( HTML::Object::DOM::NodeIterator->error, "\n" );
84              
85             Or, passing an hash reference with a property 'acceptNode' whose value is an anonymous subroutine, as the filter
86              
87             my $nodes = HTML::Object::DOM::NodeIterator->new(
88             $root_node,
89             $what_to_show_bit,
90             {
91             acceptNode => sub{ return( FILTER_ACCEPT ); }
92             }
93             ) || die( HTML::Object::DOM::NodeIterator->error, "\n" );
94              
95             Or, passing an object that implements the method "acceptNode"
96              
97             my $nodes = HTML::Object::DOM::NodeIterator->new(
98             $root_node,
99             $what_to_show_bit,
100             # This object must implement the acceptNode method
101             My::Customer::NodeFilter->new
102             ) || die( HTML::Object::DOM::NodeIterator->error, "\n" );
103              
104             There is also L<HTML::Object::DOM::TreeWalker>, which performs a somewhat similar function.
105              
106             Choose L<HTML::Object::DOM::NodeIterator> when you only need a simple iterator to filter and browse the selected nodes, and choose L<HTML::Object::DOM::TreeWalker> when you need to access to the node and its siblings.
107              
108             =head1 VERSION
109              
110             v0.2.0
111              
112             =head1 DESCRIPTION
113              
114             The C<NodeIterator> interface represents an iterator over the members of a list of the L<nodes|HTML::Object::DOM::Node> in a subtree of the L<DOM|HTML::Object::DOM>. The nodes will be returned in document order.
115              
116             A C<NodeIterator> can be created using the L<HTML::Object::DOM::Document/createNodeIterator> method, as follows:
117              
118             use HTML::Object::DOM;
119             my $parser = HTML::Object::DOM->new;
120             my $doc = $parser->parse_data( $some_html_data ) || die( $parser->error );
121             my $nodeIterator = $doc->createNodeIterator( $root, $whatToShow, $filter ) ||
122             die( $doc->error );
123              
124             =head1 PROPERTIES
125              
126             =head2 expandEntityReferences
127              
128             Normally this is read-only, but under perl you can set whatever boolean value you want.
129              
130             Under JavaScript, this is a boolean value indicating if, when discarding an C<EntityReference> its whole sub-tree must be discarded at the same time.
131              
132             Example:
133              
134             use HTML::Object::DOM::NodeFilter qw( :all );
135             my $nodeIterator = $doc->createNodeIterator(
136             $doc->body,
137             SHOW_ELEMENT,
138             sub{ return( FILTER_ACCEPT ); },
139             # or
140             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
141             );
142             my $expand = $nodeIterator->expandEntityReferences;
143              
144             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/expandEntityReferences>
145              
146             =head2 filter
147              
148             Normally this is read-only, but under perl you can set it to a new L<HTML::Object::DOM::NodeFilter> object you want, even after object instantiation.
149              
150             Returns a L<HTML::Object::DOM::NodeFilter> used to select the relevant nodes.
151              
152             Example:
153              
154             use HTML::Object::DOM::NodeFilter qw( :all );
155             my $nodeIterator = $doc->createNodeIterator(
156             $doc->body,
157             SHOW_ELEMENT,
158             sub{ return( FILTER_ACCEPT ); },
159             # or
160             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
161             );
162             my $nodeFilter = $nodeIterator->filter;
163              
164             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/filter>
165              
166             =head2 pointerBeforeReferenceNode
167              
168             Normally this is read-only, but under perl you can set whatever boolean value you want. Defaults to true.
169              
170             Returns a boolean flag that indicates whether the C<NodeIterator> is anchored before, the flag being true, or after, the flag being false, the anchor node.
171              
172             Example:
173              
174             use HTML::Object::DOM::NodeFilter qw( :all );
175             my $nodeIterator = $doc->createNodeIterator(
176             $doc->body,
177             SHOW_ELEMENT,
178             sub{ return( FILTER_ACCEPT ); },
179             # or
180             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
181             );
182             my $flag = $nodeIterator->pointerBeforeReferenceNode;
183              
184             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/pointerBeforeReferenceNode>
185              
186             =head2 pos
187              
188             Read-only.
189              
190             This is a non-standard property, which returns the 0-based position in the array of the anchor element's children.
191              
192             You can poll this to know where the iterator is at.
193              
194             Example:
195              
196             use HTML::Object::DOM::NodeFilter qw( :all );
197             # You need to first declare $nodeIterator to be able to use it in the callback
198             my $nodeIterator;
199             $nodeIterator = $doc->createNodeIterator(
200             $doc->body,
201             SHOW_ELEMENT,
202             sub
203             {
204             say "Current position is: ", $nodeIterator->pos );
205             return( $_->getName eq 'div' ? FILTER_ACCEPT : FILTER_SKIP );
206             },
207             );
208              
209             =head2 referenceNode
210              
211             Read-only.
212              
213             Returns the L<Node|HTML::Object::DOM::Node> to which the iterator is anchored.
214              
215             Example:
216              
217             use HTML::Object::DOM::NodeFilter qw( :all );
218             my $nodeIterator = $doc->createNodeIterator(
219             $doc->body,
220             SHOW_ELEMENT,
221             sub{ return( FILTER_ACCEPT ); },
222             # or
223             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
224             );
225             my $node = $nodeIterator->referenceNode;
226              
227             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/referenceNode>
228              
229             =head2 root
230              
231             Normally this is read-only, but under perl you can set whatever L<node value|HTML::Object::DOM::Node> you want.
232              
233             Returns a L<Node|HTML::Object::DOM::Node> representing the root node as specified when the C<NodeIterator> was created.
234              
235             Example:
236              
237             use HTML::Object::DOM::NodeFilter qw( :all );
238             my $nodeIterator = $doc->createNodeIterator(
239             $doc->body,
240             SHOW_ELEMENT,
241             sub{ return( FILTER_ACCEPT ); },
242             # or
243             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
244             );
245             my $root = $nodeIterator->root; # $doc->body in this case
246              
247             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/root>
248              
249             =head2 whatToShow
250              
251             Normally this is read-only, but under perl you can set whatever number value you want.
252              
253             Returns an unsigned long being a bitmask made of L<constants|/CONSTANTS> describing the types of L<Node|HTML::Object::DOM::Node> that must to be presented. Non-matching nodes are skipped, but their children may be included, if relevant.
254              
255             Possible constant values (exported by L<HTML::Object::DOM::NodeFilter>) are:
256              
257             =over 4
258              
259             =item SHOW_ALL (4294967295)
260              
261             Shows all nodes.
262              
263             =item SHOW_ELEMENT (1)
264              
265             Shows Element nodes.
266              
267             =item SHOW_ATTRIBUTE (2)
268              
269             Shows attribute L<Attribute nodes|HTML::Object::DOM::Attribute>. This is meaningful only when creating a C<NodeIterator> with an L<Attribute node|HTML::Object::DOM::Attribute> as its root; in this case, it means that the L<attribute node|HTML::Object::DOM::Attribute> will appear in the first position of the iteration or traversal. Since attributes are never children of other L<nodes|HTML::Object::DOM::Node>, they do not appear when traversing over the document tree.
270              
271             =item SHOW_TEXT (4)
272              
273             Shows Text nodes.
274              
275             Example:
276              
277             use HTML::Object::DOM::NodeFilter qw( :all );
278             my $nodeIterator = $doc->createNodeIterator(
279             $doc->body,
280             ( SHOW_ELEMENT | SHOW_COMMENT | SHOW_TEXT ),
281             sub{ return( FILTER_ACCEPT ); },
282             # or
283             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
284             );
285             if( ( $nodeIterator->whatToShow & SHOW_ALL ) ||
286             ( $nodeIterator->whatToShow & SHOW_COMMENT ) )
287             {
288             # $nodeIterator will show comments
289             }
290              
291             =item SHOW_CDATA_SECTION (8)
292              
293             Will always returns nothing, because there is no support for xml documents.
294              
295             =item SHOW_ENTITY_REFERENCE (16)
296              
297             Legacy, no more used.
298              
299             =item SHOW_ENTITY (32)
300              
301             Legacy, no more used.
302              
303             =item SHOW_PROCESSING_INSTRUCTION (64)
304              
305             Shows ProcessingInstruction nodes.
306              
307             =item SHOW_COMMENT (128)
308              
309             Shows Comment nodes.
310              
311             =item SHOW_DOCUMENT (256)
312              
313             Shows Document nodes
314              
315             =item SHOW_DOCUMENT_TYPE (512)
316              
317             Shows C<DocumentType> nodes
318              
319             =item SHOW_DOCUMENT_FRAGMENT (1024)
320              
321             Shows L<HTML::Object::DOM::DocumentFragment> nodes.
322              
323             =item SHOW_NOTATION (2048)
324              
325             Legacy, no more used.
326              
327             =item SHOW_SPACE (4096)
328              
329             Show Space nodes. This is a non-standard extension under this perl framework.
330              
331             =back
332              
333             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/whatToShow>
334              
335             =head1 CONSTRUCTOR
336              
337             =head2 new
338              
339             Provided with a L<root node|HTML::Object::DOM::Node>, an optional bitwise value representing what to show and an optional filter callback and this will return a new node iterator.
340              
341             =head1 METHODS
342              
343             =head2 detach
344              
345             This operation is a no-op. It does not do anything. Previously it was telling the web browser engine that the C<NodeIterator> was no more used, but this is now useless.
346              
347             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/detach>
348              
349             =head2 nextNode
350              
351             Returns the next L<Node|HTML::Object::DOM::Node> in the document, or C<undef> if there are none.
352              
353             Example:
354              
355             use HTML::Object::DOM::NodeFilter qw( :all );
356             my $nodeIterator = $doc->createNodeIterator(
357             $doc->body,
358             SHOW_ELEMENT,
359             sub{ return( FILTER_ACCEPT ); },
360             # or
361             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
362             0 # false; this optional argument is not used any more
363             );
364             my $currentNode = $nodeIterator->nextNode(); # returns the next node
365              
366             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/nextNode>
367              
368             =head2 previousNode
369              
370             Returns the previous L<Node|HTML::Object::DOM::Node> in the document, or C<undef> if there are none.
371              
372             Example:
373              
374             use HTML::Object::DOM::NodeFilter qw( :all );
375             my $nodeIterator = $doc->createNodeIterator(
376             $doc->body,
377             SHOW_ELEMENT,
378             sub{ return( FILTER_ACCEPT ); },
379             # or
380             # { acceptNode => sub{ return( FILTER_ACCEPT ); } },
381             0 # false; this optional argument is not used any more
382             );
383             my $currentNode = $nodeIterator->nextNode(); # returns the next node
384             my $previousNode = $nodeIterator->previousNode(); # same result, since we backtracked to the previous node
385              
386             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator/previousNode>
387              
388             =head1 AUTHOR
389              
390             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
391              
392             =head1 SEE ALSO
393              
394             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator>, L<StackOverflow topic on NodeIterator|https://stackoverflow.com/questions/7941288/when-to-use-nodeiterator>, L<W3C specifications|https://dom.spec.whatwg.org/#interface-nodeiterator>
395              
396             =head1 COPYRIGHT & LICENSE
397              
398             Copyright(c) 2021 DEGUEST Pte. Ltd.
399              
400             All rights reserved
401              
402             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
403              
404             =cut