File Coverage

blib/lib/XML/Filter/RemoveEmpty.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             XML::Filter::RemoveEmpty - Filter out tags with no character data
4              
5             =cut
6              
7             package XML::Filter::RemoveEmpty;
8              
9 2     2   44882 use strict;
  2         6  
  2         76  
10 2     2   10 use warnings;
  2         4  
  2         60  
11              
12 2     2   9 use base qw(XML::SAX::Base);
  2         8  
  2         2927  
13              
14 2     2   53781 use Alias 'attr';
  0            
  0            
15             use Text::Trim;
16             use XML::Filter::BufferText;
17             $Alias::AttrPrefix = "main::";
18              
19             use enum qw(EMPTY FULL);
20              
21             =head1 VERSION
22              
23             Version 0.02
24              
25             =cut
26              
27             our $VERSION = '0.02';
28              
29             =head1 SYNOPSIS
30              
31             Removes tags which contain neither character data nor descendants containing
32             character data. Considers whitespace meaningless by default and trims it, but
33             can preserve it; defaults to removing comments, but this can also be changed.
34              
35             use XML::Filter::RemoveEmpty;
36             use XML::SAX::Machines qw( :all );
37              
38             my $filter = XML::Filter::RemoveEmpty->new(
39             Comments => 'strip' # (default)
40             # or Comments => 'preserve', # (NOT WORKING)
41             TrimWhitespace => 'only' # (only removes ws-only data)
42             # or
43             # TrimWhitespace => 'always'
44             # (default - always trims leading and trailing whitespace)
45             );
46              
47             my $machine = Pipeline( $filter => \*STDOUT );
48              
49             $machine->parse_file(\*STDIN);
50              
51             =head1 METHODS
52              
53             Overrides new(), start_element(), end_element(), characters(), and comment()
54             from L.
55              
56             =over 4
57              
58             =item new
59              
60             Takes a list of key-value pairs for configuration (see SYNOPSIS).
61              
62             =cut
63              
64             sub new {
65             my $type = shift;
66             my %defaults = (
67             TrimWhitespace => 'always',
68             Comments => 'strip',
69             );
70             my %args = @_;
71             my %force = (
72             Comments => 'strip',
73             Handler => XML::Filter::BufferText->new,
74             );
75             $type->SUPER::new(%defaults, %args, %force);
76             }
77              
78             =item start_element
79              
80             See L
81              
82             =cut
83              
84             sub start_element {
85             my $self = attr shift;
86             my ($data) = @_;
87             my $val = {
88             data => $data,
89             status => EMPTY
90             };
91             push @::stack, $val;
92             }
93              
94             =item end_element
95              
96             See L
97              
98             =cut
99              
100             sub end_element {
101             my $self = attr shift;
102             my $top = $::stack[-1];
103             if ($top->{status} == FULL or $top->{printed}) {
104             $self->_print_stack(@::stack);
105             $self->SUPER::end_element($top->{data});
106             }
107             pop @::stack;
108             }
109              
110             =item characters
111              
112             See L
113              
114             =cut
115              
116             sub characters {
117             # We assume we have been passed all character data at once (use other
118             # modules to acheive this effect)
119             my $self = attr shift;
120             my ($data) = @_;
121             my $td = $self->_handle_text($data->{Data});
122             # Can't just check value because we might preserve only whitespace
123             if (length $td) {
124             # FIXME: Doesn't preserve mixed order of mixed-type tags
125             $::stack[-1]->{characters}{Data} = $td;
126             $::stack[-1]->{status} = FULL;
127             }
128             }
129              
130             =item comment
131              
132             See L
133              
134             =cut
135              
136             sub comment {
137             my $self = shift;
138             $self->{Comments} eq 'preserve' and $self->SUPER::comment(@_)
139             }
140              
141             =item _print_stack
142              
143             Called when character data encountered; generates SAX events for pending tags
144              
145             =cut
146              
147             sub _print_stack {
148             my ($self, @stack) = @_;
149             return unless @stack;
150             my $bottom = shift @stack;
151             unless ($bottom->{printed}) {
152             $self->SUPER::start_element($bottom->{data});
153             $self->SUPER::characters($bottom->{characters});
154             $bottom->{printed}++;
155             }
156             $self->_print_stack(@stack);
157             }
158              
159             =item _handle_text
160              
161             Does string manipulation depending on trim settings
162              
163             =cut
164              
165             sub _handle_text {
166             my $self = attr shift;
167             local $_ = defined $_[0] ? $_[0] : "";
168             (defined $_ && length $_)
169             ? ($::TrimWhitespace eq 'only' and s/^\s*$//, $_)
170             || trim($_)
171             : "";
172            
173             }
174              
175             =back
176              
177             =head1 BUGS
178              
179             May not preserve the content ordering of mixed-content tags (a tag with both
180             character data and other tags within it). Specifically, all character data in a
181             particular tag will be printed together before any inner tags are printed.
182              
183             Comments are currently always stripped because of a weakness in implmentation.
184              
185             Please report any bugs or feature requests to
186             C, or through the web interface at
187             L.
188             I will be notified, and then you'll automatically be notified of progress on
189             your bug as I make changes.
190              
191             =head1 SUPPORT
192              
193             You can find documentation for this module with the perldoc command.
194              
195             perldoc XML::Filter::RemoveEmpty
196              
197             You can also look for information at:
198              
199             =over 4
200              
201             =item * AnnoCPAN: Annotated CPAN documentation
202              
203             L
204              
205             =item * CPAN Ratings
206              
207             L
208              
209             =item * RT: CPAN's request tracker
210              
211             L
212              
213             =item * Search CPAN
214              
215             L
216              
217             =back
218              
219             =head1 ACKNOWLEDGEMENTS
220              
221             L, whose SYNOPSIS I stole.
222              
223             =head1 AUTHOR
224              
225             Darren Kulp, C<< >>
226              
227             =head1 COPYRIGHT & LICENSE
228              
229             Copyright 2006 Darren Kulp, all rights reserved.
230              
231             This program is free software; you can redistribute it and/or modify it
232             under the same terms as Perl itself.
233              
234             =cut
235              
236             1;
237              
238             __END__