File Coverage

blib/lib/XML/LibXML/SAX/Builder.pm
Criterion Covered Total %
statement 138 169 81.6
branch 47 62 75.8
condition 41 54 75.9
subroutine 22 27 81.4
pod 0 21 0.0
total 248 333 74.4


line stmt bran cond sub pod time code
1             # $Id$
2             #
3             # This is free software, you may use it and distribute it under the same terms as
4             # Perl itself.
5             #
6             # Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas
7             #
8             #
9              
10             package XML::LibXML::SAX::Builder;
11              
12 4     4   129439 use strict;
  4         20  
  4         107  
13 4     4   18 use warnings;
  4         5  
  4         93  
14              
15 4     4   672 use XML::LibXML;
  4         10  
  4         31  
16 4     4   1913 use XML::NamespaceSupport;
  4         8744  
  4         125  
17              
18 4     4   29 use vars qw ($VERSION);
  4         8  
  4         6220  
19              
20             sub CLONE_SKIP {
21 0 0   0   0 return $XML::LibXML::__threads_shared ? 0 : 1;
22             }
23              
24             $VERSION = "2.0208"; # VERSION TEMPLATE: DO NOT CHANGE
25              
26             sub new {
27 6     6 0 4698 my $class = shift;
28 6         36 return bless {@_}, $class;
29             }
30              
31 1     1 0 40 sub result { $_[0]->{LAST_DOM}; }
32              
33             sub done {
34 98     98 0 186 my ($self) = @_;
35 98         130 my $dom = $self->{DOM};
36 98 100       185 $dom = $self->{Parent} unless defined $dom; # this is for parsing document chunks
37              
38 98         323 delete $self->{NamespaceStack};
39 98         224 delete $self->{Parent};
40 98         120 delete $self->{DOM};
41              
42 98         224 $self->{LAST_DOM} = $dom;
43              
44 98         482 return $dom;
45             }
46              
47       69 0   sub set_document_locator {
48             }
49              
50             sub start_dtd {
51 9     9 0 84 my ($self, $dtd) = @_;
52 9 50 33     82 if (defined $dtd->{Name} and
      33        
53             (defined $dtd->{SystemId} or defined $dtd->{PublicId})) {
54 0         0 $self->{DOM}->createExternalSubset($dtd->{Name},$dtd->{PublicId},$dtd->{SystemId});
55             }
56             }
57              
58       9 0   sub end_dtd {
59             }
60              
61             sub start_document {
62 71     71 0 426 my ($self, $doc) = @_;
63 71         306 $self->{DOM} = XML::LibXML::Document->createDocument();
64              
65 71 100       156 if ( defined $self->{Encoding} ) {
66 1   50     6 $self->xml_decl({Version => ($self->{Version} || '1.0') , Encoding => $self->{Encoding}});
67             }
68              
69 71         208 $self->{NamespaceStack} = XML::NamespaceSupport->new;
70 71         1077 $self->{NamespaceStack}->push_context;
71 71         634 $self->{Parent} = undef;
72 71         300 return ();
73             }
74              
75             sub xml_decl {
76 70     70 0 279 my $self = shift;
77 70         98 my $decl = shift;
78              
79 70 50       124 if ( defined $decl->{Version} ) {
80 70         235 $self->{DOM}->setVersion( $decl->{Version} );
81             }
82 70 100       123 if ( defined $decl->{Encoding} ) {
83 3         13 $self->{DOM}->setEncoding( $decl->{Encoding} );
84             }
85 70         734 return ();
86             }
87              
88             sub end_document {
89 97     97 0 378 my ($self, $doc) = @_;
90 97         171 my $d = $self->done();
91 97         279 return $d;
92             }
93              
94             sub start_prefix_mapping {
95 18     18 0 92 my $self = shift;
96 18         27 my $ns = shift;
97              
98 18 100 100     70 unless ( defined $self->{DOM} or defined $self->{Parent} ) {
99 4         22 $self->{Parent} = XML::LibXML::DocumentFragment->new();
100 4         12 $self->{NamespaceStack} = XML::NamespaceSupport->new;
101 4         64 $self->{NamespaceStack}->push_context;
102             }
103              
104 18         57 $self->{USENAMESPACESTACK} = 1;
105              
106 18         51 $self->{NamespaceStack}->declare_prefix( $ns->{Prefix}, $ns->{NamespaceURI} );
107 18         601 return ();
108             }
109              
110              
111             sub end_prefix_mapping {
112 18     18 0 98 my $self = shift;
113 18         22 my $ns = shift;
114 18         52 $self->{NamespaceStack}->undeclare_prefix( $ns->{Prefix} );
115 18         498 return ();
116             }
117              
118              
119             sub start_element {
120 142     142 0 876 my ($self, $el) = @_;
121 142         157 my $node;
122              
123 142 100 100     385 unless ( defined $self->{DOM} or defined $self->{Parent} ) {
124 14         64 $self->{Parent} = XML::LibXML::DocumentFragment->new();
125 14         42 $self->{NamespaceStack} = XML::NamespaceSupport->new;
126 14         228 $self->{NamespaceStack}->push_context;
127             }
128              
129 142 100       384 if ( defined $self->{Parent} ) {
130 71   100     204 $el->{NamespaceURI} ||= "";
131             $node = $self->{Parent}->addNewChild( $el->{NamespaceURI},
132 71         364 $el->{Name} );
133             }
134             else {
135 71 100       130 if ($el->{NamespaceURI}) {
136 8 50       19 if ( defined $self->{DOM} ) {
137             $node = $self->{DOM}->createRawElementNS($el->{NamespaceURI},
138 8         97 $el->{Name});
139             }
140             else {
141 0         0 $node = XML::LibXML::Element->new( $el->{Name} );
142             $node->setNamespace( $el->{NamespaceURI},
143 0         0 $el->{Prefix} , 1 );
144             }
145             }
146             else {
147 63 50       99 if ( defined $self->{DOM} ) {
148 63         300 $node = $self->{DOM}->createRawElement($el->{Name});
149             }
150             else {
151 0         0 $node = XML::LibXML::Element->new( $el->{Name} );
152             }
153             }
154              
155 71         195 $self->{DOM}->setDocumentElement($node);
156             }
157              
158             # build namespaces
159 142         221 my $skip_ns= 0;
160 142         323 foreach my $p ( $self->{NamespaceStack}->get_declared_prefixes() ) {
161 18         123 $skip_ns= 1;
162 18         38 my $uri = $self->{NamespaceStack}->get_uri($p);
163 18         173 my $nodeflag = 0;
164 18 100 33     84 if ( defined $uri
      66        
165             and defined $el->{NamespaceURI}
166             and $uri eq $el->{NamespaceURI} ) {
167             # $nodeflag = 1;
168 11         25 next;
169             }
170 7         19 $node->setNamespace($uri, $p, 0 );
171             }
172              
173 142         919 $self->{Parent} = $node;
174              
175 142         326 $self->{NamespaceStack}->push_context;
176              
177             # do attributes
178 142         1197 foreach my $key (keys %{$el->{Attributes}}) {
  142         341  
179 62         88 my $attr = $el->{Attributes}->{$key};
180 62 50       112 if (ref($attr)) {
181             # catch broken name/value pairs
182 62 50       98 next unless $attr->{Name} ;
183             next if $self->{USENAMESPACESTACK}
184             and ( $attr->{Name} eq "xmlns"
185             or ( defined $attr->{Prefix}
186 62 100 100     229 and $attr->{Prefix} eq "xmlns" ) );
      100        
187              
188              
189 44 100 66     157 if ( defined $attr->{Prefix}
      66        
190             and $attr->{Prefix} eq "xmlns" and $skip_ns == 0 ) {
191             # ok, the generator does not set namespaces correctly!
192 14         18 my $uri = $attr->{Value};
193             $node->setNamespace($uri,
194             $attr->{LocalName},
195 14 100       41 $uri eq $el->{NamespaceURI} ? 1 : 0 );
196             }
197             else {
198             $node->setAttributeNS($attr->{NamespaceURI} || "",
199 30   100     115 $attr->{Name}, $attr->{Value});
200             }
201             }
202             else {
203 0         0 $node->setAttribute($key => $attr);
204             }
205             }
206 142         1168 return ();
207             }
208              
209             sub end_element {
210 142     142 0 853 my ($self, $el) = @_;
211 142 50       319 return unless $self->{Parent};
212              
213 142         347 $self->{NamespaceStack}->pop_context;
214 142         1439 $self->{Parent} = $self->{Parent}->parentNode();
215 142         941 return ();
216             }
217              
218             sub start_cdata {
219 11     11 0 61 my $self = shift;
220 11         17 $self->{IN_CDATA} = 1;
221 11         52 return ();
222             }
223              
224             sub end_cdata {
225 11     11 0 56 my $self = shift;
226 11         18 $self->{IN_CDATA} = 0;
227 11         90 return ();
228             }
229              
230             sub characters {
231 109     109 0 960 my ($self, $chars) = @_;
232 109 100 100     234 if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
233 7         31 $self->{Parent} = XML::LibXML::DocumentFragment->new();
234 7         22 $self->{NamespaceStack} = XML::NamespaceSupport->new;
235 7         110 $self->{NamespaceStack}->push_context;
236             }
237 109 50       413 return unless $self->{Parent};
238 109         135 my $node;
239              
240 109 50 33     373 unless ( defined $chars and defined $chars->{Data} ) {
241 0         0 return;
242             }
243              
244 109 100 100     200 if ( defined $self->{DOM} ) {
    100          
245 90 100 100     214 if ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
246 5         28 $node = $self->{DOM}->createCDATASection($chars->{Data});
247             }
248             else {
249 85         357 $node = $self->{Parent}->appendText($chars->{Data});
250 85         634 return;
251             }
252             }
253             elsif ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
254 6         25 $node = XML::LibXML::CDATASection->new($chars->{Data});
255             }
256             else {
257 13         58 $node = XML::LibXML::Text->new($chars->{Data});
258             }
259              
260 24         113 $self->{Parent}->addChild($node);
261 24         184 return ();
262             }
263              
264             sub comment {
265 14     14 0 74 my ($self, $chars) = @_;
266 14         17 my $comment;
267 14 100 100     41 if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
268 2         12 $self->{Parent} = XML::LibXML::DocumentFragment->new();
269 2         8 $self->{NamespaceStack} = XML::NamespaceSupport->new;
270 2         33 $self->{NamespaceStack}->push_context;
271             }
272              
273 14 100 66     62 unless ( defined $chars and defined $chars->{Data} ) {
274 3         16 return;
275             }
276              
277 11 100       20 if ( defined $self->{DOM} ) {
278 5         30 $comment = $self->{DOM}->createComment( $chars->{Data} );
279             }
280             else {
281 6         25 $comment = XML::LibXML::Comment->new( $chars->{Data} );
282             }
283              
284 11 100       25 if ( defined $self->{Parent} ) {
285 8         34 $self->{Parent}->addChild($comment);
286             }
287             else {
288 3         24 $self->{DOM}->addChild($comment);
289             }
290 11         105 return ();
291             }
292              
293             sub processing_instruction {
294 0     0 0   my ( $self, $pi ) = @_;
295 0           my $PI;
296 0 0         return unless defined $self->{DOM};
297 0           $PI = $self->{DOM}->createPI( $pi->{Target}, $pi->{Data} );
298              
299 0 0         if ( defined $self->{Parent} ) {
300 0           $self->{Parent}->addChild( $PI );
301             }
302             else {
303 0           $self->{DOM}->addChild( $PI );
304             }
305 0           return ();
306             }
307              
308             sub warning {
309 0     0 0   my $self = shift;
310 0           my $error = shift;
311             # fill $@ but do not die seriously
312 0           eval { $error->throw; };
  0            
313             }
314              
315             sub error {
316 0     0 0   my $self = shift;
317 0           my $error = shift;
318 0           delete $self->{NamespaceStack};
319 0           delete $self->{Parent};
320 0           delete $self->{DOM};
321 0           $error->throw;
322             }
323              
324             sub fatal_error {
325 0     0 0   my $self = shift;
326 0           my $error = shift;
327 0           delete $self->{NamespaceStack};
328 0           delete $self->{Parent};
329 0           delete $self->{DOM};
330 0           $error->throw;
331             }
332              
333             1;
334              
335             __END__