Skip to content

Commit 4690b33

Browse files
authored
Merge pull request #2 from waterkip/GL-xml-decl-with_instantion
Add new xml option to constructor
2 parents 4171530 + a49e891 commit 4690b33

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)