1 # $Id: Builder.pm 785 2009-07-16 14:17:46Z pajas $
3 # This is free software, you may use it and distribute it under the same terms as
6 # Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas
10 package XML::LibXML::SAX::Builder;
13 use XML::NamespaceSupport;
15 use vars qw ($VERSION);
18 return $XML::LibXML::__threads_shared ? 0 : 1;
21 $VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE
25 return bless {@_}, $class;
28 sub result { $_[0]->{LAST_DOM}; }
32 my $dom = $self->{DOM};
33 $dom = $self->{Parent} unless defined $dom; # this is for parsing document chunks
35 delete $self->{NamespaceStack};
36 delete $self->{Parent};
39 $self->{LAST_DOM} = $dom;
44 sub set_document_locator {
48 my ($self, $dtd) = @_;
49 if (defined $dtd->{Name} and
50 (defined $dtd->{SystemId} or defined $dtd->{PublicId})) {
51 $self->{DOM}->createExternalSubset($dtd->{Name},$dtd->{PublicId},$dtd->{SystemId});
59 my ($self, $doc) = @_;
60 $self->{DOM} = XML::LibXML::Document->createDocument();
62 if ( defined $self->{Encoding} ) {
63 $self->xml_decl({Version => ($self->{Version} || '1.0') , Encoding => $self->{Encoding}});
66 $self->{NamespaceStack} = XML::NamespaceSupport->new;
67 $self->{NamespaceStack}->push_context;
68 $self->{Parent} = undef;
76 if ( defined $decl->{Version} ) {
77 $self->{DOM}->setVersion( $decl->{Version} );
79 if ( defined $decl->{Encoding} ) {
80 $self->{DOM}->setEncoding( $decl->{Encoding} );
86 my ($self, $doc) = @_;
87 my $d = $self->done();
91 sub start_prefix_mapping {
95 unless ( defined $self->{DOM} or defined $self->{Parent} ) {
96 $self->{Parent} = XML::LibXML::DocumentFragment->new();
97 $self->{NamespaceStack} = XML::NamespaceSupport->new;
98 $self->{NamespaceStack}->push_context;
101 $self->{USENAMESPACESTACK} = 1;
103 $self->{NamespaceStack}->declare_prefix( $ns->{Prefix}, $ns->{NamespaceURI} );
108 sub end_prefix_mapping {
111 $self->{NamespaceStack}->undeclare_prefix( $ns->{Prefix} );
117 my ($self, $el) = @_;
120 unless ( defined $self->{DOM} or defined $self->{Parent} ) {
121 $self->{Parent} = XML::LibXML::DocumentFragment->new();
122 $self->{NamespaceStack} = XML::NamespaceSupport->new;
123 $self->{NamespaceStack}->push_context;
126 if ( defined $self->{Parent} ) {
127 $el->{NamespaceURI} ||= "";
128 $node = $self->{Parent}->addNewChild( $el->{NamespaceURI},
132 if ($el->{NamespaceURI}) {
133 if ( defined $self->{DOM} ) {
134 $node = $self->{DOM}->createRawElementNS($el->{NamespaceURI},
138 $node = XML::LibXML::Element->new( $el->{Name} );
139 $node->setNamespace( $el->{NamespaceURI},
144 if ( defined $self->{DOM} ) {
145 $node = $self->{DOM}->createRawElement($el->{Name});
148 $node = XML::LibXML::Element->new( $el->{Name} );
152 $self->{DOM}->setDocumentElement($node);
157 foreach my $p ( $self->{NamespaceStack}->get_declared_prefixes() ) {
159 my $uri = $self->{NamespaceStack}->get_uri($p);
162 and defined $el->{NamespaceURI}
163 and $uri eq $el->{NamespaceURI} ) {
167 $node->setNamespace($uri, $p, 0 );
170 $self->{Parent} = $node;
172 $self->{NamespaceStack}->push_context;
175 foreach my $key (keys %{$el->{Attributes}}) {
176 my $attr = $el->{Attributes}->{$key};
178 # catch broken name/value pairs
179 next unless $attr->{Name} ;
180 next if $self->{USENAMESPACESTACK}
181 and ( $attr->{Name} eq "xmlns"
182 or ( defined $attr->{Prefix}
183 and $attr->{Prefix} eq "xmlns" ) );
186 if ( defined $attr->{Prefix}
187 and $attr->{Prefix} eq "xmlns" and $skip_ns == 0 ) {
188 # ok, the generator does not set namespaces correctly!
189 my $uri = $attr->{Value};
190 $node->setNamespace($uri,
192 $uri eq $el->{NamespaceURI} ? 1 : 0 );
195 $node->setAttributeNS($attr->{NamespaceURI} || "",
196 $attr->{Name}, $attr->{Value});
200 $node->setAttribute($key => $attr);
207 my ($self, $el) = @_;
208 return unless $self->{Parent};
210 $self->{NamespaceStack}->pop_context;
211 $self->{Parent} = $self->{Parent}->parentNode();
217 $self->{IN_CDATA} = 1;
223 $self->{IN_CDATA} = 0;
228 my ($self, $chars) = @_;
229 if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
230 $self->{Parent} = XML::LibXML::DocumentFragment->new();
231 $self->{NamespaceStack} = XML::NamespaceSupport->new;
232 $self->{NamespaceStack}->push_context;
234 return unless $self->{Parent};
237 unless ( defined $chars and defined $chars->{Data} ) {
241 if ( defined $self->{DOM} ) {
242 if ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
243 $node = $self->{DOM}->createCDATASection($chars->{Data});
246 $node = $self->{Parent}->appendText($chars->{Data});
250 elsif ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
251 $node = XML::LibXML::CDATASection->new($chars->{Data});
254 $node = XML::LibXML::Text->new($chars->{Data});
257 $self->{Parent}->addChild($node);
262 my ($self, $chars) = @_;
264 if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
265 $self->{Parent} = XML::LibXML::DocumentFragment->new();
266 $self->{NamespaceStack} = XML::NamespaceSupport->new;
267 $self->{NamespaceStack}->push_context;
270 unless ( defined $chars and defined $chars->{Data} ) {
274 if ( defined $self->{DOM} ) {
275 $comment = $self->{DOM}->createComment( $chars->{Data} );
278 $comment = XML::LibXML::Comment->new( $chars->{Data} );
281 if ( defined $self->{Parent} ) {
282 $self->{Parent}->addChild($comment);
285 $self->{DOM}->addChild($comment);
290 sub processing_instruction {
291 my ( $self, $pi ) = @_;
293 return unless defined $self->{DOM};
294 $PI = $self->{DOM}->createPI( $pi->{Target}, $pi->{Data} );
296 if ( defined $self->{Parent} ) {
297 $self->{Parent}->addChild( $PI );
300 $self->{DOM}->addChild( $PI );
308 # fill $@ but do not die seriously
309 eval { $error->throw; };
315 delete $self->{NamespaceStack};
316 delete $self->{Parent};
324 delete $self->{NamespaceStack};
325 delete $self->{Parent};