Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | =pod |
2 | ||
3 | =head1 NAME | |
4 | ||
5 | SVG::XML - Handle the XML generation bits for SVG.pm | |
6 | ||
7 | =head1 AUTHOR | |
8 | ||
9 | Ronan Oger, ronan@roasp.com | |
10 | ||
11 | =head1 SEE ALSO | |
12 | ||
13 | perl(1),L<SVG>,L<SVG::XML>,L<SVG::Element>,L<SVG::Parser>, L<SVG::Manual> | |
14 | http://www.roasp.com/ | |
15 | http://www.perlsvg.com/ | |
16 | http://www.roitsystems.com/ | |
17 | http://www.w3c.org/Graphics/SVG/ | |
18 | ||
19 | =cut | |
20 | ||
21 | package SVG::XML; | |
22 | use strict; | |
23 | use vars qw($VERSION @ISA @EXPORT ); | |
24 | ||
25 | $VERSION = "2.26"; | |
26 | ||
27 | require Exporter; | |
28 | @ISA = qw(Exporter); | |
29 | @EXPORT = qw( | |
30 | xmlescp | |
31 | cssstyle | |
32 | xmlattrib | |
33 | xmlcomment | |
34 | xmlpi | |
35 | xmltag | |
36 | xmltagopen | |
37 | xmltagclose | |
38 | xmltag_ln | |
39 | xmltagopen_ln | |
40 | xmltagclose_ln | |
41 | processtag | |
42 | xmldecl | |
43 | dtddecl | |
44 | ); | |
45 | ||
46 | sub xmlescp ($) { | |
47 | my $s=shift; | |
48 | $s = '0' unless defined $s; | |
49 | $s=join(', ',@{$s}) if(ref($s) eq 'ARRAY'); | |
50 | $s=~s/&(?!#(x\w\w|\d+?);)/&/g; | |
51 | $s=~s/>/>/g; | |
52 | $s=~s/</</g; | |
53 | $s=~s/\"/"/g; | |
54 | $s=~s/\'/'/g; | |
55 | $s=~s/\`/'/g; | |
56 | $s=~s/([\x00-\x1f])/sprintf('&#x%02X;',chr($1))/eg; | |
57 | #per suggestion from Adam Schneider | |
58 | $s=~s/([\200-\377])/'&#'.ord($1).';'/ge; | |
59 | ||
60 | return $s; | |
61 | } | |
62 | ||
63 | sub cssstyle { | |
64 | my %attrs=@_; | |
65 | return(join('; ',map { qq($_: ).$attrs{$_} } keys(%attrs))); | |
66 | } | |
67 | ||
68 | # Per suggestion from Adam Schneider | |
69 | #sub xmlattrib { | |
70 | # my %attrs=@_; | |
71 | # return(join(' ',map { qq($_=").$attrs{$_}.q(") } keys(%attrs))); | |
72 | #} | |
73 | ||
74 | sub xmlattrib { | |
75 | my %attrs=@_; | |
76 | return(join(' ',map { qq($_=").xmlescp($attrs{$_}).q(") } keys(%attrs))); | |
77 | } | |
78 | ||
79 | sub xmltag ($$;@) { | |
80 | my ($name,$ns,%attrs)=@_; | |
81 | $ns=$ns?"$ns:":''; | |
82 | my $at=' '.xmlattrib(%attrs)||''; | |
83 | return qq(<$ns$name$at />); | |
84 | } | |
85 | ||
86 | sub xmltag_ln ($$;@) { | |
87 | my ($name,$ns,%attrs)=@_; | |
88 | return xmltag($name,$ns,%attrs); | |
89 | } | |
90 | ||
91 | sub xmltagopen ($$;@) { | |
92 | my ($name,$ns,%attrs)=@_; | |
93 | $ns=$ns?"$ns:":''; | |
94 | my $at=' '.xmlattrib(%attrs)||''; | |
95 | return qq(<$ns$name$at>); | |
96 | } | |
97 | ||
98 | sub xmltagopen_ln ($$;@) { | |
99 | my ($name,$ns,%attrs)=@_; | |
100 | return xmltagopen($name,$ns,%attrs); | |
101 | } | |
102 | ||
103 | sub xmlcomment ($$) { | |
104 | my ($self,$r_comment) = @_; | |
105 | my $ind = $self->{-docref}->{-elsep}.$self->{-docref}->{-indent} x $self->{-docref}->{-level}; | |
106 | return(join($ind,map { qq(<!-- $_ -->)} @$r_comment)); | |
107 | } | |
108 | ||
109 | sub xmlpi ($$) { | |
110 | my ($self,$r_pi) = @_; | |
111 | my $ind = $self->{-docref}->{-elsep}.$self->{-docref}->{-indent} x $self->{-docref}->{-level}; | |
112 | return(join($ind,map { qq(<?$_?>)} @$r_pi)); | |
113 | } | |
114 | ||
115 | *processinginstruction=\&xmlpi; | |
116 | ||
117 | sub xmltagclose ($$) { | |
118 | my ($name,$ns)=@_; | |
119 | $ns=$ns?"$ns:":''; | |
120 | return qq(</$ns$name>); | |
121 | } | |
122 | ||
123 | sub xmltagclose_ln ($$) { | |
124 | my ($name,$ns)=@_; | |
125 | return xmltagclose($name,$ns); | |
126 | } | |
127 | ||
128 | sub dtddecl ($) { | |
129 | my $self = shift; | |
130 | my $docroot = $self->{-docroot} || 'svg'; | |
131 | my $id; | |
132 | ||
133 | if ($self->{-pubid}) { | |
134 | $id = 'PUBLIC "'.$self->{-pubid}.'"'; | |
135 | $id .= ' "'.$self->{-sysid}.'"' if ($self->{-sysid}); | |
136 | } elsif ( | |
137 | $self->{-sysid}) { | |
138 | $id = 'SYSTEM "'.$self->{-sysid}.'"'; | |
139 | } else { | |
140 | $id = 'PUBLIC "-//W3C//DTD SVG 1.0//EN"' . | |
141 | $self->{-docref}->{-elsep}. | |
142 | "\"$self->{-docref}->{-dtd}\"" | |
143 | } | |
144 | ||
145 | my $at=join(' ',($docroot, $id)); | |
146 | ||
147 | #>>>TBD: add internal() method to return this | |
148 | my $extension = (exists $self->{-internal})?$self->{-internal}->render():""; | |
149 | if (exists $self->{-extension} and $self->{-extension}) { | |
150 | $extension .= $self->{-docref}{-elsep}. | |
151 | $self->{-extension}. | |
152 | $self->{-docref}{-elsep}; | |
153 | } | |
154 | $extension = " [".$self->{-docref}{-elsep}.$extension."]" if $extension; | |
155 | ||
156 | return qq[<!DOCTYPE $at$extension>]; | |
157 | } | |
158 | ||
159 | sub xmldecl ($) { | |
160 | my $self = shift; | |
161 | ||
162 | my $version= $self->{-version} || '1.0'; | |
163 | my $encoding = $self->{-encoding} || 'UTF-8'; | |
164 | my $standalone = $self->{-standalone} ||'yes'; | |
165 | ||
166 |