File Coverage

blib/lib/XML/Handler/EasyTree/Generator.pm
Criterion Covered Total %
statement 53 56 94.6
branch 16 18 88.8
condition 6 6 100.0
subroutine 7 8 87.5
pod 1 2 50.0
total 83 90 92.2


line stmt bran cond sub pod time code
1             =pod
2              
3             =head1 NAME
4              
5             XML::Handler::EasyTree::Generator - Perl extension for generating EasyTree structures
6              
7             =cut
8              
9             package XML::Handler::EasyTree::Generator;
10              
11 1     1   21051 use 5.008003; # auto-generated by h2xs, but how low can it go?
  1         4  
  1         33  
12 1     1   4 use strict;
  1         2  
  1         29  
13 1     1   3 use warnings;
  1         5  
  1         34  
14 1     1   921 use diagnostics;
  1         185409  
  1         11  
15 1     1   411 use vars qw($default_obj $error $AUTOLOAD);
  1         2  
  1         639  
16             # only make default object once to reduce latency
17             $default_obj = XML::Handler::EasyTree::Generator->new();
18             our $VERSION = '0.03';
19             our $revision = '$Id: XML::Handler::EasyTree::Generator.pm,v 1.0 2006/01/16 02:40:00 wren Exp $';
20              
21             =head1 SYNOPSIS
22              
23             use XML::Handler::EasyTree::Generator;
24            
25             $e = XML::Handler::EasyTree::Generator->new('t' => '_t',
26             'pi' => '_pi', 'c' => '_c');
27            
28             $hashref = $e->AUTOLOAD(\%args, @content);
29             $hashref = $e->AUTOLOAD(@content);
30             $hashref = $e->_t(@content); # make a text node
31             $hashref = $e->_c(@content); # make a comment node
32             $hashref = $e->_pi({'target' => $target}, @content); # make a pi node
33             $hashref = $e->_pi($target, @content); # make a pi node
34            
35             $hashref = &XML::Handler::EasyTree::Generator::AUTOLOAD(\%args, @content);
36              
37              
38             =head1 DESCRIPTION
39              
40             This module provides a way to create EasyTree structures on the
41             fly. For more about EasyTree structures see
42             L or L. The
43             interface resembles the autoloader in L. I've chosen to
44             get rid of the leading hyphen for arguments/attributes; if you'd
45             like to see them added in, I suppose I can add a regex to remove
46             them :-)
47              
48             If any errors are encountered the functions will return false
49             and the error will be stored in
50             B<$XML::Handler::EasyTree::Generator::error>.
51              
52             =head2 CAVEAT
53              
54             I've noticed that L (or L or
55             libexpat1) does a few "interesting" things with parsing input. I
56             haven't checked yet to see if L or its
57             dependencies do the same. This module does allow for generating
58             some output that is non-cannonical by those standards, but
59             largely this shouldn't be a problem. Where non-cannonical
60             abilities are granted they'll be noted.
61              
62             One example is unary vs empty tags. The parser reads them in as
63             the same, but you can generate them differently for output. In
64             the potentially forthcoming
65             L (I haven't
66             checked other modules yet) an element node with no content is
67             considered unary whereas one with a null content ('') text node
68             is considered binary but empty.
69              
70             A more dangerous example is generating comment nodes. Comments
71             are usually ignored by the parser. As such, functions that
72             flatten EasyTree structures may croak on comment nodes.
73              
74             =head2 EXPORT
75              
76             None by default. None possible for now.
77              
78             =cut
79              
80             #require Exporter;
81             #
82             #our @ISA = qw(Exporter);
83             #
84             # Items to export into callers namespace by default. Note: do
85             # not export names by default without a very good reason. Use
86             # EXPORT_OK instead. Do not simply export all your public
87             # functions/methods/constants.
88             #
89             # This allows declaration use XML::Handler::EasyTree::Generator ':all';
90             # If you do not need this, moving things directly into @EXPORT
91             # or @EXPORT_OK will save memory.
92             #our %EXPORT_TAGS = ( 'all' => [ qw() ] );
93             #
94             #our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
95             #
96             #our @EXPORT = qw();
97              
98             =head1 FUNCTIONS
99              
100             =over 4
101              
102             =item XML::Handler::EasyTree::Generator->new(['t' => $name][, 'pi' => $name][, 'c' => $name])
103              
104             This method creates a new object which lets you use the
105             autoloader below in object-oriented fashion. By default the
106             autoloader will create element nodes.
107              
108             Since tag names are
109             extensible, we need special names for other node types. Rather
110             than enforcing a specific special name, you can specify what
111             names you would like to be set aside for text,
112             parser-instruction, and comment nodes. By default these are
113             '_t', '_pi', and '_c' respectively. With the function oriented
114             autoloader there's no way to change these defaults.
115              
116             N.B. comment nodes are non-cannonical and may cause functions
117             that turn EasyTree structures into XML text to croak.
118              
119             =cut
120              
121             #######
122             # NEW #
123             #######
124             sub new {
125 4     4 1 3301 my $class = shift;
126 4         14 my %args = @_;
127 4   100     28 $args{'t'} ||= '_t';
128 4   100     20 $args{'pi'} ||= '_pi';
129 4   100     19 $args{'c'} ||= '_c';
130 4         7 my $this = \%args;
131 4         22 bless $this, $class;
132 4         14 return $this;
133             }
134              
135             =item $easytreetools_obj->AUTOLOAD([\%args,] @content)
136              
137             =item &XML::Handler::EasyTree::Generator::AUTOLOAD([\%args,] @content)
138              
139             This function set allows you to create an EasyTree node in a
140             manner similar to that used in L for creating HTML
141             nodes. It can be used either as a function or as a method.
142              
143             The initial hashref of attribute/value pairs is optional. If it
144             is present for text or comment nodes it is discarded. If it is
145             present for PI nodes, the 'target' value is taken if present,
146             all other values are discarded. If the target cannot be taken
147             from the %args hash, the first element of @content is assumed to
148             be the target.
149              
150             For element nodes the @content array can contain either scalars
151             which are interperated as text nodes, or can contain hashrefs
152             which are assumed to be EasyTree nodes. For non-element nodes
153             the @content array is join('')ed, sans the target for PI nodes
154             as appropriate.
155              
156             If you want to use a namespace for an element, surround it with
157             underscores as so: C<_namespace__tagname()> and the function
158             will deal with the rest. Single underscores are allowed in
159             namespaces or tagnames; double underscores are not allowed in
160             namespaces. It's convoluted, but it doesn't severely limit your
161             choices of tag names and allows namespaces so we can deal with
162             it.
163              
164             =cut
165              
166             ############
167             # AUTOLOAD #
168             ############
169             sub AUTOLOAD {
170             # declare and define variables
171 34     34   171 my $program = $AUTOLOAD;
172 34         190 $program =~ s/(.*):://; # remove package
173 34         52 my $this;
174 34 100       125 if (ref $_[0] eq $1) {
175 17         34 $this = shift;
176             } else {
177 17         26 $this = $default_obj;
178             }
179 34         48 $program =~ s/^_(.*?)__/$1:/; # resolve XML namespaces
180 34         56 my $args = {};
181 34 100       113 if (ref $_[0] eq 'HASH') {
182 16         26 $args = shift;
183             }
184 34         87 my @content = @_;
185 34         51 my $return = {};
186            
187             # generate EasyTree text node
188 34 100       160 if ($program eq $this->{'t'}) {
    100          
    100          
189 6         27 $return = {'type' => 't', 'content' => join('',@content)};
190            
191             # generate EasyTree comment node
192             } elsif ($program eq $this->{'c'}) {
193 6         26 $return = {'type' => 'c', 'content' => join('',@content)};
194            
195             # generate EasyTree PI node
196             } elsif ($program eq $this->{'pi'}) {
197 12         18 my $target;
198 12 100       26 if (exists $$args{'target'}) {
199 6         10 $target = $$args{'target'};
200             } else {
201 6         12 $target = shift @content;
202             }
203 12 50       31 return &error("Must specify a target for PI nodes")
204             unless $target;
205 12         68 $return = { 'type' => 'p',
206             'target' => $target,
207             'content' => join('',@content)
208             };
209            
210             # generate EasyTree element node
211             } else {
212 10         54 $return = { 'type' => 'e',
213             'name' => $program,
214             'attrib' => \%$args,
215             'content' => []
216             };
217            
218 10         27 foreach (@content) {
219 10         17 my $content;
220 10 100       39 if (ref \$_ eq 'SCALAR') {
    50          
221 8         25 $content = {'type' => 't', 'content' => $_};
222             } elsif (ref $_ eq 'HASH') {
223             # this should be an EasyTree node,
224             # but there's no error checking
225 2         42 $content = $_;
226             } else {
227 0         0 return &error("Autoloading error with content element '$_'");
228             }
229 10         17 push @{$$return{'content'}}, $content;
  10         37  
230             }
231             } # end if (node type)
232 34         330 return $return;
233             }
234              
235             #########
236             # ERROR #
237             #########
238             sub error {
239             # Usage: `or return &error($error);`
240 0     0 0   $error = join('', @_);
241 0           return;
242             }
243              
244             =back
245              
246             =head1 BUGS AND ISSUES
247              
248             Actual resolved namespaces aren't yet supported. Namespaces lead
249             to a node with the name 'namespace:tagname' just as if you have
250             namespace resolving turned off.
251              
252             =head1 SEE ALSO
253              
254             L,
255             L,
256             L
257              
258             Not specific to this module, but post discussion to
259             L
260              
261             =head1 AUTHOR
262              
263             wren ng thornton, Ewren@cpan.orgE
264             L
265              
266             =head1 COPYRIGHT AND LICENSE
267              
268             Copyright (C) 2004~2006 by wren ng thornton.
269             ALL RIGHTS RESERVED.
270              
271             This library is free software; you can redistribute it and/or
272             modify it under the same terms as Perl itself, either Perl
273             version 5.8.3 or, at your option, any later version of Perl 5
274             you may have available.
275              
276             =head1 Version History
277              
278             =over 4
279              
280             =item B
281              
282             =over 4
283              
284             =item *
285              
286             Tried better to make v0.02 updates consistent in meta files. (v0.03)
287              
288             =item *
289              
290             Updated author's name and contact info. (v0.02)
291              
292             =item *
293              
294             Initial release. (v0.01)
295              
296             =back
297              
298             =back
299              
300             =cut
301              
302             1;
303             __END__