File Coverage

blib/lib/XML/SAX/Writer.pm
Criterion Covered Total %
statement 134 141 95.0
branch 30 36 83.3
condition 18 27 66.6
subroutine 35 38 92.1
pod 8 9 88.8
total 225 251 89.6


line stmt bran cond sub pod time code
1             package XML::SAX::Writer;
2 3     3   45440 use strict;
  3         5  
  3         158  
3 3     3   11 use vars qw($VERSION %DEFAULT_ESCAPE %COMMENT_ESCAPE);
  3         4  
  3         204  
4             $VERSION = '0.53';
5              
6             # ABSTRACT: SAX2 XML Writer
7              
8 3     3   1578 use Encode qw();
  3         23927  
  3         73  
9 3     3   1383 use XML::SAX::Exception qw();
  3         7114  
  3         65  
10 3     3   1365 use XML::SAX::Writer::XML qw();
  3         5  
  3         58  
11 3     3   1395 use XML::Filter::BufferText qw();
  3         46391  
  3         4110  
12             @XML::SAX::Writer::Exception::ISA = qw(XML::SAX::Exception);
13              
14              
15             %DEFAULT_ESCAPE = (
16             '&' => '&',
17             '<' => '<',
18             '>' => '>',
19             '"' => '"',
20             "'" => ''',
21             );
22              
23             %COMMENT_ESCAPE = (
24             '--' => '--',
25             );
26              
27              
28             #-------------------------------------------------------------------#
29             # new
30             #-------------------------------------------------------------------#
31             sub new {
32 7 50   7 1 2927 my $class = ref($_[0]) ? ref(shift) : shift;
33 7 100       21 my $opt = (@_ == 1) ? { %{shift()} } : {@_};
  4         14  
34              
35             # default the options
36 7   50     35 $opt->{Writer} ||= 'XML::SAX::Writer::XML';
37 7   100     27 $opt->{Escape} ||= \%DEFAULT_ESCAPE;
38 7   50     28 $opt->{CommentEscape} ||= \%COMMENT_ESCAPE;
39 7 100       19 $opt->{EncodeFrom} = exists $opt->{EncodeFrom} ? $opt->{EncodeFrom} : 'utf-8';
40 7 100       16 $opt->{EncodeTo} = exists $opt->{EncodeTo} ? $opt->{EncodeTo} : 'utf-8';
41 7   100     25 $opt->{Format} ||= {}; # needs options w/ defaults, we'll see later
42 7   100     25 $opt->{Output} ||= *{STDOUT}{IO};
43 7   100     27 $opt->{QuoteCharacter} ||= q['];
44              
45 3     3   20 eval "use $opt->{Writer};";
  3     3   3  
  3     1   54  
  3         15  
  3         20  
  3         38  
  1         4  
  1         1  
  1         13  
  7         481  
46              
47 7         20 my $obj = bless $opt, $opt->{Writer};
48 7         29 $obj->init;
49              
50             # we need to buffer the text to escape it right
51 7         37 my $bf = XML::Filter::BufferText->new( Handler => $obj );
52              
53 7         305 return $bf;
54             }
55             #-------------------------------------------------------------------#
56              
57             #-------------------------------------------------------------------#
58             # init
59             #-------------------------------------------------------------------#
60 7     7 1 8 sub init {} # noop, for subclasses
61             #-------------------------------------------------------------------#
62              
63             #-------------------------------------------------------------------#
64             # setConverter
65             #-------------------------------------------------------------------#
66             sub setConverter {
67 13     13 1 14 my $self = shift;
68              
69 13 100       50 if (lc($self->{EncodeFrom}) ne lc($self->{EncodeTo})) {
70 10         32 $self->{Encoder} = XML::SAX::Writer::Encode->new($self->{EncodeFrom}, $self->{EncodeTo});
71             }
72             else {
73 3         14 $self->{Encoder} = XML::SAX::Writer::NullConverter->new;
74             }
75 13         32 return $self;
76             }
77             #-------------------------------------------------------------------#
78              
79             #-------------------------------------------------------------------#
80             # setConsumer
81             #-------------------------------------------------------------------#
82             sub setConsumer {
83 13     13 1 15 my $self = shift;
84              
85             # create the Consumer
86 13         23 my $ref = ref $self->{Output};
87 13 100 66     128 if ($ref eq 'SCALAR') {
    100 100        
    100          
    100          
    100          
    100          
88 3         14 $self->{Consumer} = XML::SAX::Writer::StringConsumer->new($self->{Output});
89             }
90             elsif ($ref eq 'CODE') {
91 1         5 $self->{Consumer} = XML::SAX::Writer::CodeConsumer->new($self->{Output});
92             }
93             elsif ($ref eq 'ARRAY') {
94 1         6 $self->{Consumer} = XML::SAX::Writer::ArrayConsumer->new($self->{Output});
95             }
96             elsif (
97             $ref eq 'GLOB' or
98             UNIVERSAL::isa(\$self->{Output}, 'GLOB') or
99             UNIVERSAL::isa($self->{Output}, 'IO::Handle')) {
100 4         18 $self->{Consumer} = XML::SAX::Writer::HandleConsumer->new($self->{Output});
101             }
102             elsif (not $ref) {
103 1         6 $self->{Consumer} = XML::SAX::Writer::FileConsumer->new($self->{Output});
104             }
105             elsif (UNIVERSAL::can($self->{Output}, 'output')) {
106 2         4 $self->{Consumer} = $self->{Output};
107             }
108             else {
109 1         10 XML::SAX::Writer::Exception->throw( Message => 'Unknown option for Output' );
110             }
111 12         54 return $self;
112             }
113             #-------------------------------------------------------------------#
114              
115             #-------------------------------------------------------------------#
116             # setEscaperRegex
117             #-------------------------------------------------------------------#
118             sub setEscaperRegex {
119 13     13 1 12 my $self = shift;
120              
121 65         1010 $self->{EscaperRegex} = eval 'qr/' .
122 13         16 join( '|', map { $_ = "\Q$_\E" } keys %{$self->{Escape}}) .
  13         51  
123             '/;' ;
124 13         54 return $self;
125             }
126             #-------------------------------------------------------------------#
127              
128             #-------------------------------------------------------------------#
129             # setCommentEscaperRegex
130             #-------------------------------------------------------------------#
131             sub setCommentEscaperRegex {
132 13     13 1 16 my $self = shift;
133              
134 13         739 $self->{CommentEscaperRegex} =
135             eval 'qr/' .
136 13         15 join( '|', map { $_ = "\Q$_\E" } keys %{$self->{CommentEscape}}) .
  13         30  
137             '/;' ;
138 13         43 return $self;
139             }
140             #-------------------------------------------------------------------#
141              
142             #-------------------------------------------------------------------#
143             # escape
144             #-------------------------------------------------------------------#
145             sub escape {
146 3     3 1 544 my $self = shift;
147 3         4 my $str = shift;
148              
149 3         60 $str =~ s/($self->{EscaperRegex})/$self->{Escape}->{$1}/ge;
  5         15  
150 3         8 return $str;
151             }
152             #-------------------------------------------------------------------#
153              
154             #-------------------------------------------------------------------#
155             # escapeComment
156             #-------------------------------------------------------------------#
157             sub escapeComment {
158 0     0 1 0 my $self = shift;
159 0         0 my $str = shift;
160              
161 0         0 $str =~ s/($self->{CommentEscaperRegex})/$self->{CommentEscape}->{$1}/ge;
  0         0  
162 0         0 return $str;
163             }
164             #-------------------------------------------------------------------#
165              
166             #-------------------------------------------------------------------#
167             # convert and checking the return value
168             #-------------------------------------------------------------------#
169             sub safeConvert {
170 8     8 0 9 my $self = shift;
171 8         8 my $str = shift;
172              
173 8         19 my $out = $self->{Encoder}->convert($str);
174              
175 8 100 66     22 if (!defined $out && defined $str) {
176 1         6 warn "Conversion error returned by Encoder [$self->{Encoder}], string: '$str'";
177 1         3 $out = '_LOST_DATA_';
178             }
179 8         16 return $out;
180             }
181             #-------------------------------------------------------------------#
182              
183              
184             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
185             #`,`, The Empty Consumer ,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
186             #```````````````````````````````````````````````````````````````````#
187              
188             # this package is only there to provide a smooth upgrade path in case
189             # new methods are added to the interface
190              
191             package XML::SAX::Writer::ConsumerInterface;
192              
193             sub new {
194 15     15   1102 my $class = shift;
195 15         15 my $ref = shift;
196             ## $self is a reference to the reference that we will send output
197             ## to. This allows us to bless $self without blessing $$self.
198 15   33     82 return bless \$ref, ref $class || $class;
199             }
200              
201 0     0   0 sub output {}
202 1     1   16 sub finalize {}
203              
204              
205             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
206             #`,`, The String Consumer `,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
207             #```````````````````````````````````````````````````````````````````#
208              
209             package XML::SAX::Writer::StringConsumer;
210             @XML::SAX::Writer::StringConsumer::ISA = qw(XML::SAX::Writer::ConsumerInterface);
211              
212             #-------------------------------------------------------------------#
213             # new
214             #-------------------------------------------------------------------#
215             sub new {
216 4     4   43 my $self = shift->SUPER::new( @_ );
217 4         6 ${${$self}} = '';
  4         3  
  4         18  
218 4         9 return $self;
219             }
220             #-------------------------------------------------------------------#
221              
222             #-------------------------------------------------------------------#
223             # output
224             #-------------------------------------------------------------------#
225 7     7   365 sub output { ${${$_[0]}} .= $_[1] }
  7         5  
  7         19  
226             #-------------------------------------------------------------------#
227              
228             #-------------------------------------------------------------------#
229             # finalize
230             #-------------------------------------------------------------------#
231 3     3   6 sub finalize { ${$_[0]} }
  3         9  
232             #-------------------------------------------------------------------#
233              
234             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
235             #`,`, The Code Consumer `,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
236             #```````````````````````````````````````````````````````````````````#
237              
238             package XML::SAX::Writer::CodeConsumer;
239             @XML::SAX::Writer::CodeConsumer::ISA = qw(XML::SAX::Writer::ConsumerInterface );
240              
241             #-------------------------------------------------------------------#
242             # new
243             #-------------------------------------------------------------------#
244             sub new {
245 1     1   6 my $self = shift->SUPER::new( @_ );
246 1         7 $$self->( 'start_document', '' );
247 1         5 return $self;
248             }
249             #-------------------------------------------------------------------#
250              
251             #-------------------------------------------------------------------#
252             # output
253             #-------------------------------------------------------------------#
254 1     1   2 sub output { ${$_[0]}->('data', pop) } ## Avoid an extra copy
  1         4  
255             #-------------------------------------------------------------------#
256              
257             #-------------------------------------------------------------------#
258             # finalize
259             #-------------------------------------------------------------------#
260 1     1   1 sub finalize { ${$_[0]}->('end_document', '') }
  1         3  
261             #-------------------------------------------------------------------#
262              
263              
264             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
265             #`,`, The Array Consumer ,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
266             #```````````````````````````````````````````````````````````````````#
267              
268             package XML::SAX::Writer::ArrayConsumer;
269             @XML::SAX::Writer::ArrayConsumer::ISA = qw(XML::SAX::Writer::ConsumerInterface);
270              
271             #-------------------------------------------------------------------#
272             # new
273             #-------------------------------------------------------------------#
274             sub new {
275 2     2   195 my $self = shift->SUPER::new( @_ );
276 2         11 @$$self = ();
277 2         4 return $self;
278             }
279             #-------------------------------------------------------------------#
280              
281             #-------------------------------------------------------------------#
282             # output
283             #-------------------------------------------------------------------#
284 2     2   210 sub output { push @${$_[0]}, pop }
  2         5  
285             #-------------------------------------------------------------------#
286              
287             #-------------------------------------------------------------------#
288             # finalize
289             #-------------------------------------------------------------------#
290 1     1   4 sub finalize { return ${$_[0]} }
  1         3  
291             #-------------------------------------------------------------------#
292              
293              
294             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
295             #`,`, The Handle Consumer `,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
296             #```````````````````````````````````````````````````````````````````#
297              
298             package XML::SAX::Writer::HandleConsumer;
299             @XML::SAX::Writer::HandleConsumer::ISA = qw(XML::SAX::Writer::ConsumerInterface);
300              
301             #-------------------------------------------------------------------#
302             # output
303             #-------------------------------------------------------------------#
304             sub output {
305 4     4   506 my $fh = ${$_[0]};
  4         13  
306 4 50       45 print $fh pop or XML::SAX::Exception->throw(
307             Message => "Could not write to handle: $fh ($!)"
308             );
309             }
310             #-------------------------------------------------------------------#
311              
312             #-------------------------------------------------------------------#
313             # finalize
314             #-------------------------------------------------------------------#
315 0     0   0 sub finalize { return 0 }
316             #-------------------------------------------------------------------#
317              
318              
319             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
320             #`,`, The File Consumer `,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
321             #```````````````````````````````````````````````````````````````````#
322              
323             package XML::SAX::Writer::FileConsumer;
324             @XML::SAX::Writer::FileConsumer::ISA = qw(XML::SAX::Writer::HandleConsumer);
325              
326             #-------------------------------------------------------------------#
327             # new
328             #-------------------------------------------------------------------#
329             sub new {
330 3     3   466 my ( $proto, $file ) = ( shift, shift );
331              
332 3 50 0     21 XML::SAX::Writer::Exception->throw(
333             Message => "No filename provided to " . ref( $proto || $proto )
334             ) unless defined $file;
335              
336 3         7 local *XFH;
337              
338 3 50       212 open XFH, ">$file" or XML::SAX::Writer::Exception->throw(
339             Message => "Error opening file $file: $!"
340             );
341              
342 3         27 return $proto->SUPER::new( *{XFH}{IO}, @_ );
343             }
344             #-------------------------------------------------------------------#
345              
346             #-------------------------------------------------------------------#
347             # finalize
348             #-------------------------------------------------------------------#
349             sub finalize {
350 2     2   6 close ${$_[0]};
  2         68  
351 2         4 return 0;
352             }
353             #-------------------------------------------------------------------#
354              
355              
356             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
357             #`,`, Noop Converter ,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
358             #```````````````````````````````````````````````````````````````````#
359              
360             package XML::SAX::Writer::NullConverter;
361 4     4   396 sub new { return bless [], __PACKAGE__ }
362 3     3   8 sub convert { $_[1] }
363              
364              
365             #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#
366             #`,`, Encode Converter ,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,#
367             #```````````````````````````````````````````````````````````````````#
368              
369             package XML::SAX::Writer::Encode;
370             sub new {
371 11     11   354 my ($class, $from, $to) = @_;
372 11         29 my $self = {
373             from_enc => $from,
374             to_enc => $to,
375             };
376 11         30 return bless $self, $class;
377             }
378             sub convert {
379 7     7   15 my ($self, $data) = @_;
380 7         7 eval {
381 7 50       39 $data = Encode::decode($self->{from_enc}, $data) if $self->{from_enc};
382 7 50       341 $data = Encode::encode($self->{to_enc}, $data, Encode::FB_CROAK) if $self->{to_enc};
383             };
384 7 100       255 if ($@) {
385 1         6 warn $@;
386 1         3 return;
387             }
388 6         9 return $data;
389             };
390              
391              
392             1;
393              
394             =pod
395              
396             =encoding UTF-8
397              
398             =head1 NAME
399              
400             XML::SAX::Writer - SAX2 XML Writer
401              
402             =head1 VERSION
403              
404             version 0.55
405              
406             =head1 SYNOPSIS
407              
408             use XML::SAX::Writer;
409             use XML::SAX::SomeDriver;
410              
411             my $w = XML::SAX::Writer->new;
412             my $d = XML::SAX::SomeDriver->new(Handler => $w);
413              
414             $d->parse('some options...');
415              
416             =head1 DESCRIPTION
417              
418             =head2 Why yet another XML Writer ?
419              
420             A new XML Writer was needed to match the SAX2 effort because quite
421             naturally no existing writer understood SAX2. My first intention had
422             been to start patching XML::Handler::YAWriter as it had previously
423             been my favourite writer in the SAX1 world.
424              
425             However the more I patched it the more I realised that what I thought
426             was going to be a simple patch (mostly adding a few event handlers and
427             changing the attribute syntax) was turning out to be a rewrite due to
428             various ideas I'd been collecting along the way. Besides, I couldn't
429             find a way to elegantly make it work with SAX2 without breaking the
430             SAX1 compatibility which people are probably still using. There are of
431             course ways to do that, but most require user interaction which is
432             something I wanted to avoid.
433              
434             So in the end there was a new writer. I think it's in fact better this
435             way as it helps keep SAX1 and SAX2 separated.
436              
437             =head1 METHODS
438              
439             =over 4
440              
441             =item * new(%hash)
442              
443             This is the constructor for this object. It takes a number of
444             parameters, all of which are optional.
445              
446             =item * Output
447              
448             This parameter can be one of several things. If it is a simple
449             scalar, it is interpreted as a filename which will be opened for
450             writing. If it is a scalar reference, output will be appended to this
451             scalar. If it is an array reference, output will be pushed onto this
452             array as it is generated. If it is a filehandle, then output will be
453             sent to this filehandle.
454              
455             Finally, it is possible to pass an object for this parameter, in which
456             case it is assumed to be an object that implements the consumer
457             interface L
458             INTERFACE>.
459              
460             If this parameter is not provided, then output is sent to STDOUT.
461              
462             =item * Escape
463              
464             This should be a hash reference where the keys are characters
465             sequences that should be escaped and the values are the escaped form
466             of the sequence. By default, this module will escape the ampersand
467             (&), less than (<), greater than (>), double quote ("), and apostrophe
468             ('). Note that some browsers don't support the ' escape used for
469             apostrophes so that you should be careful when outputting XHTML.
470              
471             If you only want to add entries to the Escape hash, you can first
472             copy the contents of %XML::SAX::Writer::DEFAULT_ESCAPE.
473              
474             =item * CommentEscape
475              
476             Comment content often needs to be escaped differently from other
477             content. This option works exactly as the previous one except that
478             by default it only escapes the double dash (--) and that the contents
479             can be copied from %XML::SAX::Writer::COMMENT_ESCAPE.
480              
481             =item * EncodeFrom
482              
483             The character set encoding in which incoming data will be provided.
484             This defaults to UTF-8, which works for US-ASCII as well.
485              
486             Set this to C if you do not wish to decode your data.
487              
488             =item * EncodeTo
489              
490             The character set encoding in which output should be encoded. Again,
491             this defaults to UTF-8.
492              
493             Set this to C if you do not with to encode your data.
494              
495             =item * QuoteCharacter
496              
497             Set the character used to quote attributes. This defaults to single quotes (')
498             for backwards compatibility.
499              
500             =back
501              
502             =head1 THE CONSUMER INTERFACE
503              
504             XML::SAX::Writer can receive pluggable consumer objects that will be
505             in charge of writing out what is formatted by this module. Setting a
506             Consumer is done by setting the Output option to the object of your
507             choice instead of to an array, scalar, or file handle as is more
508             commonly done (internally those in fact map to Consumer classes and
509             and simply available as options for your convenience).
510              
511             If you don't understand this, don't worry. You don't need it most of
512             the time.
513              
514             That object can be from any class, but must have two methods in its
515             API. It is also strongly recommended that it inherits from
516             XML::SAX::Writer::ConsumerInterface so that it will not break if that
517             interface evolves over time. There are examples at the end of
518             XML::SAX::Writer's code.
519              
520             The two methods that it needs to implement are:
521              
522             =over 4
523              
524             =item * output STRING
525              
526             (Required)
527              
528             This is called whenever the Writer wants to output a string formatted
529             in XML. Encoding conversion, character escaping, and formatting have
530             already taken place. It's up to the consumer to do whatever it wants
531             with the string.
532              
533             =item * finalize()
534              
535             (Optional)
536              
537             This is called once the document has been output in its entirety,
538             during the end_document event. end_document will in fact return
539             whatever finalize() returns, and that in turn should be returned
540             by parse() for whatever parser was invoked. It might be useful if
541             you need to provide feedback of some sort.
542              
543             =back
544              
545             Here's an example of a custom consumer. Note the extra C<$> signs in
546             front of $self; the base class is optimized for the overwhelmingly
547             common case where only one data member is required and $self is a
548             reference to that data member.
549              
550             package MyConsumer;
551              
552             @ISA = qw( XML::SAX::Writer::ConsumerInterface );
553              
554             use strict;
555              
556             sub new {
557             my $self = shift->SUPER::new( my $output );
558              
559             $$self = ''; # Note the extra '$'
560              
561             return $self;
562             }
563              
564             sub output {
565             my $self = shift;
566             $$self .= uc shift;
567             }
568              
569             sub get_output {
570             my $self = shift;
571             return $$self;
572             }
573              
574             And here is one way to use it:
575              
576             my $c = MyConsumer->new;
577             my $w = XML::SAX::Writer->new( Output => $c );
578              
579             ## ... send events to $w ...
580              
581             print $c->get_output;
582              
583             If you need to store more that one data member, pass in an array or hash
584             reference:
585              
586             my $self = shift->SUPER::new( {} );
587              
588             and access it like:
589              
590             sub output {
591             my $self = shift;
592             $$self->{Output} .= uc shift;
593             }
594              
595             =head1 THE ENCODER INTERFACE
596              
597             Encoders can be plugged in to allow one to use one's favourite encoder
598             object. Presently there are two encoders: Encode and NullEncoder. They
599             need to implement two methods, and may inherit from
600             XML::SAX::Writer::NullConverter if they wish to
601              
602             =over 4
603              
604             =item new FROM_ENCODING, TO_ENCODING
605              
606             Creates a new Encoder. The arguments are the chosen encodings.
607              
608             =item convert STRING
609              
610             Converts that string and returns it.
611              
612             =back
613              
614             Note that the return value of the convert method is B checked. Output may
615             be truncated if a character couldn't be converted correctly. To avoid problems
616             the encoder should take care encoding errors itself, for example by raising an
617             exception.
618              
619             =head1 CUSTOM OUTPUT
620              
621             This module is generally used to write XML -- which it does most of the
622             time -- but just like the rest of SAX it can be used as a generic
623             framework to output data, the opposite of a non-XML SAX parser.
624              
625             Of course there's only so much that one can abstract, so depending on
626             your format this may or may not be useful. If it is, you'll need to
627             know the following API (and probably to have a look inside
628             C, the default Writer).
629              
630             =over
631              
632             =item init
633              
634             Called before the writing starts, it's a chance for the subclass to do
635             some initialisation if it needs it.
636              
637             =item setConverter
638              
639             This is used to set the proper converter for character encodings. The
640             default implementation should suffice but you can override it. It must
641             set C<< $self->{Encoder} >> to an Encoder object. Subclasses *should* call
642             it.
643              
644             =item setConsumer
645              
646             Same as above, except that it is for the Consumer object, and that it
647             must set C<< $self->{Consumer} >>.
648              
649             =item setEscaperRegex
650              
651             Will initialise the escaping regex C<< $self->{EscaperRegex} >> based on
652             what is needed.
653              
654             =item escape STRING
655              
656             Takes a string and escapes it properly.
657              
658             =item setCommentEscaperRegex and escapeComment STRING
659              
660             These work exactly the same as the two above, except that they are meant
661             to operate on comment contents, which often have different escaping rules
662             than those that apply to regular content.
663              
664             =back
665              
666             =head1 TODO
667              
668             - proper UTF-16 handling
669              
670             - the formatting options need to be developed.
671              
672             - test, test, test (and then some tests)
673              
674             - doc, doc, doc (actually this part is in better shape)
675              
676             - remove the xml_decl and replace it with intelligent logic, as
677             discussed on perl-xml
678              
679             - make a the Consumer selecting code available in the API, to avoid
680             duplicating
681              
682             - add an Apache output Consumer, triggered by passing $r as Output
683              
684             =head1 CREDITS
685              
686             Michael Koehne (XML::Handler::YAWriter) for much inspiration and Barrie
687             Slaymaker for the Consumer pattern idea, the coderef output option and
688             miscellaneous bugfixes and performance tweaks. Of course the usual
689             suspects (Kip Hampton and Matt Sergeant) helped in the usual ways.
690              
691             =head1 SEE ALSO
692              
693             XML::SAX::*
694              
695             =head1 AUTHORS
696              
697             =over 4
698              
699             =item *
700              
701             Robin Berjon
702              
703             =item *
704              
705             Chris Prather
706              
707             =back
708              
709             =head1 COPYRIGHT AND LICENSE
710              
711             This software is copyright (c) 2014 by Robin Berjon.
712              
713             This is free software; you can redistribute it and/or modify it under
714             the same terms as the Perl 5 programming language system itself.
715              
716             =cut
717              
718             __END__