File Coverage

blib/lib/POE/Filter/XML/Node.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package POE::Filter::XML::Node;
2             {
3             $POE::Filter::XML::Node::VERSION = '1.140700';
4             }
5              
6             #ABSTRACT: A XML::LibXML::Element subclass that adds streaming semantics
7              
8 2     2   27367 use Moose;
  0            
  0            
9             use MooseX::NonMoose;
10             use MooseX::InsideOut;
11              
12              
13             extends 'XML::LibXML::Element';
14              
15             use XML::LibXML(':libxml');
16              
17              
18             has stream_start => (is => 'ro', writer => '_set_stream_start', isa => 'Bool', default => 0);
19             has stream_end => (is => 'ro', writer => '_set_stream_end', isa => 'Bool', default => 0);
20              
21              
22             sub BUILDARGS {
23             my ($self, $name) = @_;
24             #only a name should be passed
25             return { name => $name };
26             }
27              
28              
29             sub cloneNode {
30            
31             my ($self, $deep) = @_;
32             my $clone = $self->SUPER::cloneNode($deep);
33            
34             bless($clone, $self->meta->name());
35            
36             $clone->_set_stream_start($self->stream_start());
37             $clone->_set_stream_end($self->stream_end());
38            
39             return $clone;
40             }
41              
42             sub getChildrenByTagName {
43             my ($self, $name) = @_;
44             my $CLASS = $self->meta->name();
45             return (map { bless($_, $CLASS) } @{ $self->SUPER::getChildrenByTagName($name) });
46             }
47              
48             sub getChildrenByTagNameNS {
49             my ($self, $nsURI, $localname) = @_;
50             my $CLASS = $self->meta->name();
51             return (map { bless($_, $CLASS) } @{ $self->SUPER::getChildrenByTagNameNS($nsURI, $localname) });
52             }
53              
54             sub getChildrenByLocalName {
55             my ($self, $localname) = @_;
56             my $CLASS = $self->meta->name();
57             return (map { bless($_, $CLASS) } @{ $self->SUPER::getChildrenByLocalName($localname) });
58             }
59              
60             sub getElementsByTagName {
61             my ($self, $name) = @_;
62             my $CLASS = $self->meta->name();
63             return (map { bless($_, $CLASS) } @{ $self->SUPER::getElementsByTagName($name) });
64             }
65              
66             sub getElementsByTagNameNS {
67             my ($self, $nsURI, $localname) = @_;
68             my $CLASS = $self->meta->name();
69             return (map { bless($_, $CLASS) } @{ $self->SUPER::getElementsByTagNameNS($nsURI, $localname) });
70             }
71              
72             sub getElementsByLocalName {
73             my ($self, $localname) = @_;
74             my $CLASS = $self->meta->name();
75             return (map { bless($_, $CLASS) } @{ $self->SUPER::getElementsByLocalName($localname) });
76             }
77            
78              
79             sub toString {
80             my ($self, $formatted, $docencoding) = @_;
81            
82             $formatted = defined($formatted) ? $formatted : 0;
83             $docencoding = defined($docencoding) ? $docencoding : 0;
84            
85             if($self->stream_start())
86             {
87             my $string = '<';
88             $string .= $self->nodeName();
89             foreach my $attr ($self->attributes())
90             {
91             $string .= sprintf(' %s="%s"', $attr->nodeName(), $attr->value());
92             }
93             $string .= '>';
94             return $string;
95             }
96             elsif ($self->stream_end())
97             {
98             return sprintf('</%s>', $self->nodeName());
99             }
100             else
101             {
102             return $self->SUPER::toString($formatted, $docencoding);
103             }
104             }
105              
106              
107             sub setAttributes {
108             my ($self, $array) = @_;
109             for(my $i = 0; $i < scalar(@$array); $i++)
110             {
111             if($array->[$i] eq 'xmlns')
112             {
113             $self->setNamespace($array->[++$i], '', 0);
114             }
115             else
116             {
117             $self->setAttribute($array->[$i], $array->[++$i]);
118             }
119             }
120             }
121              
122              
123             sub getAttributes {
124             my ($self) = @_;
125             my $attributes = {};
126              
127             foreach my $attrib ($self->attributes())
128             {
129             if($attrib->nodeType == XML_ATTRIBUTE_NODE)
130             {
131             $attributes->{$attrib->nodeName()} = $attrib->value();
132             }
133             }
134              
135             return $attributes;
136             }
137              
138              
139             sub getSingleChildByTagName {
140             my ($self, $name) = @_;
141             my $node = ($self->getChildrenByTagName($name))[0];
142             return undef if not defined($node);
143             return $node;
144             }
145              
146              
147             sub getChildrenHash {
148             my ($self) = @_;
149             my $children = {};
150              
151             foreach my $child ($self->getChildrenByTagName("*"))
152             {
153             my $name = $child->nodeName();
154            
155             if(!exists($children->{$name}))
156             {
157             $children->{$name} = [];
158             }
159            
160             push(@{$children->{$name}}, $child);
161             }
162              
163             return $children;
164             }
165              
166             1;
167              
168              
169              
170             =pod
171              
172             =head1 NAME
173              
174             POE::Filter::XML::Node - A XML::LibXML::Element subclass that adds streaming semantics
175              
176             =head1 VERSION
177              
178             version 1.140700
179              
180             =head1 SYNOPSIS
181              
182             use POE::Filter::XML::Node;
183              
184             my $node = POE::Filter::XML::Node->new('iq');
185              
186             $node->setAttributes(
187             ['to', 'foo@other',
188             'from', 'bar@other',
189             'type', 'get']
190             );
191              
192             my $query = $node->addNewChild('jabber:iq:foo', 'query');
193              
194             $query->appendTextChild('foo_tag', 'bar');
195              
196             say $node->toString();
197              
198             --
199              
200             (newlines and tabs for example only)
201              
202             <iq to='foo@other' from='bar@other' type='get'>
203             <query xmlns='jabber:iq:foo'>
204             <foo_tag>bar</foo_tag>
205             </query>
206             </iq>
207              
208             =head1 DESCRIPTION
209              
210             POE::Filter::XML::Node is a XML::LibXML::Element subclass that aims to provide
211             a few extra convenience methods and light integration into a streaming context.
212              
213             This module can be used to create arbitrarily complex XML data structures that
214             know how to stringify themselves.
215              
216             =head1 PUBLIC_ATTRIBUTES
217              
218             =head2 stream_[start|end]
219              
220             is: ro, isa: Bool, default: false
221              
222             These two attributes define behaviors to toString() for the node. In the case
223             of stream_start, this means dropping all children and merely leaving the tag
224             unterminated (eg. <start>). For stream_end, it will drop any children and treat
225             the tag like a terminator (eg. </end>).
226              
227             Each attribute has a private writer ('_set_stream_[start|end]') if it necessary
228             to manipulate these attributes post construction.
229              
230             =head1 PUBLIC_METHODS
231              
232             =head2 override cloneNode
233              
234             (Bool $deep)
235              
236             cloneNode is overriden to carry forward the stream_[end|start] attributes
237              
238             =head2 override toString
239              
240             (Bool $formatted)
241              
242             toString was overridden to provide special stringification semantics for when
243             stream_start or stream_end are boolean true.
244              
245             =head2 setAttributes
246              
247             (ArrayRef $array_of_tuples)
248              
249             setAttributes() accepts a single arguement: an array reference. Basically you
250             pair up all the attributes you want to be into the node (ie. [attrib, value])
251             and this method will process them using setAttribute(). This is just a
252             convenience method.
253              
254             If one of the attributes is 'xmlns', setNamespace() will be called with the
255             value used as the $nsURI argument, with no prefix, and not activated.
256              
257             eg.
258             ['xmlns', 'http://foo']
259             |
260             V
261             setNamespace($value, '', 0)
262             |
263             V
264             <node xmlns="http://foo"/>
265              
266             =head2 getAttributes
267              
268             returns (HashRef)
269              
270             This method returns all of the attribute nodes on the Element (filtering out
271             namespace declarations) as a HashRef.
272              
273             =head2 getFirstChildByTagName(Str $name)
274              
275             returns (Maybe[POE::Filter::XML::Node])
276              
277             This is a convenience method that basically does:
278             (getChildrenByTagName($name))[0]
279              
280             =head2 getChildrenHash
281              
282             returns (HashRef)
283              
284             getChildrenHash() returns a hash reference to all the children of that node.
285             Each key in the hash will be node name, and each value will be an array
286             reference with all of the children with that name.
287              
288             =head1 AUTHOR
289              
290             Nicholas R. Perez <nperez@cpan.org>
291              
292             =head1 COPYRIGHT AND LICENSE
293              
294             This software is copyright (c) 2014 by Nicholas R. Perez <nperez@cpan.org>.
295              
296             This is free software; you can redistribute it and/or modify it under
297             the same terms as the Perl 5 programming language system itself.
298              
299             =cut
300              
301              
302             __END__
303