Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5969 dpurdie 1
########################################################################
2
# Writer.pm - write an XML document.
3
# Copyright (c) 1999 by Megginson Technologies.
4
# Copyright (c) 2003 Ed Avis <ed@membled.com>
5
# Copyright (c) 2004-2010 Joseph Walton <joe@kafsemo.org>
6
# Redistribution and use in source and compiled forms, with or without
7
# modification, are permitted under any circumstances.  No warranty.
8
########################################################################
9
 
10
package XML::Writer;
11
 
12
require 5.004;
13
 
14
use strict;
15
use vars qw($VERSION);
16
use Carp;
17
use IO::Handle;
18
$VERSION = "0.625";
19
 
20
use overload '""' => \&_overload_string;
21
 
22
 
23
########################################################################
24
# Constructor.
25
########################################################################
26
 
27
#
28
# Public constructor.
29
#
30
# This actually does most of the work of the module: it defines closures
31
# for all of the real processing, and selects the appropriate closures
32
# to use based on the value of the UNSAFE parameter.  The actual methods
33
# are just stubs.
34
#
35
sub new {
36
  my ($class, %params) = (@_);
37
 
38
                                # If the user wants namespaces,
39
                                # intercept the request here; it will
40
                                # come back to this constructor
41
                                # from within XML::Writer::Namespaces::new()
42
  if ($params{NAMESPACES}) {
43
    delete $params{NAMESPACES};
44
    return XML::Writer::Namespaces->new(%params);
45
  }
46
 
47
                                # Set up $self and basic parameters
48
  my $self;
49
  my $output;
50
  my $unsafe = $params{UNSAFE};
51
  my $newlines = $params{NEWLINES};
52
  my $dataMode = $params{DATA_MODE};
53
  my $dataIndent;
54
  my $selfcontained_output;
55
  my $use_selfcontained_output = 0;
56
 
57
                                # If the NEWLINES parameter is specified,
58
                                # set the $nl variable appropriately
59
  my $nl = '';
60
  if ($newlines) {
61
    $nl = "\n";
62
  }
63
 
64
  my $outputEncoding = $params{ENCODING} || "";
65
  my ($checkUnencodedRepertoire, $escapeEncoding);
66
  if (lc($outputEncoding) eq 'us-ascii') {
67
    $checkUnencodedRepertoire = \&_croakUnlessASCII;
68
    $escapeEncoding = \&_escapeASCII;
69
  } else {
70
    my $doNothing = sub {};
71
    $checkUnencodedRepertoire = $doNothing;
72
    $escapeEncoding = $doNothing;
73
  }
74
 
75
                                # Parse variables
76
  my @elementStack = ();
77
  my $elementLevel = 0;
78
  my %seen = ();
79
 
80
  my $hasData = 0;
81
  my @hasDataStack = ();
82
  my $hasElement = 0;
83
  my @hasElementStack = ();
84
  my $hasHeading = 0; # Does this document have anything before the first element?
85
 
86
  #
87
  # Private method to show attributes.
88
  #
89
  my $showAttributes = sub {
90
    my $atts = $_[0];
91
    my $i = 1;
92
    while ($atts->[$i]) {
93
      my $aname = $atts->[$i++];
94
      my $value = _escapeLiteral($atts->[$i++]);
95
      $value =~ s/\x0a/\&#10\;/g;
96
      $value =~ s/\x0d/\&#13\;/g;
97
      $value =~ s/\x09/\&#9\;/g;
98
      &{$escapeEncoding}($value);
99
      $output->print(" $aname=\"$value\"");
100
    }
101
  };
102
 
103
                                # Method implementations: the SAFE_
104
                                # versions perform error checking
105
                                # and then call the regular ones.
106
  my $end = sub {
107
    $output->print("\n");
108
 
109
    return $selfcontained_output
110
        if $use_selfcontained_output and defined wantarray;
111
  };
112
 
113
  my $SAFE_end = sub {
114
    if (!$seen{ELEMENT}) {
115
      croak("Document cannot end without a document element");
116
    } elsif ($elementLevel > 0) {
117
      croak("Document ended with unmatched start tag(s): @elementStack");
118
    } else {
119
      @elementStack = ();
120
      $elementLevel = 0;
121
      %seen = ();
122
      &{$end};
123
    }
124
  };
125
 
126
  my $xmlDecl = sub {
127
    my ($encoding, $standalone) = (@_);
128
    if ($standalone && $standalone ne 'no') {
129
      $standalone = 'yes';
130
    }
131
 
132
    # Only include an encoding if one has been explicitly supplied,
133
    #  either here or on construction. Allow the empty string
134
    #  to suppress it.
135
    if (!defined($encoding)) {
136
      $encoding = $outputEncoding;
137
    }
138
    $output->print("<?xml version=\"1.0\"");
139
    if ($encoding) {
140
      $output->print(" encoding=\"$encoding\"");
141
    }
142
    if ($standalone) {
143
      $output->print(" standalone=\"$standalone\"");
144
    }
145
    $output->print("?>\n");
146
    $hasHeading = 1;
147
  };
148
 
149
  my $SAFE_xmlDecl = sub {
150
    if ($seen{ANYTHING}) {
151
      croak("The XML declaration is not the first thing in the document");
152
    } else {
153
      $seen{ANYTHING} = 1;
154
      $seen{XMLDECL} = 1;
155
      &{$xmlDecl};
156
    }
157
  };
158
 
159
  my $pi = sub {
160
    my ($target, $data) = (@_);
161
    if ($data) {
162
      $output->print("<?$target $data?>");
163
    } else {
164
      $output->print("<?$target?>");
165
    }
166
    if ($elementLevel == 0) {
167
      $output->print("\n");
168
      $hasHeading = 1;
169
    }
170
  };
171
 
172
  my $SAFE_pi = sub {
173
    my ($name, $data) = (@_);
174
    $seen{ANYTHING} = 1;
175
    if (($name =~ /^xml/i) && ($name !~ /^xml-(stylesheet|model)$/i)) {
176
      carp("Processing instruction target begins with 'xml'");
177
    }
178
 
179
    if ($name =~ /\?\>/ || (defined($data) && $data =~ /\?\>/)) {
180
      croak("Processing instruction may not contain '?>'");
181
    } elsif ($name =~ /\s/) {
182
      croak("Processing instruction name may not contain whitespace");
183
    } else {
184
      &{$pi};
185
    }
186
  };
187
 
188
  my $comment = sub {
189
    my $data = $_[0];
190
    if ($dataMode && $elementLevel) {
191
      $output->print("\n");
192
      $output->print($dataIndent x $elementLevel);
193
    }
194
    $output->print("<!-- $data -->");
195
    if ($dataMode && $elementLevel) {
196
      $hasElement = 1;
197
    } elsif ($elementLevel == 0) {
198
      $output->print("\n");
199
      $hasHeading = 1;
200
    }
201
  };
202
 
203
  my $SAFE_comment = sub {
204
    my $data = $_[0];
205
    if ($data =~ /--/) {
206
      carp("Interoperability problem: \"--\" in comment text");
207
    }
208
 
209
    if ($data =~ /-->/) {
210
      croak("Comment may not contain '-->'");
211
    } else {
212
      &{$checkUnencodedRepertoire}($data);
213
      $seen{ANYTHING} = 1;
214
      &{$comment};
215
    }
216
  };
217
 
218
  my $doctype = sub {
219
    my ($name, $publicId, $systemId) = (@_);
220
    $output->print("<!DOCTYPE $name");
221
    if ($publicId) {
222
      unless ( defined $systemId) {
223
        croak("A DOCTYPE declaration with a public ID must also have a system ID");
224
      }
225
      $output->print(" PUBLIC \"$publicId\" \"$systemId\"");
226
    } elsif ( defined $systemId ) {
227
      $output->print(" SYSTEM \"$systemId\"");
228
    }
229
    $output->print(">\n");
230
    $hasHeading = 1;
231
  };
232
 
233
  my $SAFE_doctype = sub {
234
    my $name = $_[0];
235
    if ($seen{DOCTYPE}) {
236
      croak("Attempt to insert second DOCTYPE declaration");
237
    } elsif ($seen{ELEMENT}) {
238
      croak("The DOCTYPE declaration must come before the first start tag");
239
    } else {
240
      $seen{ANYTHING} = 1;
241
      $seen{DOCTYPE} = $name;
242
      &{$doctype};
243
    }
244
  };
245
 
246
  my $startTag = sub {
247
    my $name = $_[0];
248
    if ($dataMode && ($hasHeading || $elementLevel)) {
249
      $output->print("\n");
250
      $output->print($dataIndent x $elementLevel);
251
    }
252
    $elementLevel++;
253
    push @elementStack, $name;
254
    $output->print("<$name");
255
    &{$showAttributes}(\@_);
256
    $output->print("$nl>");
257
    if ($dataMode) {
258
      $hasElement = 1;
259
      push @hasDataStack, $hasData;
260
      $hasData = 0;
261
      push @hasElementStack, $hasElement;
262
      $hasElement = 0;
263
    }
264
  };
265
 
266
  my $SAFE_startTag = sub {
267
    my $name = $_[0];
268
 
269
    &{$checkUnencodedRepertoire}($name);
270
    _checkAttributes(\@_);
271
 
272
    if ($seen{ELEMENT} && $elementLevel == 0) {
273
      croak("Attempt to insert start tag after close of document element");
274
    } elsif ($elementLevel == 0 && $seen{DOCTYPE} && $name ne $seen{DOCTYPE}) {
275
      croak("Document element is \"$name\", but DOCTYPE is \""
276
            . $seen{DOCTYPE}
277
            . "\"");
278
    } elsif ($dataMode && $hasData) {
279
      croak("Mixed content not allowed in data mode: element $name");
280
    } else {
281
      $seen{ANYTHING} = 1;
282
      $seen{ELEMENT} = 1;
283
      &{$startTag};
284
    }
285
  };
286
 
287
  my $emptyTag = sub {
288
    my $name = $_[0];
289
    if ($dataMode && ($hasHeading || $elementLevel)) {
290
      $output->print("\n");
291
      $output->print($dataIndent x $elementLevel);
292
    }
293
    $output->print("<$name");
294
    &{$showAttributes}(\@_);
295
    $output->print("$nl />");
296
    if ($dataMode) {
297
      $hasElement = 1;
298
    }
299
  };
300
 
301
  my $SAFE_emptyTag = sub {
302
    my $name = $_[0];
303
 
304
    &{$checkUnencodedRepertoire}($name);
305
    _checkAttributes(\@_);
306
 
307
    if ($seen{ELEMENT} && $elementLevel == 0) {
308
      croak("Attempt to insert empty tag after close of document element");
309
    } elsif ($elementLevel == 0 && $seen{DOCTYPE} && $name ne $seen{DOCTYPE}) {
310
      croak("Document element is \"$name\", but DOCTYPE is \""
311
            . $seen{DOCTYPE}
312
            . "\"");
313
    } elsif ($dataMode && $hasData) {
314
      croak("Mixed content not allowed in data mode: element $name");
315
    } else {
316
      $seen{ANYTHING} = 1;
317
      $seen{ELEMENT} = 1;
318
      &{$emptyTag};
319
    }
320
  };
321
 
322
  my $endTag = sub {
323
    my $name = $_[0];
324
    my $currentName = pop @elementStack;
325
    $name = $currentName unless $name;
326
    $elementLevel--;
327
    if ($dataMode && $hasElement) {
328
      $output->print("\n");
329
      $output->print($dataIndent x $elementLevel);
330
    }
331
    $output->print("</$name$nl>");
332
    if ($dataMode) {
333
      $hasData = pop @hasDataStack;
334
      $hasElement = pop @hasElementStack;
335
    }
336
  };
337
 
338
  my $SAFE_endTag = sub {
339
    my $name = $_[0];
340
    my $oldName = $elementStack[$#elementStack];
341
    if ($elementLevel <= 0) {
342
      croak("End tag \"$name\" does not close any open element");
343
    } elsif ($name && ($name ne $oldName)) {
344
      croak("Attempt to end element \"$oldName\" with \"$name\" tag");
345
    } else {
346
      &{$endTag};
347
    }
348
  };
349
 
350
  my $characters = sub {
351
    my $data = $_[0];
352
    if ($data =~ /[\&\<\>]/) {
353
      $data =~ s/\&/\&amp\;/g;
354
      $data =~ s/\</\&lt\;/g;
355
      $data =~ s/\>/\&gt\;/g;
356
    }
357
    &{$escapeEncoding}($data);
358
    $output->print($data);
359
    $hasData = 1;
360
  };
361
 
362
  my $SAFE_characters = sub {
363
    if ($elementLevel < 1) {
364
      croak("Attempt to insert characters outside of document element");
365
    } elsif ($dataMode && $hasElement) {
366
      croak("Mixed content not allowed in data mode: characters");
367
    } else {
368
      _croakUnlessDefinedCharacters($_[0]);
369
      &{$characters};
370
    }
371
  };
372
 
373
  my $raw = sub {
374
    $output->print($_[0]);
375
    # Don't set $hasData or any other information: we know nothing
376
    # about what was just written.
377
    #
378
  };
379
 
380
  my $SAFE_raw = sub {
381
    croak('raw() is only available when UNSAFE is set');
382
  };
383
 
384
  my $cdata = sub {
385
      my $data = $_[0];
386
      $data    =~ s/\]\]>/\]\]\]\]><!\[CDATA\[>/g;
387
      $output->print("<![CDATA[$data]]>");
388
      $hasData = 1;
389
  };
390
 
391
  my $SAFE_cdata = sub {
392
    if ($elementLevel < 1) {
393
      croak("Attempt to insert characters outside of document element");
394
    } elsif ($dataMode && $hasElement) {
395
      croak("Mixed content not allowed in data mode: characters");
396
    } else {
397
      _croakUnlessDefinedCharacters($_[0]);
398
      &{$checkUnencodedRepertoire}($_[0]);
399
      &{$cdata};
400
    }
401
  };
402
 
403
                                # Assign the correct closures based on
404
                                # the UNSAFE parameter
405
  if ($unsafe) {
406
    $self = {'END' => $end,
407
             'XMLDECL' => $xmlDecl,
408
             'PI' => $pi,
409
             'COMMENT' => $comment,
410
             'DOCTYPE' => $doctype,
411
             'STARTTAG' => $startTag,
412
             'EMPTYTAG' => $emptyTag,
413
             'ENDTAG' => $endTag,
414
             'CHARACTERS' => $characters,
415
             'RAW' => $raw,
416
             'CDATA' => $cdata
417
            };
418
  } else {
419
    $self = {'END' => $SAFE_end,
420
             'XMLDECL' => $SAFE_xmlDecl,
421
             'PI' => $SAFE_pi,
422
             'COMMENT' => $SAFE_comment,
423
             'DOCTYPE' => $SAFE_doctype,
424
             'STARTTAG' => $SAFE_startTag,
425
             'EMPTYTAG' => $SAFE_emptyTag,
426
             'ENDTAG' => $SAFE_endTag,
427
             'CHARACTERS' => $SAFE_characters,
428
             'RAW' => $SAFE_raw,               # This will intentionally fail
429
             'CDATA' => $SAFE_cdata
430
            };
431
  }
432
 
433
                                # Query methods
434
  $self->{'IN_ELEMENT'} = sub {
435
    my ($ancestor) = (@_);
436
    return $elementStack[$#elementStack] eq $ancestor;
437
  };
438
 
439
  $self->{'WITHIN_ELEMENT'} = sub {
440
    my ($ancestor) = (@_);
441
    my $el;
442
    foreach $el (@elementStack) {
443
      return 1 if $el eq $ancestor;
444
    }
445
    return 0;
446
  };
447
 
448
  $self->{'CURRENT_ELEMENT'} = sub {
449
    return $elementStack[$#elementStack];
450
  };
451
 
452
  $self->{'ANCESTOR'} = sub {
453
    my ($n) = (@_);
454
    if ($n < scalar(@elementStack)) {
455
      return $elementStack[$#elementStack-$n];
456
    } else {
457
      return undef;
458
    }
459
  };
460
 
461
                                # Set and get the output destination.
462
  $self->{'GETOUTPUT'} = sub {
463
    if (ref($output) ne 'XML::Writer::_PrintChecker') {
464
      return $output;
465
    } else {
466
      return $output->{HANDLE};
467
    }
468
  };
469
 
470
  $self->{'SETOUTPUT'} = sub {
471
    my $newOutput = $_[0];
472
 
473
    if (defined($newOutput) && !ref($newOutput) && 'self' eq $newOutput ) {
474
      $newOutput = \$selfcontained_output;
475
      $use_selfcontained_output = 1;
476
    }
477
 
478
    if (ref($newOutput) eq 'SCALAR') {
479
      $output = XML::Writer::_String->new($newOutput);
480
    } else {
481
                                # If there is no OUTPUT parameter,
482
                                # use standard output
483
      $output = $newOutput || \*STDOUT;
484
      if ($outputEncoding && (ref($output) eq 'GLOB' || $output->isa('IO::Handle'))) {
485
        if (lc($outputEncoding) eq 'utf-8') {
486
          binmode($output, ':encoding(utf-8)');
487
        } elsif (lc($outputEncoding) eq 'us-ascii') {
488
          binmode($output, ':encoding(us-ascii)');
489
        } else {
490
          die 'The only supported encodings are utf-8 and us-ascii';
491
        }
492
      }
493
    }
494
 
495
    if ($params{CHECK_PRINT}) {
496
      $output = XML::Writer::_PrintChecker->new($output);
497
    }
498
  };
499
 
500
  $self->{OVERLOADSTRING} = sub {
501
      # if we don't use the self-contained output,
502
      # simple passthrough
503
      return $use_selfcontained_output ? $selfcontained_output : undef;
504
  };
505
 
506
  $self->{TOSTRING} = sub {
507
      die "'to_string' can only be used with self-contained output\n"
508
          unless $use_selfcontained_output;
509
 
510
      return $selfcontained_output;
511
  };
512
 
513
  $self->{'SETDATAMODE'} = sub {
514
    $dataMode = $_[0];
515
  };
516
 
517
  $self->{'GETDATAMODE'} = sub {
518
    return $dataMode;
519
  };
520
 
521
  $self->{'SETDATAINDENT'} = sub {
522
    if ($_[0] =~ /^\s*$/) {
523
      $dataIndent = $_[0];
524
    } else {
525
      $dataIndent = ' ' x $_[0];
526
    }
527
  };
528
 
529
  $self->{'GETDATAINDENT'} = sub {
530
    if ($dataIndent =~ /^ *$/) {
531
      return length($dataIndent);
532
    } else {
533
      return $dataIndent;
534
    }
535
  };
536
 
537
                                # Set the indent.
538
  &{$self->{'SETDATAINDENT'}}($params{'DATA_INDENT'} || '');
539
 
540
                                # Set the output.
541
  &{$self->{'SETOUTPUT'}}($params{'OUTPUT'});
542
 
543
                                # Return the blessed object.
544
  return bless $self, $class;
545
}
546
 
547
 
548
 
549
########################################################################
550
# Public methods
551
########################################################################
552
 
553
#
554
# Finish writing the document.
555
#
556
sub end {
557
  my $self = shift;
558
  &{$self->{END}};
559
}
560
 
561
#
562
# Write an XML declaration.
563
#
564
sub xmlDecl {
565
  my $self = shift;
566
  &{$self->{XMLDECL}};
567
}
568
 
569
#
570
# Write a processing instruction.
571
#
572
sub pi {
573
  my $self = shift;
574
  &{$self->{PI}};
575
}
576
 
577
#
578
# Write a comment.
579
#
580
sub comment {
581
  my $self = shift;
582
  &{$self->{COMMENT}};
583
}
584
 
585
#
586
# Write a DOCTYPE declaration.
587
#
588
sub doctype {
589
  my $self = shift;
590
  &{$self->{DOCTYPE}};
591
}
592
 
593
#
594
# Write a start tag.
595
#
596
sub startTag {
597
  my $self = shift;
598
  &{$self->{STARTTAG}};
599
}
600
 
601
#
602
# Write an empty tag.
603
#
604
sub emptyTag {
605
  my $self = shift;
606
  &{$self->{EMPTYTAG}};
607
}
608
 
609
#
610
# Write an end tag.
611
#
612
sub endTag {
613
  my $self = shift;
614
  &{$self->{ENDTAG}};
615
}
616
 
617
#
618
# Write a simple data element.
619
#
620
sub dataElement {
621
  my ($self, $name, $data, @atts) = (@_);
622
  $self->startTag($name, @atts);
623
  $self->characters($data);
624
  $self->endTag($name);
625
}
626
 
627
#
628
# Write a simple CDATA element.
629
#
630
sub cdataElement {
631
    my ($self, $name, $data, %atts) = (@_);
632
    $self->startTag($name, %atts);
633
    $self->cdata($data);
634
    $self->endTag($name);
635
}
636
 
637
#
638
# Write character data.
639
#
640
sub characters {
641
  my $self = shift;
642
  &{$self->{CHARACTERS}};
643
}
644
 
645
#
646
# Write raw, unquoted, completely unchecked character data.
647
#
648
sub raw {
649
  my $self = shift;
650
  &{$self->{RAW}};
651
}
652
 
653
#
654
# Write CDATA.
655
#
656
sub cdata {
657
    my $self = shift;
658
    &{$self->{CDATA}};
659
}
660
 
661
#
662
# Query the current element.
663
#
664
sub in_element {
665
  my $self = shift;
666
  return &{$self->{IN_ELEMENT}};
667
}
668
 
669
#
670
# Query the ancestors.
671
#
672
sub within_element {
673
  my $self = shift;
674
  return &{$self->{WITHIN_ELEMENT}};
675
}
676
 
677
#
678
# Get the name of the current element.
679
#
680
sub current_element {
681
  my $self = shift;
682
  return &{$self->{CURRENT_ELEMENT}};
683
}
684
 
685
#
686
# Get the name of the numbered ancestor (zero-based).
687
#
688
sub ancestor {
689
  my $self = shift;
690
  return &{$self->{ANCESTOR}};
691
}
692
 
693
#
694
# Get the current output destination.
695
#
696
sub getOutput {
697
  my $self = shift;
698
  return &{$self->{GETOUTPUT}};
699
}
700
 
701
 
702
#
703
# Set the current output destination.
704
#
705
sub setOutput {
706
  my $self = shift;
707
  return &{$self->{SETOUTPUT}};
708
}
709
 
710
#
711
# Set the current data mode (true or false).
712
#
713
sub setDataMode {
714
  my $self = shift;
715
  return &{$self->{SETDATAMODE}};
716
}
717
 
718
 
719
#
720
# Get the current data mode (true or false).
721
#
722
sub getDataMode {
723
  my $self = shift;
724
  return &{$self->{GETDATAMODE}};
725
}
726
 
727
 
728
#
729
# Set the current data indent step.
730
#
731
sub setDataIndent {
732
  my $self = shift;
733
  return &{$self->{SETDATAINDENT}};
734
}
735
 
736
 
737
#
738
# Get the current data indent step.
739
#
740
sub getDataIndent {
741
  my $self = shift;
742
  return &{$self->{GETDATAINDENT}};
743
}
744
 
745
 
746
#
747
# Empty stub.
748
#
749
sub addPrefix {
750
}
751
 
752
 
753
#
754
# Empty stub.
755
#
756
sub removePrefix {
757
}
758
 
759
sub to_string {
760
    my $self = shift;
761
 
762
    $self->{TOSTRING}->();
763
}
764
 
765
 
766
 
767
########################################################################
768
# Private functions.
769
########################################################################
770
 
771
#
772
# Private: check for duplicate attributes and bad characters.
773
# Note - this starts at $_[1], because $_[0] is assumed to be an
774
# element name.
775
#
776
sub _checkAttributes {
777
  my %anames;
778
  my $i = 1;
779
  while ($_[0]->[$i]) {
780
    my $name = $_[0]->[$i];
781
    $i += 1;
782
    if ($anames{$name}) {
783
      croak("Two attributes named \"$name\"");
784
    } else {
785
      $anames{$name} = 1;
786
    }
787
    _croakUnlessDefinedCharacters($_[0]->[$i]);
788
    $i += 1;
789
  }
790
}
791
 
792
#
793
# Private: escape an attribute value literal.
794
#
795
sub _escapeLiteral {
796
  my $data = $_[0];
797
  if ($data =~ /[\&\<\>\"]/) {
798
    $data =~ s/\&/\&amp\;/g;
799
    $data =~ s/\</\&lt\;/g;
800
    $data =~ s/\>/\&gt\;/g;
801
    $data =~ s/\"/\&quot\;/g;
802
  }
803
  return $data;
804
}
805
 
806
sub _escapeASCII($) {
807
  $_[0] =~ s/([^\x00-\x7F])/sprintf('&#x%X;', ord($1))/ge;
808
}
809
 
810
sub _croakUnlessASCII($) {
811
  if ($_[0] =~ /[^\x00-\x7F]/) {
812
    croak('Non-ASCII characters are not permitted in this part of a US-ASCII document');
813
  }
814
}
815
 
816
# Enforce XML 1.0, section 2.2's definition of "Char" (only reject low ASCII,
817
#  so as not to require Unicode support from perl)
818
sub _croakUnlessDefinedCharacters($) {
819
  if ($_[0] =~ /([\x00-\x08\x0B-\x0C\x0E-\x1F])/) {
820
    croak(sprintf('Code point \u%04X is not a valid character in XML', ord($1)));
821
  }
822
}
823
 
824
sub _overload_string {
825
    my $self = shift;
826
    $self->{OVERLOADSTRING}->() || overload::StrVal($self);
827
}
828
 
829
########################################################################
830
# XML::Writer::Namespaces - subclass for Namespace processing.
831
########################################################################
832
 
833
package XML::Writer::Namespaces;
834
use strict;
835
use vars qw(@ISA);
836
use Carp;
837
 
838
@ISA = qw(XML::Writer);
839
 
840
#
841
# Constructor
842
#
843
sub new {
844
  my ($class, %params) = (@_);
845
 
846
  my $unsafe = $params{UNSAFE};
847
 
848
                                # Snarf the prefix map, if any, and
849
                                # note the default prefix.
850
  my %prefixMap = ();
851
  if ($params{PREFIX_MAP}) {
852
    %prefixMap = (%{$params{PREFIX_MAP}});
853
    delete $params{PREFIX_MAP};
854
  }
855
  $prefixMap{'http://www.w3.org/XML/1998/namespace'} = 'xml';
856
 
857
                                # Generate the reverse map for URIs
858
  my $uriMap = {};
859
  my $key;
860
  foreach $key (keys(%prefixMap)) {
861
    $uriMap->{$prefixMap{$key}} = $key;
862
  }
863
 
864
  my $defaultPrefix = $uriMap->{''};
865
  delete $prefixMap{$defaultPrefix} if ($defaultPrefix);
866
 
867
                                # Create an instance of the parent.
868
  my $self = XML::Writer->new(%params);
869
 
870
                                # Snarf the parent's methods that we're
871
                                # going to override.
872
  my $OLD_startTag = $self->{STARTTAG};
873
  my $OLD_emptyTag = $self->{EMPTYTAG};
874
  my $OLD_endTag = $self->{ENDTAG};
875
 
876
                                # State variables
877
  my @stack;
878
  my $prefixCounter = 1;
879
  my $nsDecls = {'http://www.w3.org/XML/1998/namespace' => 'xml'};
880
  my $nsDefaultDecl = undef;
881
  my $nsCopyFlag = 0;
882
  my @forcedNSDecls = ();
883
 
884
  if ($params{FORCED_NS_DECLS}) {
885
    @forcedNSDecls = @{$params{FORCED_NS_DECLS}};
886
    delete $params{FORCED_NS_DECLS};
887
  }
888
 
889
  #
890
  # Push the current declaration state.
891
  #
892
  my $pushState = sub {
893
    push @stack, [$nsDecls, $nsDefaultDecl, $nsCopyFlag, $uriMap];
894
    $nsCopyFlag = 0;
895
  };
896
 
897
 
898
  #
899
  # Pop the current declaration state.
900
  #
901
  my $popState = sub {
902
    ($nsDecls, $nsDefaultDecl, $nsCopyFlag, $uriMap) = @{pop @stack};
903
  };
904
 
905
  #
906
  # Generate a new prefix.
907
  #
908
  my $genPrefix = sub {
909
    my $uri = $_[0];
910
    my $prefixCounter = 1;
911
    my $prefix = $prefixMap{$uri};
912
    my %clashMap = %{$uriMap};
913
    while( my ($u, $p) = each(%prefixMap)) {
914
      $clashMap{$p} = $u;
915
    }
916
 
917
    while (!defined($prefix) || ($clashMap{$prefix} && $clashMap{$prefix} ne $uri)) {
918
      $prefix = "__NS$prefixCounter";
919
      $prefixCounter++;
920
    }
921
 
922
    return $prefix;
923
  };
924
 
925
  #
926
  # Perform namespace processing on a single name.
927
  #
928
  my $processName = sub {
929
    my ($nameref, $atts, $attFlag) = (@_);
930
    my ($uri, $local) = @{$$nameref};
931
    my $prefix = $nsDecls->{$uri};
932
 
933
                                # Is this an element name that matches
934
                                # the default NS?
935
    if (!$attFlag && $defaultPrefix && ($uri eq $defaultPrefix)) {
936
      unless ($nsDefaultDecl && ($nsDefaultDecl eq $uri)) {
937
        push @{$atts}, 'xmlns';
938
        push @{$atts}, $uri;
939
        $nsDefaultDecl = $uri;
940
      }
941
      $$nameref = $local;
942
 
943
      if (defined($uriMap->{''})) {
944
        delete ($nsDecls->{$uriMap->{''}});
945
      }
946
 
947
      $nsDecls->{$uri} = '';
948
      unless ($nsCopyFlag) {
949
        $uriMap = {%{$uriMap}};
950
        $nsDecls = {%{$nsDecls}};
951
        $nsCopyFlag = 1;
952
      }
953
      $uriMap->{''} = $uri;
954
 
955
                                # Is there a straight-forward prefix?
956
    } elsif ($prefix) {
957
      $$nameref = "$prefix:$local";
958
    } else {
959
      $prefix = &{$genPrefix}($uri);
960
      unless ($nsCopyFlag) {
961
        $uriMap = {%{$uriMap}};
962
        $nsDecls = {%{$nsDecls}};
963
        $nsCopyFlag = 1;
964
      }
965
      $uriMap->{$prefix} = $uri;
966
      $nsDecls->{$uri} = $prefix;
967
      push @{$atts}, "xmlns:$prefix";
968
      push @{$atts}, $uri;
969
      $$nameref = "$prefix:$local";
970
    }
971
  };
972
 
973
 
974
  #
975
  # Perform namespace processing on element and attribute names.
976
  #
977
  my $nsProcess = sub {
978
    if (ref($_[0]->[0]) eq 'ARRAY') {
979
      my $x = \@{$_[0]->[0]};
980
      &{$processName}(\$x, $_[0], 0);
981
      splice(@{$_[0]}, 0, 1, $x);
982
    }
983
    my $i = 1;
984
    while ($_[0]->[$i]) {
985
      if (ref($_[0]->[$i]) eq 'ARRAY') {
986
        my $x = \@{$_[0]->[$i]};
987
        &{$processName}(\$x, $_[0], 1);
988
        splice(@{$_[0]}, $i, 1, $x);
989
      }
990
      $i += 2;
991
    }
992
 
993
    # We do this if any declarations are forced, due either to
994
    #  constructor arguments or to a call during processing.
995
    if (@forcedNSDecls) {
996
      foreach (@forcedNSDecls) {
997
        my @dummy = ($_, 'dummy');
998
        my $d2 = \@dummy;
999
        if ($defaultPrefix && ($_ eq $defaultPrefix)) {
1000
          &{$processName}(\$d2, $_[0], 0);
1001
        } else {
1002
          &{$processName}(\$d2, $_[0], 1);
1003
        }
1004
      }
1005
      @forcedNSDecls = ();
1006
    }
1007
  };
1008
 
1009
 
1010
  # Indicate that a namespace should be declared by the next open element
1011
  $self->{FORCENSDECL} = sub {
1012
    push @forcedNSDecls, $_[0];
1013
  };
1014
 
1015
 
1016
  #
1017
  # Start tag, with NS processing
1018
  #
1019
  $self->{STARTTAG} = sub {
1020
    my $name = $_[0];
1021
    unless ($unsafe) {
1022
      _checkNSNames(\@_);
1023
    }
1024
    &{$pushState}();
1025
    &{$nsProcess}(\@_);
1026
    &{$OLD_startTag};
1027
  };
1028
 
1029
 
1030
  #
1031
  # Empty tag, with NS processing
1032
  #
1033
  $self->{EMPTYTAG} = sub {
1034
    unless ($unsafe) {
1035
      _checkNSNames(\@_);
1036
    }
1037
    &{$pushState}();
1038
    &{$nsProcess}(\@_);
1039
    &{$OLD_emptyTag};
1040
    &{$popState}();
1041
  };
1042
 
1043
 
1044
  #
1045
  # End tag, with NS processing
1046
  #
1047
  $self->{ENDTAG} = sub {
1048
    my $name = $_[0];
1049
    if (ref($_[0]) eq 'ARRAY') {
1050
      my $pfx = $nsDecls->{$_[0]->[0]};
1051
      if ($pfx) {
1052
        $_[0] = $pfx . ':' . $_[0]->[1];
1053
      } else {
1054
        $_[0] = $_[0]->[1];
1055
      }
1056
    } else {
1057
      $_[0] = $_[0];
1058
    }
1059
#    &{$nsProcess}(\@_);
1060
    &{$OLD_endTag};
1061
    &{$popState}();
1062
  };
1063
 
1064
 
1065
  #
1066
  # Processing instruction, but only if not UNSAFE.
1067
  #
1068
  unless ($unsafe) {
1069
    my $OLD_pi = $self->{PI};
1070
    $self->{PI} = sub {
1071
      my $target = $_[0];
1072
      if (index($target, ':') >= 0) {
1073
        croak "PI target '$target' contains a colon.";
1074
      }
1075
      &{$OLD_pi};
1076
    }
1077
  };
1078
 
1079
 
1080
  #
1081
  # Add a prefix to the prefix map.
1082
  #
1083
  $self->{ADDPREFIX} = sub {
1084
    my ($uri, $prefix) = (@_);
1085
    if ($prefix) {
1086
      $prefixMap{$uri} = $prefix;
1087
    } else {
1088
      if (defined($defaultPrefix)) {
1089
        delete($prefixMap{$defaultPrefix});
1090
      }
1091
      $defaultPrefix = $uri;
1092
    }
1093
  };
1094
 
1095
 
1096
  #
1097
  # Remove a prefix from the prefix map.
1098
  #
1099
  $self->{REMOVEPREFIX} = sub {
1100
    my ($uri) = (@_);
1101
    if ($defaultPrefix && ($defaultPrefix eq $uri)) {
1102
      $defaultPrefix = undef;
1103
    }
1104
    delete $prefixMap{$uri};
1105
  };
1106
 
1107
 
1108
  #
1109
  # Bless and return the object.
1110
  #
1111
  return bless $self, $class;
1112
}
1113
 
1114
 
1115
#
1116
# Add a preferred prefix for a namespace URI.
1117
#
1118
sub addPrefix {
1119
  my $self = shift;
1120
  return &{$self->{ADDPREFIX}};
1121
}
1122
 
1123
 
1124
#
1125
# Remove a preferred prefix for a namespace URI.
1126
#
1127
sub removePrefix {
1128
  my $self = shift;
1129
  return &{$self->{REMOVEPREFIX}};
1130
}
1131
 
1132
 
1133
#
1134
# Check names.
1135
#
1136
sub _checkNSNames {
1137
  my $names = $_[0];
1138
  my $i = 1;
1139
  my $name = $names->[0];
1140
 
1141
                                # Check the element name.
1142
  if (ref($name) eq 'ARRAY') {
1143
    if (index($name->[1], ':') >= 0) {
1144
      croak("Local part of element name '" .
1145
            $name->[1] .
1146
            "' contains a colon.");
1147
    }
1148
  } elsif (index($name, ':') >= 0) {
1149
    croak("Element name '$name' contains a colon.");
1150
  }
1151
 
1152
                                # Check the attribute names.
1153
  while ($names->[$i]) {
1154
    my $name = $names->[$i];
1155
    if (ref($name) eq 'ARRAY') {
1156
      my $local = $name->[1];
1157
      if (index($local, ':') >= 0) {
1158
        croak "Local part of attribute name '$local' contains a colon.";
1159
      }
1160
    } else {
1161
      if ($name =~ /^xmlns/) {
1162
        croak "Attribute name '$name' begins with 'xmlns'";
1163
      } elsif (index($name, ':') >= 0) {
1164
        croak "Attribute name '$name' contains ':'";
1165
      }
1166
    }
1167
    $i += 2;
1168
  }
1169
}
1170
 
1171
sub forceNSDecl
1172
{
1173
  my $self = shift;
1174
  return &{$self->{FORCENSDECL}};
1175
}
1176
 
1177
 
1178
package XML::Writer::_String;
1179
 
1180
# Internal class, behaving sufficiently like an IO::Handle,
1181
#  that stores written output in a string
1182
#
1183
# Heavily inspired by Simon Oliver's XML::Writer::String
1184
 
1185
sub new
1186
{
1187
  my $class = shift;
1188
  my $scalar_ref = shift;
1189
  return bless($scalar_ref, $class);
1190
}
1191
 
1192
sub print
1193
{
1194
  ${(shift)} .= join('', @_);
1195
  return 1;
1196
}
1197
 
1198
 
1199
package XML::Writer::_PrintChecker;
1200
 
1201
use Carp;
1202
 
1203
sub new
1204
{
1205
  my $class = shift;
1206
  return bless({HANDLE => shift}, $class);
1207
}
1208
 
1209
sub print
1210
{
1211
  my $self = shift;
1212
  if ($self->{HANDLE}->print(shift)) {
1213
    return 1;
1214
  } else {
1215
    croak "Failed to write output: $!";
1216
  }
1217
}
1218
 
1219
1;
1220
__END__
1221
 
1222
########################################################################
1223
# POD Documentation
1224
########################################################################
1225
 
1226
=head1 NAME
1227
 
1228
XML::Writer - Perl extension for writing XML documents.
1229
 
1230
=head1 SYNOPSIS
1231
 
1232
  use XML::Writer;
1233
  use IO::File;
1234
 
1235
  my $output = IO::File->new(">output.xml");
1236
 
1237
  my $writer = XML::Writer->new(OUTPUT => $output);
1238
  $writer->startTag("greeting",
1239
                    "class" => "simple");
1240
  $writer->characters("Hello, world!");
1241
  $writer->endTag("greeting");
1242
  $writer->end();
1243
  $output->close();
1244
 
1245
 
1246
=head1 DESCRIPTION
1247
 
1248
XML::Writer is a helper module for Perl programs that write an XML
1249
document.  The module handles all escaping for attribute values and
1250
character data and constructs different types of markup, such as tags,
1251
comments, and processing instructions.
1252
 
1253
By default, the module performs several well-formedness checks to
1254
catch errors during output.  This behaviour can be extremely useful
1255
during development and debugging, but it can be turned off for
1256
production-grade code.
1257
 
1258
The module can operate either in regular mode in or Namespace
1259
processing mode.  In Namespace mode, the module will generate
1260
Namespace Declarations itself, and will perform additional checks on
1261
the output.
1262
 
1263
Additional support is available for a simplified data mode with no
1264
mixed content: newlines are automatically inserted around elements and
1265
elements can optionally be indented based as their nesting level.
1266
 
1267
 
1268
=head1 METHODS
1269
 
1270
=head2 Writing XML
1271
 
1272
=over 4
1273
 
1274
=item new([$params])
1275
 
1276
Create a new XML::Writer object:
1277
 
1278
  my $writer = XML::Writer->new(OUTPUT => $output, NEWLINES => 1);
1279
 
1280
Arguments are an anonymous hash array of parameters:
1281
 
1282
=over 4
1283
 
1284
=item OUTPUT
1285
 
1286
An object blessed into IO::Handle or one of its subclasses (such as IO::File),
1287
or a reference to a string, or any blessed object that has a print() method;
1288
if this parameter is not present, the module will write to standard output. If
1289
a string reference is passed, it will capture the generated XML (as a string;
1290
to get bytes use the C<Encode> module).
1291
 
1292
If the string I<self> is passed, the output will be captured internally by the
1293
object, and can be accessed via the C<to_string()> method, or by calling the
1294
object in a string context.
1295
 
1296
    my $writer = XML::Writer->new( OUTPUT => 'self' );
1297
 
1298
    $writer->dataElement( hello => 'world' );
1299
 
1300
    print $writer->to_string;  # outputs <hello>world</hello>
1301
    print "$writer";           # ditto
1302
 
1303
=item NAMESPACES
1304
 
1305
A true (1) or false (0, undef) value; if this parameter is present and
1306
its value is true, then the module will accept two-member array
1307
reference in the place of element and attribute names, as in the
1308
following example:
1309
 
1310
  my $rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
1311
  my $writer = XML::Writer->new(NAMESPACES => 1);
1312
  $writer->startTag([$rdfns, "Description"]);
1313
 
1314
The first member of the array is a namespace URI, and the second part
1315
is the local part of a qualified name.  The module will automatically
1316
generate appropriate namespace declarations and will replace the URI
1317
part with a prefix.
1318
 
1319
=item PREFIX_MAP
1320
 
1321
A hash reference; if this parameter is present and the module is
1322
performing namespace processing (see the NAMESPACES parameter), then
1323
the module will use this hash to look up preferred prefixes for
1324
namespace URIs:
1325
 
1326
 
1327
  my $rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
1328
  my $writer = XML::Writer->new(NAMESPACES => 1,
1329
                               PREFIX_MAP => {$rdfns => 'rdf'});
1330
 
1331
The keys in the hash table are namespace URIs, and the values are the
1332
associated prefixes.  If there is not a preferred prefix for the
1333
namespace URI in this hash, then the module will automatically
1334
generate prefixes of the form "__NS1", "__NS2", etc.
1335
 
1336
To set the default namespace, use '' for the prefix.
1337
 
1338
=item FORCED_NS_DECLS
1339
 
1340
An array reference; if this parameter is present, the document element
1341
will contain declarations for all the given namespace URIs.
1342
Declaring namespaces in advance is particularly useful when a large
1343
number of elements from a namespace are siblings, but don't share a direct
1344
ancestor from the same namespace.
1345
 
1346
=item NEWLINES
1347
 
1348
A true or false value; if this parameter is present and its value is
1349
true, then the module will insert an extra newline before the closing
1350
delimiter of start, end, and empty tags to guarantee that the document
1351
does not end up as a single, long line.  If the parameter is not
1352
present, the module will not insert the newlines.
1353
 
1354
=item UNSAFE
1355
 
1356
A true or false value; if this parameter is present and its value is
1357
true, then the module will skip most well-formedness error checking.
1358
If the parameter is not present, the module will perform the
1359
well-formedness error checking by default.  Turn off error checking at
1360
your own risk!
1361
 
1362
=item DATA_MODE
1363
 
1364
A true or false value; if this parameter is present and its value is
1365
true, then the module will enter a special data mode, inserting
1366
newlines automatically around elements and (unless UNSAFE is also
1367
specified) reporting an error if any element has both characters and
1368
elements as content.
1369
 
1370
=item DATA_INDENT
1371
 
1372
A numeric value or white space; if this parameter is present, it represents the
1373
indent step for elements in data mode (it will be ignored when not in
1374
data mode). If it is white space it will be repeated for each level of
1375
indentation.
1376
 
1377
=item ENCODING
1378
 
1379
A character encoding to use for the output; currently this must be one of
1380
'utf-8' or 'us-ascii'.
1381
If present, it will be used for the underlying character encoding and as the
1382
default in the XML declaration.
1383
All character data should be passed as Unicode strings when an encoding is
1384
set.
1385
 
1386
=item CHECK_PRINT
1387
 
1388
A true or false value; if this parameter is present and its value is
1389
true, all prints to the underlying output will be checked for success. Failures
1390
will cause a croak rather than being ignored.
1391
 
1392
=back
1393
 
1394
=item end()
1395
 
1396
Finish creating an XML document.  This method will check that the
1397
document has exactly one document element, and that all start tags are
1398
closed:
1399
 
1400
  $writer->end();
1401
 
1402
If I<OUTPUT> as been set to I<self>, C<end()> will return the generated
1403
document as well.
1404
 
1405
=item xmlDecl([$encoding, $standalone])
1406
 
1407
Add an XML declaration to the beginning of an XML document.  The
1408
version will always be "1.0".  If you provide a non-null encoding or
1409
standalone argument, its value will appear in the declaration (any
1410
non-null value for standalone except 'no' will automatically be
1411
converted to 'yes'). If not given here, the encoding will be taken from the
1412
ENCODING argument. Pass the empty string to suppress this behaviour.
1413
 
1414
  $writer->xmlDecl("UTF-8");
1415
 
1416
=item doctype($name, [$publicId, $systemId])
1417
 
1418
Add a DOCTYPE declaration to an XML document.  The declaration must
1419
appear before the beginning of the root element.  If you provide a
1420
publicId, you must provide a systemId as well, but you may provide
1421
just a system ID by passing 'undef' for the publicId.
1422
 
1423
  $writer->doctype("html");
1424
 
1425
=item comment($text)
1426
 
1427
Add a comment to an XML document.  If the comment appears outside the
1428
document element (either before the first start tag or after the last
1429
end tag), the module will add a carriage return after it to improve
1430
readability. In data mode, comments will be treated as empty tags:
1431
 
1432
  $writer->comment("This is a comment");
1433
 
1434
=item pi($target [, $data])
1435
 
1436
Add a processing instruction to an XML document:
1437
 
1438
  $writer->pi('xml-stylesheet', 'href="style.css" type="text/css"');
1439
 
1440
If the processing instruction appears outside the document element
1441
(either before the first start tag or after the last end tag), the
1442
module will add a carriage return after it to improve readability.
1443
 
1444
The $target argument must be a single XML name.  If you provide the
1445
$data argument, the module will insert its contents following the
1446
$target argument, separated by a single space.
1447
 
1448
=item startTag($name [, $aname1 => $value1, ...])
1449
 
1450
Add a start tag to an XML document.  Any arguments after the element
1451
name are assumed to be name/value pairs for attributes: the module
1452
will escape all '&', '<', '>', and '"' characters in the attribute
1453
values using the predefined XML entities:
1454
 
1455
  $writer->startTag('doc', 'version' => '1.0',
1456
                           'status' => 'draft',
1457
                           'topic' => 'AT&T');
1458
 
1459
All start tags must eventually have matching end tags.
1460
 
1461
=item emptyTag($name [, $aname1 => $value1, ...])
1462
 
1463
Add an empty tag to an XML document.  Any arguments after the element
1464
name are assumed to be name/value pairs for attributes (see startTag()
1465
for details):
1466
 
1467
  $writer->emptyTag('img', 'src' => 'portrait.jpg',
1468
                           'alt' => 'Portrait of Emma.');
1469
 
1470
=item endTag([$name])
1471
 
1472
Add an end tag to an XML document.  The end tag must match the closest
1473
open start tag, and there must be a matching and properly-nested end
1474
tag for every start tag:
1475
 
1476
  $writer->endTag('doc');
1477
 
1478
If the $name argument is omitted, then the module will automatically
1479
supply the name of the currently open element:
1480
 
1481
  $writer->startTag('p');
1482
  $writer->endTag();
1483
 
1484
=item dataElement($name, $data [, $aname1 => $value1, ...])
1485
 
1486
Print an entire element containing only character data.  This is
1487
equivalent to
1488
 
1489
  $writer->startTag($name [, $aname1 => $value1, ...]);
1490
  $writer->characters($data);
1491
  $writer->endTag($name);
1492
 
1493
=item characters($data)
1494
 
1495
Add character data to an XML document.  All '<', '>', and '&'
1496
characters in the $data argument will automatically be escaped using
1497
the predefined XML entities:
1498
 
1499
  $writer->characters("Here is the formula: ");
1500
  $writer->characters("a < 100 && a > 5");
1501
 
1502
You may invoke this method only within the document element
1503
(i.e. after the first start tag and before the last end tag).
1504
 
1505
In data mode, you must not use this method to add whitespace between
1506
elements.
1507
 
1508
=item raw($data)
1509
 
1510
Print data completely unquoted and unchecked to the XML document.  For
1511
example C<raw('<')> will print a literal < character.  This
1512
necessarily bypasses all well-formedness checking, and is therefore
1513
only available in unsafe mode.
1514
 
1515
This can sometimes be useful for printing entities which are defined
1516
for your XML format but the module doesn't know about, for example
1517
&nbsp; for XHTML.
1518
 
1519
=item cdata($data)
1520
 
1521
As C<characters()> but writes the data quoted in a CDATA section, that
1522
is, between <![CDATA[ and ]]>.  If the data to be written itself
1523
contains ]]>, it will be written as several consecutive CDATA
1524
sections.
1525
 
1526
=item cdataElement($name, $data [, $aname1 => $value1, ...])
1527
 
1528
As C<dataElement()> but the element content is written as one or more
1529
CDATA sections (see C<cdata()>).
1530
 
1531
=item setOutput($output)
1532
 
1533
Set the current output destination, as in the OUTPUT parameter for the
1534
constructor.
1535
 
1536
=item getOutput()
1537
 
1538
Return the current output destination, as in the OUTPUT parameter for
1539
the constructor.
1540
 
1541
=item setDataMode($mode)
1542
 
1543
Enable or disable data mode, as in the DATA_MODE parameter for the
1544
constructor.
1545
 
1546
=item getDataMode()
1547
 
1548
Return the current data mode, as in the DATA_MODE parameter for the
1549
constructor.
1550
 
1551
=item setDataIndent($step)
1552
 
1553
Set the indent step for data mode, as in the DATA_INDENT parameter for
1554
the constructor.
1555
 
1556
=item getDataIndent()
1557
 
1558
Return the indent step for data mode, as in the DATA_INDENT parameter
1559
for the constructor.
1560
 
1561
 
1562
=back
1563
 
1564
=head2 Querying XML
1565
 
1566
=over 4
1567
 
1568
=item in_element($name)
1569
 
1570
Return a true value if the most recent open element matches $name:
1571
 
1572
  if ($writer->in_element('dl')) {
1573
    $writer->startTag('dt');
1574
  } else {
1575
    $writer->startTag('li');
1576
  }
1577
 
1578
=item within_element($name)
1579
 
1580
Return a true value if any open element matches $name:
1581
 
1582
  if ($writer->within_element('body')) {
1583
    $writer->startTag('h1');
1584
  } else {
1585
    $writer->startTag('title');
1586
  }
1587
 
1588
=item current_element()
1589
 
1590
Return the name of the currently open element:
1591
 
1592
  my $name = $writer->current_element();
1593
 
1594
This is the equivalent of
1595
 
1596
  my $name = $writer->ancestor(0);
1597
 
1598
=item ancestor($n)
1599
 
1600
Return the name of the nth ancestor, where $n=0 for the current open
1601
element.
1602
 
1603
=back
1604
 
1605
 
1606
=head2 Additional Namespace Support
1607
 
1608
As of 0.510, these methods may be used while writing a document.
1609
 
1610
=over 4
1611
 
1612
=item addPrefix($uri, $prefix)
1613
 
1614
Add a preferred mapping between a Namespace URI and a prefix.  See
1615
also the PREFIX_MAP constructor parameter.
1616
 
1617
To set the default namespace, omit the $prefix parameter or set it to
1618
''.
1619
 
1620
=item removePrefix($uri)
1621
 
1622
Remove a preferred mapping between a Namespace URI and a prefix.
1623
 
1624
=item forceNSDecl($uri)
1625
 
1626
Indicate that a namespace declaration for this URI should be included
1627
with the next element to be started.
1628
 
1629
=back
1630
 
1631
 
1632
=head1 ERROR REPORTING
1633
 
1634
With the default settings, the XML::Writer module can detect several
1635
basic XML well-formedness errors:
1636
 
1637
=over 4
1638
 
1639
=item *
1640
 
1641
Lack of a (top-level) document element, or multiple document elements.
1642
 
1643
=item *
1644
 
1645
Unclosed start tags.
1646
 
1647
=item *
1648
 
1649
Misplaced delimiters in the contents of processing instructions or
1650
comments.
1651
 
1652
=item *
1653
 
1654
Misplaced or duplicate XML declaration(s).
1655
 
1656
=item *
1657
 
1658
Misplaced or duplicate DOCTYPE declaration(s).
1659
 
1660
=item *
1661
 
1662
Mismatch between the document type name in the DOCTYPE declaration and
1663
the name of the document element.
1664
 
1665
=item *
1666
 
1667
Mismatched start and end tags.
1668
 
1669
=item *
1670
 
1671
Attempts to insert character data outside the document element.
1672
 
1673
=item *
1674
 
1675
Duplicate attributes with the same name.
1676
 
1677
=back
1678
 
1679
During Namespace processing, the module can detect the following
1680
additional errors:
1681
 
1682
=over 4
1683
 
1684
=item *
1685
 
1686
Attempts to use PI targets or element or attribute names containing a
1687
colon.
1688
 
1689
=item *
1690
 
1691
Attempts to use attributes with names beginning "xmlns".
1692
 
1693
=back
1694
 
1695
To ensure full error detection, a program must also invoke the end
1696
method when it has finished writing a document:
1697
 
1698
  $writer->startTag('greeting');
1699
  $writer->characters("Hello, world!");
1700
  $writer->endTag('greeting');
1701
  $writer->end();
1702
 
1703
This error reporting can catch many hidden bugs in Perl programs that
1704
create XML documents; however, if necessary, it can be turned off by
1705
providing an UNSAFE parameter:
1706
 
1707
  my $writer = XML::Writer->new(OUTPUT => $output, UNSAFE => 1);
1708
 
1709
=head2 PRINTING OUTPUT
1710
 
1711
If I<OUTPUT> has been set to I<self> and the object has been called in
1712
a string context, it'll return the xml document.
1713
 
1714
=over 4
1715
 
1716
=item to_string
1717
 
1718
If I<OUTPUT> has been set to I<self>, calls an implicit C<end()> on the
1719
document and prints it. Dies if I<OUTPUT> has been set to anything else.
1720
 
1721
=back
1722
 
1723
=head1 AUTHOR
1724
 
1725
David Megginson E<lt>david@megginson.comE<gt>
1726
 
1727
 
1728
=head1 COPYRIGHT AND LICENSE
1729
 
1730
Copyright (c) 1999 by Megginson Technologies.
1731
 
1732
Copyright (c) 2003 Ed Avis E<lt>ed@membled.comE<gt>
1733
 
1734
Copyright (c) 2004-2010 Joseph Walton E<lt>joe@kafsemo.orgE<gt>
1735
 
1736
Redistribution and use in source and compiled forms, with or without
1737
modification, are permitted under any circumstances.  No warranty.
1738
 
1739
=head1 SEE ALSO
1740
 
1741
XML::Parser
1742
 
1743
=cut