File Coverage

blib/lib/XML/Generator/Essex.pm
Criterion Covered Total %
statement 52 70 74.2
branch 10 32 31.2
condition 5 24 20.8
subroutine 16 21 76.1
pod 12 12 100.0
total 95 159 59.7


line stmt bran cond sub pod time code
1             package XML::Generator::Essex;
2              
3             $VERSION = 0.000_1;
4              
5             =head1 NAME
6              
7             XML::Generator::Essex - Generate XML with Essex
8              
9             =head1 SYNOPSIS
10              
11             package My::Generator;
12              
13             use XML::Generator::Essex;
14             @ISA = qw( XML::Generator::Essex );
15              
16             use strict;
17              
18             sub main { # Called by XML::Generator::Essex->generate().
19             my $self = shift;
20             }
21              
22             ## And, to use:
23              
24             my $g = MY::Generator->new( Handler => $h );
25             $g->generate( ... );
26              
27             =head1 DESCRIPTION
28              
29             Provides Essex output primitives like C and constructors for
30             essex events.
31              
32             =for test_script XML-Filter-Essex.t
33              
34             =cut
35              
36 2     2   13932 use XML::Essex::Constants qw( EOD );
  2         5  
  2         14  
37              
38 2     2   1441 use XML::Essex::Base (); # Don't import things.
  2         8  
  2         39  
39 2     2   1483 use XML::Essex::Model ();
  2         9  
  2         45  
40 2     2   3323 use XML::SAX::Base ();
  2         52117  
  2         60  
41              
42 2     2   29 no warnings "once";
  2         4  
  2         222  
43              
44             @ISA = qw( XML::Essex::Base XML::SAX::Base );
45              
46             ## This is duplicated in XML::Essex
47             @event_ctors = qw(
48             characters
49             chars
50             end_document
51             end_doc
52             end_element
53             end_elt
54             end
55             start_document
56             start_doc
57             start_element
58             start_elt
59             start
60             xml_decl
61             );
62              
63             @EXPORT = (
64             qw(
65             get_handler
66             output_monitor
67             set_handler
68              
69             put
70             ),
71             @event_ctors,
72             );
73              
74 2     2   11 use strict;
  2         5  
  2         75  
75 2     2   3287 use NEXT;
  2         5477  
  2         72  
76 2     2   1413 use XML::Essex::Filter::OutputMonitor;
  2         6  
  2         2108  
