File Coverage

blib/lib/Text/vFile/toXML.pm
Criterion Covered Total %
statement 22 37 59.4
branch 2 2 100.0
condition 1 9 11.1
subroutine 7 9 77.7
pod 3 3 100.0
total 35 60 58.3


line stmt bran cond sub pod time code
1             package Text::vFile::toXML;
2              
3 2     2   39524 use strict;
  2         8  
  2         72  
4 2     2   14 use warnings;
  2         5  
  2         175  
5              
6             =head1 NAME
7              
8             Text::vFile::toXML - Convert vFiles into equivalent XML
9              
10             =head1 VERSION
11              
12             Version 0.05
13              
14             =cut
15              
16             our $VERSION = '0.05';
17              
18 2     2   16 use Carp qw(croak);
  2         17  
  2         133  
19 2     2   991 use Text::vFile::asData;
  2         9618  
  2         12  
20 2     2   1064 use XML::Quick;
  2         1919  
  2         153  
21              
22 2     2   18 use base qw(Exporter);
  2         5  
  2         859  
23             our @EXPORT_OK = qw(to_xml xCalNS);
24              
25             our %attrs = qw(language xml:lang);
26             our $xCalNS = 'urn:ietf:params:xml:ns:xcal';
27              
28             =head1 SYNOPSIS
29              
30             This module converts iCalendar (iCal : generically, vFile) files into their
31             (equivalent) XML (xCalendar / xCal) representation, according to Royer's IETF
32             Draft (L).
33              
34             # Enable functional interface
35             use Text::vFile::toXML qw(to_xml);
36              
37             # Input filename
38             my $arg = "input.file";
39             my $a = Text::vFile::toXML->new(filename => $arg)->to_xml;
40             my $b = Text::vFile::toXML->new(filehandle =>
41             do { open my $fh, $arg or die "can't open ics: $!"; $fh }
42             )->to_xml;
43              
44             use Text::vFile::asData; # to make the functional example work
45             my $data =
46             Text::vFile::asData->new->parse(
47             do {
48             open my $fh, $arg
49             or die "Can't open vFile: $!"; $fh
50             }
51             );
52             my $c = Text::vFile::toXML->new(data => $data)->to_xml;
53              
54             # Use functional interface
55             my $d = to_xml($data);
56              
57             # Now ($a, $b, $c, $d) all contain the same XML string.
58              
59             =head1 EXPORT
60              
61             No functions are exported by default; you can choose to import the 'to_xml'
62             function if you wish to use the functional interface.
63              
64             =head1 METHODS
65              
66             =head2 new
67              
68             Creates a new Text::vFile::toXML object; takes a list of key-value pairs for initialization, which must contain exactly one of the following:
69              
70             filehandle => (filehandle object)
71             filename => (string)
72             data => (Text::vFile::asData struct)
73              
74             =cut
75              
76             sub new {
77 3     3 1 1129 my ($type, %args) = @_;
78              
79             croak "Must provide exactly one of (filehandle, filename, or data)"
80 3 100       5 unless +@{[ grep defined, @args{qw(filehandle filename data)} ]} == 1;
  3         259  
81              
82             $args{_data} = delete $args{data}
83             || Text::vFile::asData->new->parse(
84             $args{filehandle} || ($args{filename} &&
85 1   33     18 do { open my $fh, $args{filename} or die; $fh }
86             ));
87            
88 0           bless \%args, $type
89             }
90              
91             =head2 to_xml
92              
93             Wraps the convert() function; returns an XML string. Can be called as an
94             instance method (OO-style) or as a function (functional style), in which case
95             it takes a Text::vFile::asData-compatible data structure as its only parameter.
96              
97             =cut
98              
99             sub to_xml {
100 0   0 0 1   xml({ convert($_[0]->{_data}{objects} || $_[0]->{objects}) },
101             { root => 'iCalendar', attrs => { 'xmlns:xCal' => $xCalNS } })
102             }
103              
104             =head2 convert
105              
106             Recursively converts Text::vFile::asData structures to XML::Quick-compatible
107             ones.
108              
109             =cut
110              
111             sub convert {
112 0     0 1   my ($data) = @_;
113 0           my %result;
114              
115 0           for my $object (@$data) {
116 0           my ($props, $objects, $type) = @$object{qw(properties objects type)};
117              
118 0           push @{ $result{lc $type} }, +{
119             convert($objects),
120             map {
121 0           my $propname = $_;
  0            
122 0           lc $propname => [ map { my ($p, $v) = @$_{qw(param value)}; +{
123             _cdata => $v,
124 0   0       _attrs => +{ map { $attrs{lc $_} || lc $_ => $p->{$_} } keys %$p } }
  0            
125 0           } @{ $props->{$propname} } ]
  0            
126             } keys %$props
127             };
128             }
129              
130 0           return %result;
131             }
132              
133             =head1 AUTHOR
134              
135             Darren Kulp, C<< >>
136              
137             =head1 BUGS
138              
139             Probably. Email me at the address above with bug reports.
140              
141             =head1 ACKNOWLEDGEMENTS
142              
143             The L and L modules proved very useful, to the
144             point of nearly trivializing this module.
145              
146             =head1 COPYRIGHT & LICENSE
147              
148             Copyright 2006-2017 Darren Kulp.
149              
150             This program is released under the terms of the BSD license.
151              
152             =cut
153              
154             1; # End of Text::vFile::toXML
155             __END__