File Coverage

blib/lib/XML/Tiny/DOM/Element.pm
Criterion Covered Total %
statement 67 71 94.3
branch 21 22 95.4
condition 11 14 78.5
subroutine 17 19 89.4
pod n/a
total 116 126 92.0


line stmt bran cond sub pod time code
1             package XML::Tiny::DOM::Element;
2              
3 2     2   10 use strict;
  2         3  
  2         63  
4 2     2   9 use warnings;
  2         4  
  2         56  
5              
6 2     2   8 use vars qw($VERSION $AUTOLOAD);
  2         4  
  2         578  
7             use overload
8 8     8   30 '""' => sub { return shift()->_gettext(); },
9 6     6   9 'eq' => sub { my $s = shift(); return $s->_compare('eq', @_) },
  6         37  
10 1     1   2 'ne' => sub { my $s = shift(); return $s->_compare('ne', @_) },
  1         3  
11 4     4   7 'lt' => sub { my $s = shift(); return $s->_compare('lt', @_) },
  4         10  
12 0     0   0 'le' => sub { my $s = shift(); return $s->_compare('le', @_) },
  0         0  
13 4     4   6 'gt' => sub { my $s = shift(); return $s->_compare('gt', @_) },
  4         12  
14 0     0   0 'ge' => sub { my $s = shift(); return $s->_compare('ge', @_) },
  0         0  
15 10     10   26 'cmp' => sub { my $s = shift(); return $s->_compare('cmp', @_) },
  10         24  
16 277     277   653 'bool' => sub { 1 },
17 2     2   3692 ;
  2         2201  
  2         72  
