File Coverage

blib/lib/Text/FakeXML.pm
Criterion Covered Total %
statement 71 78 91.0
branch 21 30 70.0
condition 0 2 0.0
subroutine 15 17 88.2
pod 6 13 46.1
total 113 140 80.7


line stmt bran cond sub pod time code
1             #! perl
2              
3             package Text::FakeXML;
4              
5 10     10   57802 use 5.008;
  10         38  
  10         464  
6 10     10   58 use warnings;
  10         19  
  10         314  
7 10     10   51 use strict;
  10         21  
  10         370  
8 10     10   83 use Carp;
  10         20  
  10         14813  
9              
10             =head1 NAME
11              
12             Text::FakeXML - Creating text with EthingsE.
13              
14             =head1 VERSION
15              
16             Version 0.02
17              
18             =cut
19              
20             our $VERSION = '0.02';
21              
22              
23             =head1 SYNOPSIS
24              
25             Many applications use XML-style data, e.g., for configuration.
26             However, very often this data is not 'real' XML, but just text with
27             some XML-like markups. Therefore is it not necessary to pull in the
28             whole vast XML machinery to create these files. A simple 'fake' module
29             is sufficient.
30              
31             For example, consider this real-life config file for eye-of-gnome:
32              
33            
34            
35            
36             440x350+1063+144
37            
38            
39              
40             This doesn't require anything fancy:
41              
42             use Text::FakeXML;
43             my $cfg = Text::FakeXML->new(version => "1.0");
44             $cfg->xml_elt_open("gconf");
45             $cfg->xml_elt("entry", name => "geometry_collection",
46             mtime => "1164190071", type => "string");
47             $cfg->xml_elt("stringvalue", "440x350+1063+144" );
48             $cfg->xml_elt_close("gconf");
49              
50             =head1 METHODS
51              
52             =head2 new
53              
54             Constructor. Takes an optional series of key/value pairs:
55              
56             =over 4
57              
58             =item fh
59              
60             The file handle where to write the output to. If not specified, the
61             currently selected file handle is used.
62              
63             =item version
64              
65             If specified, a leading C<< >> is emitted.
66              
67             =item indent
68              
69             Indentation for each level of tags. Must be a string (e.g., two spaces
70             C<< " " >>) or a number that indicates the desired number of spaces.
71             Default is two spaces.
72              
73             =item level
74              
75             The starting level of indentation. Defaults to zero.
76              
77             =back
78              
79             Example:
80              
81             my $o = Text::FakeXML::new version => '1.0';
82              
83             =cut
84              
85             sub new {
86 10     10 1 19104 my ($pkg, %args) = @_;
87 10         89 my $self = bless
88             {
89             _level => 0,
90             _indent => " ",
91             _fh => select,
92             }, $pkg;
93              
94 10         22 my $version;
95             my $encoding;
96 10 50       110 if ( exists $args{fh} ) {
97 10         80 $self->{_fh} = delete $args{fh};
98             }
99 10 100       46 if ( exists $args{version} ) {
100 1         4 $version = delete $args{version};
101             }
102 10 50       65 if ( exists $args{encoding} ) {
103 0         0 $encoding = delete $args{encoding};
104 0   0     0 $version ||= '1.0';
105             }
106 10 100       43 if ( exists $args{indent} ) {
107 2         5 $self->{_indent} = delete $args{indent};
108 2 100       15 $self->{_indent} = " " x $self->{_indent}
109             if $self->{_indent} =~ /^\d+$/;
110             }
111 10 100       39 if ( exists $args{level} ) {
112 3         8 $self->{_level} = delete $args{level};
113             }
114              
115 10 50       38 croak(__PACKAGE__, ": Unhandled constructor attributes: ",
116             join(" ", sort keys %args))
117             if %args;
118              
119 10 100       33 if ( $version ) {
120 1 50       9 $self->print("
121             $encoding ? " encoding='$encoding'" : "",
122             "?>\n");
123             }
124              
125 10         37 $self;
126             }
127              
128 22     22 1 120 sub indent { $_[0]->{_indent} x $_[0]->{_level} }
129 7     7 0 19 sub indent_incr { $_[0]->{_level}++ }
130 6     6 0 13 sub indent_decr { $_[0]->{_level}-- }
131 0     0 0 0 sub indent_init { $_[0]->{_level} = 0 }
132              
133             sub print {
134 23     23 0 62 my ($self, @args) = @_;
135 23         75 my $fh = select($self->{_fh});
136 23         74 print(@args);
137 23         113 select($fh);
138             }
139              
140             sub printi {
141 22     22 0 63 my ($self, @args) = @_;
142 22         69 $self->print($self->indent, @args);
143             }
144              
145             =head2 xml_elt_open
146              
147             Emits the opening tag for a new element.
148             First argument is the name of the element. It may
149             be followed by a series of key/value pairs that will be used as
150             attributes for this element.
151              
152             =cut
153              
154             sub xml_elt_open {
155 7     7 1 53 my ($self, $tag, @atts) = @_;
156 7 50       33 croak("xml_elt_open: odd number of attribute arguments")
157             if @atts % 2;
158 7         19 my $t = "<$tag";
159 7         25 while ( @atts ) {
160 5         18 $t .= " " . shift(@atts) . "=" . xml_quote(xml_text(shift(@atts))) . "";
161             }
162 7         15 $t .= ">";
163 7         29 $self->printi("$t\n");
164 7         28 $self->indent_incr;
165 7         8 unshift(@{$self->{elts}}, $tag);
  7         35  
166             }
167              
168             =head2 xml_elt_close
169              
170             Closes the current element. First (and only) argument is the name of
171             the element.
172              
173             =cut
174              
175             sub xml_elt_close {
176 6     6 1 30 my ($self, $tag) = @_;
177 6 50       35 if ( $tag eq $self->{elts}->[0] ) {
178 6         29 shift(@{$self->{elts}});
  6         15  
179             }
180             else {
181 0         0 warn("XML ERROR: closing element $tag while in ",
182             $self->{elts}->[0], "\n");
183             }
184 6         20 $self->indent_decr;
185 6         22 $self->printi("\n");
186             }
187              
188             =head2 xml_elt
189              
190             Outputs a simple element. First argument is the name of the element,
191             the second argument (if present) is the value. This may be followed by
192             a series of key/value pairs that will be used as attributes for this
193             element.
194              
195             $o->xml_elt("foo") ->
196             $o->xml_elt("foo", "bar") -> bar
197             $o->xml_elt("foo", "bar",
198             id => 1) -> bar
199             $o->xml_elt("foo", undef,
200             id => 1) ->
201              
202             =cut
203              
204             sub xml_elt {
205 9     9 1 1388 my ($self, $tag, $val, @atts) = @_;
206 9 50       46 croak("xml_elt: odd number of attribute arguments")
207             if @atts % 2;
208 9         31 my $t = "<$tag";
209 9         55 while ( @atts ) {
210 2         10 $t .= " " . shift(@atts) . "=" .
211             xml_quote(xml_text(shift(@atts))) . "";
212             }
213 9 100       42 if ( defined $val ) {
214 8         28 $self->printi($t, ">", xml_text($val), "\n");
215             }
216             else {
217 1         8 $self->printi("$t />\n");
218             }
219             }
220              
221             =head2 xml_comment
222              
223             Outputs a comment. Arguments contain the comment text.
224              
225             =cut
226              
227             sub xml_comment {
228 0     0 1 0 my ($self, @a) = @_;
229 0         0 $self->printi("\n");
230             }
231              
232             # XMLise text.
233             sub xml_text {
234 15 50   15 0 53 return "" unless defined $_[0];
235 15         38 for ( $_[0] ) {
236 15         35 s/&/&/g;
237 15         28 s/'/'/g;
238 15         34 s/
239 15         30 s/>/>/g;
240 15         102 return $_;
241             }
242             }
243              
244             sub xml_quote {
245 7     7 0 14 my $t = shift;
246 7 50       54 return '"'.$t.'"' unless $t =~ /"/;
247 0           return "'".$t."'";
248             }
249              
250             =head1 AUTHOR
251              
252             Johan Vromans, C<< >>
253              
254             =head1 BUGS
255              
256             Please report any bugs or feature requests to C, or through
257             the web interface at L. I will be notified, and then you'll
258             automatically be notified of progress on your bug as I make changes.
259              
260             =head1 SUPPORT
261              
262             You can find documentation for this module with the perldoc command.
263              
264             perldoc Text::FakeXML
265              
266             You can also look for information at:
267              
268             =over 4
269              
270             =item * RT: CPAN's request tracker
271              
272             L
273              
274             =item * CPAN Ratings
275              
276             L
277              
278             =item * Search CPAN
279              
280             L
281              
282             =back
283              
284             =head1 COPYRIGHT & LICENSE
285              
286             Copyright 2008 Johan Vromans, all rights reserved.
287              
288             This program is free software; you can redistribute it and/or modify it
289             under the same terms as Perl itself.
290              
291             =cut
292              
293             1;