77              
78             sub _init { ## Called by new()
79 1     1   2 my $self = shift;
80              
81 1         8 $self->SUPER::set_handler(
82             XML::Essex::Filter::OutputMonitor->new(
83             Handler => $self->SUPER::get_handler
84             )
85             );
86              
87 1         57 $self->NEXT::_init( @_ );
88             }
89              
90              
91             sub reset { ## Called by execute()
92 1     1 1 2 my $self = shift;
93 1         5 $self->output_monitor->reset;
94 1         17 $self->NEXT::reset( @_ );
95             }
96              
97              
98             sub finish { ## Called by execute()
99 1     1 1 2 my $self = shift;
100 1         3 my ( $ok, $x ) = @_;
101              
102 1         3 my $om = $self->output_monitor;
103              
104 1 50       11 unless ( $ok ) {
105 0 0       0 if ( $x eq EOD . "\n" ) {
106 0 0       0 return ( 1, $om->end_document_result )
107             if $om->end_document_result_has_been_set;
108              
109 0 0       0 return ( 1, undef )
110             unless $om->start_document_seen;
111              
112 0         0 my $eod = EOD;
113 0         0 $x =~ s/^$eod/$eod and no result set by $self/o;
114             }
115 0         0 die $x;
116             }
117              
118 1         17 $self->output_monitor->finish;
119              
120 1 50 33     6 die "incomplete document emitted by $self\n"
121             if $om->start_document_seen && ! $om->end_document_seen;
122              
123 1         11 $self->NEXT::finish( @_ );
124 1 50       160 return ( 1, $om->end_document_result )
125             if $om->end_document_result_has_been_set;
126              
127 0 0       0 die "no result set by $self\n"
128             if $om->start_document_seen;
129              
130 0         0 return ();
131             }
132              
133              
134             =head2 Methods
135              
136             =over
137              
138             =item put
139              
140             Example What's emitted
141             ======= ==============
142             put; ## (whatever's in $_: event, characters, etc)
143             put "text<"; ## text<
144             put [ a => "foo" ] ## foo
145             put comment "foo"; ##
146             put $event; ## an event (see constructors below)
147             put $data; ## Emit a data structure
148             put @list; ## Emit multiple events and / or data structures
149              
150             Emits one or more data structures as XML. Returns the result of
151             emitting the last event (ie the result from the next SAX processor).
152              
153             Most of the things you can pass to put (strings, constructed events) are
154             relatively self evident.
155              
156             For instance, you can pass any events you construct, so an Essex script
157             to make sure all character data is emitted in CDATA sections might look
158             like:
159              
160             get( "text()" ), put cdata $_ while 1;
161              
162             A less obvious feature is that you can pass a (possibly nested) Perl
163             ARRAY that defines an XML tree to emit:
164              
165             put [
166             root => { id => 1 }, ## HASHes contain attributes
167             "root content",
168             [ a => "a content" ],
169             "more root content",
170             [ b => { id => 2 }, "b content" ],
171             ];
172              
173             will emit the SAX events corresponding to the XML (whitespace added for
174             legibility):
175              
176            
177             root content
178             a content
179             more root content
180             b content
181            
182              
183             NOTE: this does not allow you to control attribute order.
184              
185             By using the DOM constructors, you could also write the above as:
186              
187             put elt(
188             root => { id => 1 }, ## HASHes contain attributes
189             "root content",
190             elt( a => "a content" ),
191             "more root content",
192             elt( b => { id => 2 }, "b content" ),
193             ];
194              
195             to emit the XML C<< content >>.
196              
197             You can actually pass any blessed object to C that provides a
198             C method. This will be called with the results of
199             $self->get_handler() (which may be undefined) and should return
200             a TRUE if the handler is undefined or if no events are sent. If any
201             events are sent, it should return the result of the last event.
202              
203             See XML::Essex::Model for some more examples.
204              
205             C is a bit DWIMy: it will fill in the name of end_elements for
206             you if you leave them out:
207              
208             put start "foo";
209             ...
210             put end;
211              
212             It will also C if you emit the wrong end_elt for the currently
213             open element (it keeps a stack), or if you emit and end_document
214             without emitting end_elements. You can catch this error and C the
215             proper end_element events if you like.
216              
217             If the filter exits after half-emitting a document and does not
218             set a result, an error is emitted. This is to notify you that a
219             document was half-emitted. die() to get around this.
220              
221             Note that downstream filters are free to cache things you send, so don't
222             modify events once they're sent. If you need to do that, send a copy
223             and modify the original.
224              
225             =cut
226              
227             sub put {
228 3 50 33 3 1 29 my $self = @_ && UNIVERSAL::isa( $_[0], __PACKAGE__ )
229             ? shift
230             : $XML::Essex::Base::self;
231              
232 3         6 my $om = $self->output_monitor;
233              
234 3 50 33     40 if ( ! $om->get_handler
      33        
235             || $om->get_handler->isa( "XML::SAX::Base::NoHandler" )
236             && $self->{Writer}
237             ) {
238 0         0 $om->set_handler( $self->{Writer}->() );
239             }
240            
241 3         69 my $r;
242 3 50       9 for ( @_ ? @_ : $_ ) {
243 4 100       57 if ( ! ref $_ ) {
    50          
    0          
244 1         12 $r = $om->characters( { Data => $_ } );
245             }
246             elsif ( UNIVERSAL::can( $_, "generate_SAX" ) ) {
247 3         10 $r = $_->generate_SAX( $om );
248             }
249             elsif ( ref $_ eq "ARRAY" ) {
250 0         0 $r = XML::Essex::Event::element->new( @$_ )->generate_SAX( $om );
251             }
252             else {
253 0   0     0 Carp::croak "Unable to put() ", ref $_ || "'$_'";
254             }
255             }
256              
257 3         32 return $r;
258             }
259              
260             =item output_monitor
261              
262             Returns a handle to the output monitor. See
263             L for details.
264              
265             =cut
266              
267             sub set_handler {
268 0 0 0 0 1 0 my $self = @_ && UNIVERSAL::isa( $_[0], __PACKAGE__ )
269             ? shift
270             : $XML::Essex::Base::self;
271 0         0 $self->output_monitor->set_handler( @_ );
272             }
273              
274             sub get_handler {
275 0 0 0 0 1 0 my $self = @_ && UNIVERSAL::isa( $_[0], __PACKAGE__ )
276             ? shift
277             : $XML::Essex::Base::self;
278 0         0 $self->output_monitor->get_handler( @_ );
279             }
280              
281             sub output_monitor {
282 6 50 33 6 1 41 my $self = @_ && UNIVERSAL::isa( $_[0], __PACKAGE__ )
283             ? shift
284             : $XML::Essex::Base::self;
285 6         23 $self->SUPER::get_handler
286             }
287              
288             =back
289              
290             =head2 Event Constructors
291              
292             Each event can be constructed by calling the appropriate function or
293             abbreviated function.
294              
295             =over
296              
297             =cut
298              
299             =item start_document
300              
301             aka: start_doc
302              
303             start_doc \%values; ## SAX does not define any %values.
304              
305             =cut
306              
307 0     0 1 0 sub start_document { XML::Essex::Event::start_document->new( @_ ) }
308             *start_doc = \&start_document;
309              
310             =item end_document
311              
312             aka: end_doc
313              
314             end_doc \%values; ## SAX does not define any %values.
315              
316             =cut
317              
318 0     0 1 0 sub end_document { XML::Essex::Event::end_document->new( @_ ) }
319             *end_doc = \&end_document;
320              
321             =item xml_decl
322              
323             aka: no abbreviated form
324              
325             xml_decl
326             Version => 1,
327             Encoding => "UTF-8",
328             Standalone => "yes";
329              
330             xml_decl {
331             Version => 1,
332             Encoding => "UTF-8",
333             Standalone => "yes"
334             };
335              
336             =cut
337              
338 0     0 1 0 sub xml_decl { XML::Essex::Event::xml_decl->new( @_ ) }
339              
340             =item start_element
341              
342             aka: start_elt, start
343              
344             my $e = start "foo", { "attr" => "va1", ... };
345             my $e = start $start_elt; ## copy constructor
346             my $e = start $elt;
347             my $e = start $end_elt;
348              
349             Stringifies like: C<< >>
350              
351             =cut
352              
353 1     1 1 15 sub start_element { XML::Essex::Event::start_element->new( @_ ) }
354             *start_elt = \&start_element;
355             *start = \&start_element;
356              
357             =item end_element
358              
359             aka: end_elt, end
360              
361             my $e = end "foo";
362             my $e = end $end_elt; ## copy constructor
363             my $e = end $start_elt; ## end for a given start_elt
364             my $e = end $elt; ## elt deconstructor
365              
366             Stringifies like: C<< >>
367              
368             =cut
369              
370 1     1 1 9 sub end_element { XML::Essex::Event::end_element->new( @_ ) }
371             *end_elt = \&end_element;
372             *end = \&end_element;
373              
374             =item characters
375              
376             aka: chars
377              
378             my $e = chars "foo", "bar";
379              
380             Stringifies like the string it is: C<< foobar >>
381              
382             NOTE: the stringified form is not XML escaped.
383              
384             =cut
385              
386 1     1 1 9 sub characters { XML::Essex::Event::characters->new( @_ ) }
387             *chars = \&characters;
388              
389             =back
390              
391              
392             =head1 LIMITATIONS
393              
394             =head1 COPYRIGHT
395              
396             Copyright 2002, R. Barrie Slaymaker, Jr., All Rights Reserved
397              
398             =head1 LICENSE
399              
400             You may use this module under the terms of the BSD, Artistic, oir GPL licenses,
401             any version.
402              
403             =head1 AUTHOR
404              
405             Barrie Slaymaker
406              
407             =cut
408              
409             1;