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   147769 use strict;
  4         22  
  4         137  
13 4     4   21 use warnings;
  4         8  
  4         124  
14              
15 4     4   671 use XML::LibXML;
  4         10  
  4         41  
16 4     4   2342 use XML::NamespaceSupport;
  4         11112  
  4         146  
17              
18 4     4   32 use vars qw ($VERSION);
  4         8  
  4         7428  
19              
20             sub CLONE_SKIP {
21 0 0   0   0 return $XML::LibXML::__threads_shared ? 0 : 1;
22             }
23              
24             $VERSION = "2.0207"; # VERSION TEMPLATE: DO NOT CHANGE
25              
26             sub new {
27 6     6 0 5115 my $class = shift;
28 6         27 return bless {@_}, $class;
29             }
30              
31 1     1 0 33 sub result { $_[0]->{LAST_DOM}; }
32              
33             sub done {
34 98     98 0 234 my ($self) = @_;
35 98         164 my $dom = $self->{DOM};
36 98 100       196 $dom = $self->{Parent} unless defined $dom; # this is for parsing document chunks
37              
38 98         393 delete $self->{NamespaceStack};
39 98         259 delete $self->{Parent};
40 98         188 delete $self->{DOM};
41              
42 98         278 $self->{LAST_DOM} = $dom;
43              
44 98         211 return $dom;
45             }
46              
47       69 0   sub set_document_locator {
48             }
49              
50             sub start_dtd {
51 9     9 0 130 my ($self, $dtd) = @_;
52 9 50 33     97 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 494 my ($self, $doc) = @_;
63 71         370 $self->{DOM} = XML::LibXML::Document->createDocument();
64              
65 71 100       205 if ( defined $self->{Encoding} ) {
66 1   50     10 $self->xml_decl({Version => ($self->{Version} || '1.0') , Encoding => $self->{Encoding}});
67             }
68              
69 71         219 $self->{NamespaceStack} = XML::NamespaceSupport->new;
70 71         1293 $self->{NamespaceStack}->push_context;
71 71         740 $self->{Parent} = undef;
72 71         359 return ();
73             }
74              
75             sub xml_decl {
76 70     70 0 350 my $self = shift;
77 70         95 my $decl = shift;
78              
79 70 50       146 if ( defined $decl->{Version} ) {
80 70         389 $self->{DOM}->setVersion( $decl->{Version} );
81             }
82 70 100       150 if ( defined $decl->{Encoding} ) {
83 3         16 $self->{DOM}->setEncoding( $decl->{Encoding} );
84             }
85 70         820 return ();
86             }
87              
88             sub end_document {
89 97     97 0 450 my ($self, $doc) = @_;
90 97         209 my $d = $self->done();
91 97         355 return $d;
92             }
93              
94             sub start_prefix_mapping {
95 18     18 0 121 my $self = shift;
96 18         28 my $ns = shift;
97              
98 18 100 100     80 unless ( defined $self->{DOM} or defined $self->{Parent} ) {
99 4         20 $self->{Parent} = XML::LibXML::DocumentFragment->new();
100 4         17 $self->{NamespaceStack} = XML::NamespaceSupport->new;
101 4         75 $self->{NamespaceStack}->push_context;
102             }
103              
104 18         67 $self->{USENAMESPACESTACK} = 1;
105              
106 18         63 $self->{NamespaceStack}->declare_prefix( $ns->{Prefix}, $ns->{NamespaceURI} );
107 18         680 return ();
108             }
109              
110              
111             sub end_prefix_mapping {
112 18     18 0 114 my $self = shift;
113 18         30 my $ns = shift;
114 18         61 $self->{NamespaceStack}->undeclare_prefix( $ns->{Prefix} );
115 18         583 return ();
116             }
117              
118              
119             sub start_element {
120 142     142 0 1045 my ($self, $el) = @_;
121 142         197 my $node;
122              
123 142 100 100     419 unless ( defined $self->{DOM} or defined $self->{Parent} ) {
124 14         73 $self->{Parent} = XML::LibXML::DocumentFragment->new();
125 14         49 $self->{NamespaceStack} = XML::NamespaceSupport->new;
126 14         301 $self->{NamespaceStack}->push_context;
127             }
128              
129 142 100       437 if ( defined $self->{Parent} ) {
130 71   100     251 $el->{NamespaceURI} ||= "";
131             $node = $self->{Parent}->addNewChild( $el->{NamespaceURI},
132 71         442 $el->{Name} );
133             }
134             else {
135 71 100       126 if ($el->{NamespaceURI}) {
136 8 50       27 if ( defined $self->{DOM} ) {
137             $node = $self->{DOM}->createRawElementNS($el->{NamespaceURI},
138 8         105 $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       121 if ( defined $self->{DOM} ) {
148 63         360 $node = $self->{DOM}->createRawElement($el->{Name});
149             }
150             else {
151 0         0 $node = XML::LibXML::Element->new( $el->{Name} );
152             }
153             }
154              
155 71         242 $self->{DOM}->setDocumentElement($node);
156             }
157              
158             # build namespaces
159 142         246 my $skip_ns= 0;
160 142         386 foreach my $p ( $self->{NamespaceStack}->get_declared_prefixes() ) {
161 18         149 $skip_ns= 1;
162 18         47 my $uri = $self->{NamespaceStack}->get_uri($p);
163 18         180 my $nodeflag = 0;
164 18 100 33     194 if ( defined $uri
      66        
165             and defined $el->{NamespaceURI}
166             and $uri eq $el->{NamespaceURI} ) {
167             # $nodeflag = 1;
168 11         26 next;
169             }
170 7         33 $node->setNamespace($uri, $p, 0 );
171             }
172              
173 142         1105 $self->{Parent} = $node;
174              
175 142         383 $self->{NamespaceStack}->push_context;
176              
177             # do attributes
178 142         1414 foreach my $key (keys %{$el->{Attributes}}) {
  142         388  
179 62         116 my $attr = $el->{Attributes}->{$key};
180 62 50       127 if (ref($attr)) {
181             # catch broken name/value pairs
182 62 50       160 next unless $attr->{Name} ;
183             next if $self->{USENAMESPACESTACK}
184             and ( $attr->{Name} eq "xmlns"
185             or ( defined $attr->{Prefix}
186 62 100 100     269 and $attr->{Prefix} eq "xmlns" ) );
      100        
187              
188              
189 44 100 66     183 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         22 my $uri = $attr->{Value};
193             $node->setNamespace($uri,
194             $attr->{LocalName},
195 14 100       38 $uri eq $el->{NamespaceURI} ? 1 : 0 );
196             }
197             else {
198             $node->setAttributeNS($attr->{NamespaceURI} || "",
199 30   100     146 $attr->{Name}, $attr->{Value});
200             }
201             }
202             else {
203 0         0 $node->setAttribute($key => $attr);
204             }
205             }
206 142         1302 return ();
207             }
208              
209             sub end_element {
210 142     142 0 1025 my ($self, $el) = @_;
211 142 50       375 return unless $self->{Parent};
212              
213 142         422 $self->{NamespaceStack}->pop_context;
214 142         1805 $self->{Parent} = $self->{Parent}->parentNode();
215 142         1080 return ();
216             }
217              
218             sub start_cdata {
219 11     11 0 75 my $self = shift;
220 11         21 $self->{IN_CDATA} = 1;
221 11         53 return ();
222             }
223              
224             sub end_cdata {
225 11     11 0 67 my $self = shift;
226 11         29 $self->{IN_CDATA} = 0;
227 11         98 return ();
228             }
229              
230             sub characters {
231 109     109 0 1205 my ($self, $chars) = @_;
232 109 100 100     282 if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
233 7         34 $self->{Parent} = XML::LibXML::DocumentFragment->new();
234 7         27 $self->{NamespaceStack} = XML::NamespaceSupport->new;
235 7         131 $self->{NamespaceStack}->push_context;
236             }
237 109 50       466 return unless $self->{Parent};
238 109         160 my $node;
239              
240 109 50 33     385 unless ( defined $chars and defined $chars->{Data} ) {
241 0         0 return;
242             }
243              
244 109 100 100     262 if ( defined $self->{DOM} ) {
    100          
245 90 100 100     242 if ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
246 5         39 $node = $self->{DOM}->createCDATASection($chars->{Data});
247             }
248             else {
249 85         399 $node = $self->{Parent}->appendText($chars->{Data});
250 85         724 return;
251             }
252             }
253             elsif ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
254 6         39 $node = XML::LibXML::CDATASection->new($chars->{Data});
255             }
256             else {
257 13         64 $node = XML::LibXML::Text->new($chars->{Data});
258             }
259              
260 24         127 $self->{Parent}->addChild($node);
261 24         219 return ();
262             }
263              
264             sub comment {
265 14     14 0 82 my ($self, $chars) = @_;
266 14         24 my $comment;
267 14 100 100     48 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         38 $self->{NamespaceStack}->push_context;
271             }
272              
273 14 100 66     74 unless ( defined $chars and defined $chars->{Data} ) {
274 3         29 return;
275             }
276              
277 11 100       23 if ( defined $self->{DOM} ) {
278 5         34 $comment = $self->{DOM}->createComment( $chars->{Data} );
279             }
280             else {
281 6         29 $comment = XML::LibXML::Comment->new( $chars->{Data} );
282             }
283              
284 11 100       33 if ( defined $self->{Parent} ) {
285 8         43 $self->{Parent}->addChild($comment);
286             }
287             else {
288 3         18 $self->{DOM}->addChild($comment);
289             }
290 11         155 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__