Skip to content

Commit a49e891

Browse files
committed
Add new xml option to constructor
This allows using the XML tag without having to define strict conformance. This allows us to use XML::Generator like so: use XML::Generator; my $gen = XML::Generator->new('conformance' => loose, xml => { version => "1.0", enconding => 'UTF-8'); $gen->xml($gen->foo); which returns <?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo /> Signed-off-by: Wesley Schwengle <waterkip@cpan.org>
1 parent 4171530 commit a49e891

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

lib/XML/Generator.pm

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,12 @@ Sets the default encoding for use in XML declarations.
435435
Specify the dtd. The value should be an array reference with three
436436
values; the type, the name and the uri.
437437
438+
=head2 xml
439+
440+
This is an hash ref value that should contain the version, encoding and dtd
441+
values (same as above). This is used in case C<conformance> is set to C<loose>,
442+
but you still want to use the xml declaration or prolog.
443+
438444
=head1 IMPORT ARGUMENTS
439445
440446
use XML::Generator ':option';
@@ -620,6 +626,10 @@ sub new {
620626
$options{'escape'} = 0;
621627
}
622628

629+
if ($options{'xml'} && ref $options{'xml'} ne 'HASH') {
630+
Carp::croak("XML arguments must be a hash");
631+
}
632+
623633
if (ref $options{'namespace'} eq 'ARRAY') {
624634
if (@{ $options{'namespace'} } > 2 && (@{ $options{'namespace'} } % 2) != 0) {
625635
Carp::croak "odd number of arguments for namespace";
@@ -768,23 +778,38 @@ explicitly provide undef as the value.
768778
769779
=cut
770780

781+
sub _allow_xml_cmd {
782+
my $this = shift;
783+
return 1 if $this->{conformance} eq 'strict';
784+
return 1 if defined $this->{xml};
785+
return 0;
786+
}
787+
788+
771789
sub xmldecl {
772-
my($this, @args) = @_;
790+
my $this = shift;
773791

774-
return $this->XML::Generator::util::tag('xmldecl', @_)
775-
unless $this->{conformance} eq 'strict';
792+
return $this->XML::Generator::util::tag('xmldecl', @_) unless $this->{conformance} eq 'strict';
793+
return $this->_xmldecl(@_);
794+
}
795+
796+
sub _xmldecl {
797+
my $this = shift;
798+
my @args = @_;
776799

777-
my $version = $this->{'version'} || '1.0';
800+
return unless $this->_allow_xml_cmd;
801+
802+
my $version = $this->{xml}{version} // $this->{'version'} || '1.0';
778803

779804
# there's no explicit support for encodings yet, but at the
780805
# least we can know to put it in the declaration
781-
my $encoding = $this->{'encoding'};
806+
my $encoding = $this->{xml}{encoding} // $this->{'encoding'};
782807

783808
# similarly, although we don't do anything with DTDs yet, we
784809
# recognize a 'dtd' => [ ... ] option to the constructor, and
785810
# use it to create a <!DOCTYPE ...> and to indicate that this
786811
# document can't stand alone.
787-
my $doctype = $this->xmldtd($this->{dtd});
812+
my $doctype = $this->xmldtd($this->{xml}{dtd} // $this->{dtd});
788813
my $standalone = $doctype ? "no" : "yes";
789814

790815
for (my $i = 0; $i < $#args; $i += 2) {
@@ -807,12 +832,9 @@ sub xmldecl {
807832
$version ||= '';
808833
$standalone ||= '';
809834

810-
my $xml = "<?xml$version$encoding$standalone?>";
811-
$xml .= "\n$doctype" if $doctype;
812-
813-
$xml = "$xml\n";
814-
815-
return $xml;
835+
my @xml = ("<?xml$version$encoding$standalone?>");
836+
push(@xml, $doctype) if $doctype;
837+
return join("\n", @xml, "");
816838
}
817839

818840
=head2 xmldtd
@@ -883,7 +905,7 @@ sub xml {
883905
my $this = shift;
884906

885907
return $this->XML::Generator::util::tag('xml', @_)
886-
unless $this->{conformance} eq 'strict';
908+
unless $this->_allow_xml_cmd;
887909

888910
unless (@_) {
889911
Carp::croak "usage: object->xml( (COMMENT | PI)* XML (COMMENT | PI)* )";
@@ -903,7 +925,7 @@ sub xml {
903925
}
904926
}
905927

906-
return XML::Generator::final->new([$this->xmldecl(), @_]);
928+
return XML::Generator::final->new([$this->_xmldecl(), @_]);
907929
}
908930

909931
=head1 CREATING A SUBCLASS

t/Generator.t

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use Test;
44
use utf8;
55

6-
BEGIN { $| = 1; plan tests => 105; }
6+
BEGIN { $| = 1; plan tests => 108; }
77

88
use XML::Generator ();
99
ok(1);
@@ -90,6 +90,7 @@ ok($xml, '<!-- test -->');
9090
$x = new XML::Generator 'conformance' => 'strict',
9191
'version' => '1.1',
9292
'encoding' => 'iso-8859-2';
93+
9394
$xml = $x->xmldecl();
9495
ok($xml, qq(<?xml version="1.1" encoding="iso-8859-2" standalone="yes"?>\n));
9596

@@ -137,6 +138,41 @@ $xml = $x->foo(['bar' => 'bam'], {'baz:foo' => 'qux', 'fob' => 'gux'});
137138
ok($xml eq '<bar:foo xmlns:bar="bam" baz:foo="qux" fob="gux" />' ||
138139
$xml eq '<bar:foo xmlns:bar="bam" fob="gux" baz:foo="qux" />', 1, $xml);
139140

141+
$x = XML::Generator->new(
142+
conformance => 'loose',
143+
xml => { version => "1.0", encoding => 'UTF-8' },
144+
);
145+
146+
ok(
147+
$x->xml($x->foo),
148+
join("\n",
149+
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
150+
'<foo />'),
151+
"Correct XML tag"
152+
);
153+
154+
$x = XML::Generator->new(
155+
conformance => 'loose',
156+
xml => { version => "1.0", encoding => 'UTF-8', dtd => [ 'foo' ] },
157+
);
158+
159+
ok(
160+
$x->xml($x->foo),
161+
join("\n",
162+
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>',
163+
'<!DOCTYPE foo>',
164+
'<foo />'),
165+
"Correct XML tag with doctype"
166+
);
167+
168+
eval {
169+
XML::Generator->new(
170+
conformance => 'loose',
171+
xml => [],
172+
);
173+
};
174+
ok $@ =~ qr/XML arguments must be a hash/;
175+
140176
$x = new XML::Generator;
141177
$xml = $x->xml();
142178
ok($xml, '<xml />');

0 commit comments

Comments
 (0)