File Coverage

blib/lib/XML/Tiny/Tree.pm
Criterion Covered Total %
statement 49 49 100.0
branch 6 8 75.0
condition 4 12 33.3
subroutine 8 8 100.0
pod 1 1 100.0
total 68 78 87.1


line stmt bran cond sub pod time code
1             package XML::Tiny::Tree;
2              
3 1     1   16314 use strict;
  1         2  
  1         44  
4 1     1   4 use warnings;
  1         2  
  1         23  
5              
6 1     1   636 use Moo;
  1         12285  
  1         4  
7              
8 1     1   1782 use Tree;
  1         6649  
  1         32  
9              
10 1     1   629 use Types::Standard qw/Int Str/;
  1         57494  
  1         15  
11              
12 1     1   1519 use XML::Tiny;
  1         1316  
  1         461  
13              
14             has fatal_declarations =>
15             (
16             default => sub{return 0},
17             is => 'rw',
18             isa => Int,
19             required => 0,
20             );
21              
22              
23             has input_file =>
24             (
25             default => sub{return ''},
26             is => 'rw',
27             isa => Str,
28             required => 0,
29             );
30              
31             has no_entity_parsing =>
32             (
33             default => sub{return 0},
34             is => 'rw',
35             isa => Int,
36             required => 0,
37             );
38              
39             has strict_entity_parsing =>
40             (
41             default => sub{return 0},
42             is => 'rw',
43             isa => Int,
44             required => 0,
45             );
46              
47             our $VERSION = '1.00';
48              
49             # ------------------------------------------------
50              
51             sub convert
52             {
53 1     1 1 17 my($self, %arg) = @_;
54 1   33     7 my($fatal_declarations) = $arg{fatal_declarations} || $self -> fatal_declarations;
55 1   33     507 my($input_file) = $arg{input_file} || $self -> input_file;
56 1   33     561 my($no_entity_parsing) = $arg{no_entity_parsing} || $self -> no_entity_parsing;
57 1   33     478 my($strict_entity_parsing) = $arg{strict_entity_parsing} || $self -> strict_entity_parsing;
58              
59 1 50       605 die "Input file not specified\n" if (! defined $input_file);
60              
61 1         70 open(my $fh, '<', $input_file);
62              
63 1         10 my $xml = XML::Tiny::parsefile
64             (
65             $fh,
66             fatal_declarations => $fatal_declarations,
67             no_entity_parsing => $no_entity_parsing,
68             strict_entity_parsing => $strict_entity_parsing,
69             );
70              
71 1         1042 close $fh;
72              
73 1         7 return $self -> _reformat($xml, undef, []);
74              
75             } # End of convert.
76              
77             # ------------------------------------------------
78              
79             sub _reformat
80             {
81 6     6   12 my($self, $ara_ref, $tree, $stack) = @_;
82              
83 6         5 my($name, $node);
84              
85 6         9 for my $hash_ref (@$ara_ref)
86             {
87 8         10 $name = $$hash_ref{name};
88              
89             # This assumes that a named node is created before its content,
90             # so that by the time we get here, $node -> meta() has been called.
91              
92 8 100       13 if (! defined $name)
93             {
94 3         4 my($content) = $$hash_ref{content};
95              
96 3 50       6 if (defined $content)
97             {
98 3         9 my($meta) = $$stack[$#$stack] -> meta;
99 3         18 $meta = {%$meta, content => $content};
100              
101 3         5 $$stack[$#$stack] -> meta($meta);
102             }
103              
104 3         27 next;
105             }
106              
107 5         22 $node = Tree -> new($name);
108              
109             # Init $tree now that we need it.
110              
111 5 100       155 if (! defined $tree)
112             {
113 1         2 $tree = $node;
114              
115 1         3 push @$stack, $node;
116             }
117              
118 5         19 $node -> meta({attributes => $$hash_ref{attrib}, content => ''});
119 5         57 $$stack[$#$stack] -> add_child($node);
120              
121 5         582 push @$stack, $node;
122              
123 5         15 $self -> _reformat($$hash_ref{content}, $tree, $stack);
124              
125 5         6 pop @$stack;
126             }
127              
128 6         13 return $tree;
129              
130             } # End of _reformat.
131              
132             # -----------------------------------------------
133              
134             1;
135              
136             =pod
137              
138             =head1 NAME
139              
140             XML::Tiny::Tree - Convert XML::Tiny output into a Tree
141              
142             =head1 Synopsis
143              
144             This is scripts/synopsis.pl:
145              
146             #!/usr/bin/env perl
147              
148             use strict;
149             use warnings;
150              
151             use XML::Tiny::Tree;
152              
153             # ------------------------------------------------
154              
155             my($input_file) = shift || die "Usage $0 file. Try using data/test.xml as the input. \n";
156             my($tree) = XML::Tiny::Tree -> new
157             (
158             input_file => $input_file,
159             no_entity_parsing => 1,
160             ) -> convert;
161              
162             print "Input file: $input_file. \n";
163             print "The whole tree: \n";
164             print map("$_\n", @{$tree -> tree2string});
165             print '-' x 50, "\n";
166             print "Bits and pieces from the first child (tag_4) of the second child (tag_3) of the root (tag_1): \n";
167              
168             my(@children) = $tree -> children;
169             @children = $children[1] -> children;
170             my($tag) = $children[0] -> value;
171             my($meta) = $children[0] -> meta;
172             my($attr) = $$meta{attributes};
173              
174             print "tag: $tag. \n";
175             print "content: $$meta{content}. \n";
176             print 'attributes: ', join(', ', map{"$_ => $$attr{$_}"} sort keys %$attr), ". \n";
177              
178             =head1 Description
179              
180             L reads a file via L, and reformats the output into a tree managed
181             by L.
182              
183             =head1 Constructor and Initialization
184              
185             =head2 Calling new()
186              
187             C is called as C<< my($obj) = XML::Tiny::Tree -> new(k1 => v1, k2 => v2, ...) >>.
188              
189             It returns a new object of type C.
190              
191             Key-value pairs accepted in the parameter list (see corresponding methods for details
192             [e.g. L]):
193              
194             =over 4
195              
196             =item o fatal_declarations => $Boolean
197              
198             Specify whether or not to get L to error if such declarations are found.
199              
200             Default: 0.
201              
202             This key is optional.
203              
204             =item o input_file => $string
205              
206             Specify the name of the XML file to process.
207              
208             Default: ''.
209              
210             This key is mandatory.
211              
212             =item o no_entity_parsing => $Boolean
213              
214             Specify whether or not to get L to do entity parsing.
215              
216             Default: 0.
217              
218             This key is optional.
219              
220             =item o strict_entity_parsing => $Boolean
221              
222             If set to true, any unrecognised entities (ie, those outside the core five plus numeric entities)
223             cause a fatal error.
224              
225             Default: 0.
226              
227             This key is optional.
228              
229             =back
230              
231             =head1 Distributions
232              
233             This module is available as a Unix-style distro (*.tgz).
234              
235             See L
236             for help on unpacking and installing distros.
237              
238             =head1 Installing the module
239              
240             Install L as you would for any C module:
241              
242             Run:
243              
244             cpanm XML::Tiny::Tree
245              
246             or run:
247              
248             sudo cpan XML::Tiny::Tree
249              
250             or unpack the distro, and then either:
251              
252             perl Build.PL
253             ./Build
254             ./Build test
255             sudo ./Build install
256              
257             or:
258              
259             perl Makefile.PL
260             make (or dmake)
261             make test
262             make install
263              
264             =head1 Methods
265              
266             =head2 convert([%arg])
267              
268             Here, the [] indicate an optional parameter.
269              
270             Triggers reading the XML file and conversion of the output of L into a L.
271              
272             Returns an object of type L.
273              
274             C takes the same parameters as L.
275             See L for details.
276              
277             =head2 fatal_declarations([$Boolean])
278              
279             Here, the [] indicate an optional parameter.
280              
281             Gets or sets the value of the option to pass to L.
282              
283             C is a parameter to L.
284              
285             =head2 input_file([$string])
286              
287             Here, the [] indicate an optional parameter.
288              
289             Gets or sets the name of the input file to pass to L's method C.
290              
291             C is a parameter to L.
292              
293             =head2 new([%arg])
294              
295             See L for details.
296              
297             =head2 no_entity_parsing([$Boolean])
298              
299             Here, the [] indicate an optional parameter.
300              
301             Gets or sets the value of the option to pass to L.
302              
303             C is a parameter to L.
304              
305             =head2 strict_entity_parsing([$Boolean])
306              
307             Here, the [] indicate an optional parameter.
308              
309             Gets or sets the value of the option to pass to L.
310              
311             C is a parameter to L.
312              
313             =head1 FAQ
314              
315             =head2 How to I access the names of the XML tags?
316              
317             Each node in the tree is an object of type L, and has a method called C. This method
318             returns a string which is the name of the tag.
319              
320             See the L for sample code.
321              
322             =head2 How do I access the attributes of each XML tag?
323              
324             Each node in the tree is an object of type L, and has a method called C. This method
325             returns a hashref containing 2 keys:
326              
327             =over 4
328              
329             =item o attributes => $hashref
330              
331             =item o content => $string
332              
333             =back
334              
335             If the tag has no attributes, then $hashref is {}.
336              
337             If the tag has no content, then $string is ''.
338              
339             See the L for sample code.
340              
341             =head2 How do I access the content of each XML tag?
342              
343             See the answer to the previous question.
344              
345             See the L for sample code.
346              
347             =head2 Is it possible for a tag to have both content and sub-tags?
348              
349             Yes. See data/test.xml in the distro for such a case.
350              
351             =head1 See Also
352              
353             L.
354              
355             L.
356              
357             =head1 Machine-Readable Change Log
358              
359             The file Changes was converted into Changelog.ini by L.
360              
361             =head1 Version Numbers
362              
363             Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.
364              
365             =head1 Repository
366              
367             L.
368              
369             =head1 Support
370              
371             Email the author, or log a bug on RT:
372              
373             L.
374              
375             =head1 Author
376              
377             L was written by Ron Savage Iron@savage.net.auE> in 2015.
378              
379             Home page: L.
380              
381             =head1 Copyright
382              
383             Australian copyright (c) 2015, Ron Savage.
384              
385             All Programs of mine are 'OSI Certified Open Source Software';
386             you can redistribute them and/or modify them under the terms of
387             The Artistic License, a copy of which is available at:
388             http://www.opensource.org/licenses/index.html
389              
390             =cut
391