18              
19             $VERSION = '1.1';
20              
21             =head1 NAME
22              
23             XML::Tiny::DOM::Element - an object representing an XML element
24              
25             =head1 DESCRIPTION
26              
27             This represents a single Eelement /E in an XML document that
28             was parsed using XML::Tiny::DOM.
29              
30             =head1 SYNOPSIS
31              
32             use XML::Tiny::DOM;
33             my $document = XML::Tiny::DOM->new(...);
34             # $document is now an XML::Tiny::DOM::Element
35              
36             now, given a document like this:
37              
38            
39            
40            
41            
42             -a
43             -q
44            
45            
46            
47            
48            
49            
50            
51            
52            
53            
54              
55             you can do this:
56              
57             my $rsync = $document->externalprograms->rsync();
58             my $rsyncbinary = $rsync->binary();
59             my $allrsyncargs = [ $rsync->args->arg('*') ];
60             my $secondarg = $rsync->args->arg(1);
61             my $gamma = $document->intervals->interval('gamma');
62              
63             =head1 METHODS
64              
65             =head2 created by AUTOLOAD
66              
67             Most methods are created using AUTOLOAD. There's also a few utility and
68             private methods whose names start with an underscore. Consequently
69             your documents shouldn't contain any elements or attributes whose names
70             start with an underscore, or that are called DESTROY or AUTOLOAD, because
71             those are special to perl.
72              
73             When you call the ...->foo() method on an object, it first looks for
74             an XML attribute with that name. If there is one, its value is returned.
75              
76             If there's no such attribute, then it looks for a child element with that
77             name. If no parameter is given, it returns the first such element. If a
78             numeric parameter is given, it returns the Nth element (counting from 0).
79             If the parameter is '*' then all such elements are returned. Otherwise,
80             child elements of the appropriate type are searched and a list of those whose
81             ...->name() method returns something that matches the parameter is returned.
82              
83             =head2 _parent
84              
85             Returns the parent element of this element. It is an error to call this
86             on the root element.
87              
88             =head2 _root
89              
90             Return the root element.
91              
92             =cut
93              
94             sub AUTOLOAD {
95 98     98   3195 (my $nodename = $AUTOLOAD) =~ s/.*:://;
96 98         135 my $self = shift();
97 98   100     319 my $wanted = shift() || 0;
98              
99 98 50       190 return if($nodename eq 'DESTROY');
100              
101             # attribs take precedence ...
102 98 100       370 return $self->{attrib}->{$nodename}
103             if(exists($self->{attrib}->{$nodename}));
104              
105 83         112 my @childnodes = ();
106 83         187 foreach my $childnode (@{$self->{content}}) {
  83         200  
107 340 100 66     1614 if($childnode->{type} eq 'e' && $childnode->{name} eq $nodename) {
108 131         318 push @childnodes, __PACKAGE__->_new($childnode, _parent => $self);
109             }
110             }
111 83 100       578 if($wanted eq '*') {
    100          
112 2         10 return @childnodes;
113             } elsif($wanted =~ /^\d+$/) {
114 80 100       1332 return $childnodes[$wanted] if(exists($childnodes[$wanted]));
115 1         8 die("Can't get '$nodename' number $wanted from object ".ref($self)."\n")
116             ;
117             } else {
118 1         2 return (grep { $_->name() eq $wanted } @childnodes);
  4         21  
119             }
120             }
121              
122             sub _new {
123 133     133   6729 my $class = shift;
124 133         128 my $document = shift;
125 133         225 my %params = @_;
126 133 100       303 if($params{_parent}) { $document->{_parent} = $params{_parent}; }
  131         209  
127 133         556 bless $document, $class;
128             }
129              
130             sub _parent {
131 9     9   13 my $self = shift;
132 9 100       16 return $self->{_parent} if($self->{_parent});
133 2         13 die("Can't get root element's parent\n");
134             }
135              
136             sub _root {
137 1     1   3 my $self = shift;
138 1         2 $@ = 0;
139 1         4 while(!$@) { eval { $self = $self->_parent() }; }
  3         4  
  3         7  
140 1         8 return $self;
141             }
142              
143             sub _gettext {
144 33     33   42 my $self = shift;
145 33         55 my $c = $self->{content};
146 33 100 66     265 if(
    100 100        
      66        
147             ref($c) eq 'ARRAY' &&
148             defined($c->[0]->{type}) &&
149             $c->[0]->{type} eq 't' # it's a text node
150 3         17 ) {
151 30         140 (my $value = $c->[0]->{content}) =~ s/^\s+|\s+$//g;
152 30         130 return $value;
153             } elsif(
154             ref($c) eq 'ARRAY' &&
155             (keys %{$c->[0]}) == 0 # empty node
156             ) { # empty element stringifies to ''
157 1         3 return '';
158             } else {
159 2         18 die("Can't stringify '".$self->{name}."' in ".ref($self)."\n");
160             }
161             }
162              
163             sub _compare {
164 25     25   45 my($self, $op, $comparand, $reversed) = @_;
165 25         50 my $value = $self->_gettext();
166 25 100       57 ($value, $comparand) = ($comparand, $value) if($reversed);
167 25         1269 return eval "\$value $op \$comparand";
168             }
169              
170             =head1 BUGS and FEEDBACK
171              
172             I welcome feedback about my code, including constructive criticism.
173             Bug reports should be made using L or by email,
174             and should include the smallest possible chunk of code, along with
175             any necessary XML data, which demonstrates the bug. Ideally, this
176             will be in the form of a file which I can drop in to the module's
177             test suite.
178              
179             =head1 SEE ALSO
180              
181             L
182              
183             L
184              
185             =head1 AUTHOR, COPYRIGHT and LICENCE
186              
187             David Cantrell EFE
188              
189             Copyright 2009 David Cantrell Edavid@cantrell.org.ukE
190              
191             This software is free-as-in-speech software, and may be used,
192             distributed, and modified under the terms of either the GNU
193             General Public Licence version 2 or the Artistic Licence. It's
194             up to you which one you use. The full text of the licences can
195             be found in the files GPL2.txt and ARTISTIC.txt, respectively.
196              
197             =head1 CONSPIRACY
198              
199             This module is also free-as-in-mason software.
200              
201             =cut
202              
203             'zero';