File Coverage

blib/lib/HTML/TreeBuilder/Select.pm
Criterion Covered Total %
statement 41 84 48.8
branch 5 38 13.1
condition 0 9 0.0
subroutine 12 17 70.5
pod 3 4 75.0
total 61 152 40.1


line stmt bran cond sub pod time code
1             package HTML::TreeBuilder::Select;
2              
3 2     2   52882 use warnings;
  2         5  
  2         76  
4 2     2   13 use strict;
  2         5  
  2         108  
5              
6             =head1 NAME
7              
8             HTML::TreeBuilder::Select - Traverse a HTML tree using CSS selectors
9              
10             =head1 VERSION
11              
12             Version 0.111
13              
14             =cut
15              
16             our $VERSION = '0.111';
17              
18 2     2   2153 use HTML::TreeBuilder::XPath;
  2         176058  
  2         28  
19 2     2   2217 use Class::Accessor;
  2         4750  
  2         14  
20 2     2   85 use base qw(HTML::TreeBuilder::XPath);
  2         5  
  2         883  
21              
22 0 0   0   0 sub __container { my $self = shift; return $self->{__container} unless @_; return $self->{__container} = shift }
  0         0  
  0         0  
23 0 0   0   0 sub __fake_container { my $self = shift; return $self->{__fake_container} unless @_; return $self->{__fake_container} = shift }
  0         0  
  0         0  
24              
25             =head1 SYNOPSIS
26              
27             my $tree = new HTML::TreeBuilder::Select
28              
29             my @entries = $tree->select("div.main div.entry");
30              
31             =over 4
32              
33             =item @elements = $tree->select(QUERY)
34              
35             Search the tree for elements matching the C, which should be a CSS selector.
36              
37             =item $tree->dump_HTML()
38              
39             Returns a string representation of the tree in (possibly invalid) HTML format. This method will preserve any text outside of the root-level elements and NOT automatically wrap the content in ... .
40              
41             =cut
42              
43             sub dump_HTML {
44 0     0 1 0 my $self = shift;
45 0 0       0 return unless my $container = $self->container;
46 0         0 my @content;
47 0 0       0 @content = $self->__fake_container ? $container->content_list : ($container);
48 0 0       0 return join '', map { if (ref $_) { $_ = $_->as_HTML } $_ } @content;
  0         0  
  0         0  
  0         0  
49             }
50              
51             =item my $element = $tree->container()
52              
53             A convenience method that will return either the containing element of the tree, or a simple div container containing the root-level elements. This is very similar to the C method, but C will also remember whether the tree had a containing root element or not.
54              
55             =cut
56              
57             sub container {
58 0     0 1 0 my $self = shift;
59 0         0 my $container = $self->__container;
60 0 0       0 return $container if $container;
61 0         0 my @content = $self->guts;
62 0 0 0     0 if (1 == @content && ref $content[0]) {
63 0         0 $container = $content[0];
64             }
65             else {
66 0         0 $self->__fake_container(1);
67 0         0 $container = scalar $self->guts;
68             }
69 0 0       0 return unless $container;
70 0         0 $self->__container($container);
71 0         0 return $container;
72             }
73              
74             =item $tree->delete()
75              
76             Same as L
77              
78             =cut
79              
80             sub delete {
81 0     0 1 0 my $self = shift;
82 0         0 $self->__fake_container(undef);
83 0         0 $self->__container(undef);
84 0         0 return $self->SUPER::delete;
85             }
86              
87             =back
88              
89             =cut
90              
91             package HTML::Element;
92              
93 2     2   13 use HTML::TreeBuilder::XPath;
  2         4  
  2         20  
94 2     2   2132 use HTML::Selector::XPath qw(selector_to_xpath);
  2         5700  
  2         171  
95 2     2   18 use Carp;
  2         3  
  2         154  
96              
97 2     2   14 use constant _KEEP => "keep";
  2         4  
  2         154  
98 2     2   24 use constant _REPLACE => "replace";
  2         5  
  2         110  
99 2     2   12 use constant _DELETE => "delete";
  2         5  
  2         946  
100              
101             sub select {
102 2     2 0 17185 my $self = shift;
103 2 50       15 my $query = shift or croak "Need a query (a CSS selector or XPath)";
104 2         5 my $operation = shift;
105              
106 2         5 my $path;
107 2 50       15 if ($query =~ s/^~//) {
    50          
108 0         0 $path = $query;
109             }
110             elsif (! ref $query) {
111 2         13 $path = selector_to_xpath($query);
112             }
113              
114 2         788 my @elements = $self->findnodes($path);
115              
116 2 50       38587 return wantarray ? @elements : $elements[0] unless $operation;
    50          
117              
118 0 0         if (ref $operation eq "CODE") {
    0          
119 0           for my $element (@elements) {
120 0           my @result = $operation->($element);
121 0           my $directive = shift @result;
122 0   0       $directive &&= lc $directive;
123 0 0 0       if (! $directive || $directive eq _KEEP) {
    0          
    0          
124             }
125             elsif ($directive eq _REPLACE) {
126 0           my $replacement = shift @result;
127 0 0         if (ref $replacement eq "ARRAY") {
128 0           $replacement = HTML::Element->new_from_lol($replacement);
129             }
130 0           $element->replace_with($replacement)->delete;
131             }
132             elsif ($directive eq _DELETE) {
133 0           $element->delete;
134             }
135             }
136             }
137             elsif ($operation =~ m/^#$/i) {
138 0           return scalar @elements;
139             }
140             else {
141 0           croak "Operation ($operation) not permitted";
142             }
143             }
144              
145             =head1 AUTHOR
146              
147             Robert Krimen, C<< >>
148              
149             =head1 BUGS
150              
151             Please report any bugs or feature requests to
152             C, or through the web interface at
153             L.
154             I will be notified, and then you'll automatically be notified of progress on
155             your bug as I make changes.
156              
157             =head1 SUPPORT
158              
159             You can find documentation for this module with the perldoc command.
160              
161             perldoc HTML::TreeBuilder::Select
162              
163             You can also look for information at:
164              
165             =over 4
166              
167             =item * AnnoCPAN: Annotated CPAN documentation
168              
169             L
170              
171             =item * CPAN Ratings
172              
173             L
174              
175             =item * RT: CPAN's request tracker
176              
177             L
178              
179             =item * Search CPAN
180              
181             L
182              
183             =back
184              
185             =head1 ACKNOWLEDGEMENTS
186              
187             =head1 COPYRIGHT & LICENSE
188              
189             Copyright 2007 Robert Krimen, all rights reserved.
190              
191             This program is free software; you can redistribute it and/or modify it
192             under the same terms as Perl itself.
193              
194             =cut
195              
196             1; # End of HTML::TreeBuilder::Select
197