File Coverage

blib/lib/XML/Filter/GenericChunk.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package XML::Filter::GenericChunk;
2              
3             # $Id: GenericChunk.pm,v 1.8 2002/03/14 09:20:53 cb13108 Exp $
4              
5 2     2   6024 use strict;
  2         6  
  2         77  
6 2     2   9 use warnings;
  2         3  
  2         54  
7              
8 2     2   2840 use XML::LibXML;
  0            
  0            
9             use XML::LibXML::SAX::Parser;
10             use XML::SAX::Base;
11              
12             # this is done because of mod_perl!
13             $XML::Filter::GenericChunk::VERSION = '0.07';
14             @XML::Filter::GenericChunk::ISA = qw( XML::SAX::Base );
15              
16             sub new {
17             my $class = shift;
18             my $self = $class->SUPER::new(@_);
19              
20             $self->{TagName} ||= [];
21             $self->{RelaxedNames} ||= 0;
22             $self->{NamespaceURI} ||= "";
23             $self->{TagByName} = {};
24             # $self->{DropElement} = 0;
25              
26             $self->_prepare_names();
27              
28             return $self;
29             }
30              
31             sub start_document {
32             my $self = shift;
33              
34             $self->{WBChunk} = "";
35             $self->{CurrentElement} = "";
36             $self->{DropElement} ||= 0;
37              
38             $self->SUPER::start_document(@_);
39             }
40              
41             sub start_element {
42             my $self = shift;
43             my $element = shift;
44             $self->_init_element($element);
45              
46             unless ( $self->is_tag() and $self->{DropElement} == 1 ) {
47             $self->SUPER::start_element($element);
48             }
49             }
50              
51             sub end_element {
52             my $self = shift;
53             my $element = shift;
54              
55             # need to remember if this is the active tag, because after reset this
56             # information is not available anymore
57             my $istag = $self->is_tag();
58              
59             $self->_reset_element($element);
60             $self->reset_data();
61              
62             unless ( $istag and $self->{DropElement} == 1 ) {
63             $self->SUPER::end_element($element);
64             }
65             }
66              
67             sub relaxed_names {
68             my $self = shift;
69             if ( scalar @_ && defined $_[0] ) {
70             $self->{RelaxedNames} = shift;
71             }
72             return $self->{RelaxedNames};
73             }
74              
75             sub set_tagname {
76             my $self = shift;
77             push @{$self->{TagName}}, @_;
78             $self->_prepare_names();
79             }
80              
81             sub set_namespace {
82             my $self = shift;
83             my $uri = shift;
84             $self->{NamespaceURI} = $uri if defined $uri;
85             }
86              
87             sub reset_tagname {
88             my $self = shift;
89             $self->{TagName} = [];
90             $self->{TagByName} = {};
91             }
92              
93             sub is_tag {
94             return length $_[0]->{CurrentElement} > 0 ? 1 : 0;
95             }
96              
97             sub flush_chunk {
98             my $self = shift;
99              
100             my $docfrag = $self->get_data_fragment();
101             if ( defined $docfrag and defined $docfrag->childNodes() ) {
102             # TODO: check if there are any namespaces to be fixed!
103              
104             my $saxparser = XML::LibXML::SAX::Parser->new( Handler => $self->{Handler} );
105             foreach my $node ( $docfrag->childNodes() ) {
106             $saxparser->process_node( $node );
107             }
108             }
109             }
110              
111             sub get_data_fragment {
112             my $self = shift;
113             return undef unless length $self->{WBChunk};
114              
115             my $docfrag = undef;
116             my $parser = XML::LibXML->new();
117              
118             eval {
119             if ( defined $self->{Encoding} ) {
120             $docfrag = $parser->parse_xml_chunk( $self->get_data,
121             $self->{Encoding} );
122             }
123             else {
124             $docfrag = $parser->parse_xml_chunk( $self->get_data );
125             }
126             };
127              
128             $self->reset_data;
129              
130             if ( $@ ) {
131             die "brocken chunk\n" . $@;
132             }
133              
134             return $docfrag;
135             }
136              
137             sub add_data {
138             my $self = shift;
139             foreach my $s ( @_ ) {
140             $self->{WBChunk} .= $s if defined $s;
141             }
142             }
143              
144             sub get_data { $_[0]->{WBChunk}; }
145             sub reset_data { $_[0]->{WBChunk} = ""; }
146              
147             sub _prepare_names {
148             my $self = shift;
149             # this precaches the tagnames
150             map {$self->{TagByName}->{$_} = 1;} @{$self->{TagName}};
151             }
152              
153             sub _init_element {
154             my $self = shift;
155             my $element = shift;
156              
157             unless( length $self->{CurrentElement} > 0 ) {
158             # in this case we test the entire name!
159             my $name = "";
160             if ( $self->relaxed_names() == 1 ) {
161             $name = $element->{Name};
162             if ( defined $name and exists $self->{TagByName}->{$name} ) {
163             $self->{CurrentElement} = $name;
164             return;
165             }
166              
167             }
168             elsif ( length $self->{NamespaceURI} ) {
169             return unless defined $element->{NamespaceURI}
170             and $self->{NamespaceURI} eq $element->{NamespaceURI};
171             }
172              
173             $name = $element->{LocalName};
174              
175             if ( defined $name and exists $self->{TagByName}->{$name} ) {
176             $self->{CurrentElement} = $name;
177             }
178             }
179             }
180              
181             sub _reset_element {
182             my $self = shift;
183             my $element = shift;
184              
185             if ( $self->is_tag() ) {
186             my $name = "";
187             if ( $self->relaxed_names() == 1) {
188             $name = $element->{Name};
189             if ( defined $name
190             and defined $self->{CurrentElement}
191             and $self->{CurrentElement} eq $name ) {
192             $self->{CurrentElement} = "";
193             return;
194             }
195             }
196             elsif ( length $self->{NamespaceURI} ) {
197             return unless defined $element->{NamespaceURI}
198             and $self->{NamespaceURI} eq $element->{NamespaceURI};
199             }
200              
201             $name = $element->{LocalName};
202              
203             if ( defined $name
204             and defined $self->{CurrentElement}
205             and $self->{CurrentElement} eq $name ) {
206             $self->{CurrentElement} = "";
207             }
208             }
209             }
210              
211             1;
212             __END__