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