File Coverage

blib/lib/DBD/XMLSimple.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package DBD::XMLSimple;
2              
3 1     1   84889 use warnings;
  1         1  
  1         31  
4 1     1   4 use strict;
  1         1  
  1         25  
5              
6             =head1 NAME
7              
8             DBD::XMLSimple - Access XML data via the DBI interface
9              
10             =head1 VERSION
11              
12             Version 0.04
13              
14             =cut
15              
16             =head1 SYNOPSIS
17              
18             Reads XML and makes it available via DBI.
19              
20             use FindBin qw($Bin);
21             use DBI;
22              
23             my $dbh = DBI->connect('dbi:XMLSimple(RaiseError => 1):');
24              
25             # To be replaced with xmls_import once the driver has been registered
26             $dbh->func('person', 'XML', "$Bin/../data/person.xml", 'x_import');
27              
28             my $sth = $dbh->prepare("SELECT * FROM person");
29              
30             Input data will be something like this:
31              
32            
33            
34            
35             Nigel Horne
36             njh@bandsman.co.uk
37            
38            
39             A N Other
40             nobody@example.com
41            
42            
43             =cut
44              
45             =head1 SUBROUTINES/METHODS
46              
47             =head2 driver
48              
49             No routines in this module should be called directly by the application.
50              
51             =cut
52              
53 1     1   3 use base qw(DBI::DBD::SqlEngine);
  1         4  
  1         651  
54              
55             use vars qw($VERSION $drh $methods_already_installed);
56              
57             our $VERSION = '0.04';
58             our $drh = undef;
59              
60             sub driver
61             {
62             return $drh if $drh;
63              
64             my($class, $attr) = @_;
65              
66             # $class .= '::dr';
67             # $drh = DBI::_new_drh($class, {
68             # $drh = DBI::_new_drh("$class::dr", {
69             $drh = $class->SUPER::driver({
70             'Name' => 'XML',
71             'Version' => $VERSION,
72             'Attribution' => 'DBD::XMLSimple by Nigel Horne',
73             });
74              
75             if($drh) {
76             unless($methods_already_installed++) {
77             DBI->setup_driver(__PACKAGE__);
78             DBD::XMLSimple::db->install_method('x_import');
79             }
80             }
81              
82             return $drh;
83             }
84              
85             sub CLONE
86             {
87             undef $drh;
88             }
89              
90             package DBD::XMLSimple::dr;
91              
92             use vars qw($imp_data_size);
93              
94             sub disconnect_all
95             {
96             shift->{tables} = {};
97             }
98              
99             sub DESTROY
100             {
101             shift->{tables} = {};
102             }
103              
104             package DBD::XMLSimple::db;
105              
106             use vars qw($imp_data_size);
107              
108             $DBD::XMLSimple::db::imp_data_size = 0;
109             @DBD::XMLSimple::db::ISA = qw(DBI::DBD::SqlEngine::db);
110              
111             sub x_import
112             {
113             my($dbh, $table_name, $format, $file_name, $flags) = @_;
114              
115             die if($format ne 'XML');
116              
117             $dbh->{filename} = $file_name;
118             }
119              
120             package DBD::XMLSimple::st;
121              
122             use strict;
123             use warnings;
124              
125             use vars qw($imp_data_size);
126              
127             $DBD::XMLSimple::st::imp_data_size = 0;
128             @DBD::XMLSimple::st::ISA = qw(DBI::DBD::SqlEngine::st);
129              
130             package DBD::XMLSimple::Statement;
131              
132             use strict;
133             use warnings;
134             use XML::Twig;
135              
136             @DBD::XMLSimple::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement);
137              
138             sub open_table($$$$$)
139             {
140             my($self, $data, $tname, $createMode, $lockMode) = @_;
141             my $dbh = $data->{Database};
142              
143             my $twig = XML::Twig->new();
144             my $source = $dbh->{filename};
145             if(ref($source) eq 'ARRAY') {
146             $twig->parse(join('', @{$source}));
147             } else {
148             $twig->parsefile($source);
149             }
150              
151             my $root = $twig->root;
152             my %table;
153             my $rows = 0;
154             my %col_nums;
155             my @col_names;
156             foreach my $record($root->children()) {
157             my %row;
158             my $index = 0;
159             foreach my $leaf($record->children) {
160             $row{$leaf->name()} = $leaf->field();
161             $col_nums{$leaf->name()} = $index++;
162             push @col_names, $leaf->name() if($rows eq 0);
163             }
164             $table{data}->{$record->att('id')} = \%row;
165             $rows++;
166             }
167              
168             # FIXME: This assumes the each of the records in the XML file is
169             # in the same order
170             $data->{'rows'} = $rows;
171              
172             $table{'table_name'} = $tname;
173             $table{'col_names'} = \@col_names;
174             $table{'col_nums'} = \%col_nums;
175              
176             return DBD::XMLSimple::Table->new($data, \%table);
177             }
178              
179             package DBD::XMLSimple::Table;
180              
181             use strict;
182             use warnings;
183              
184             @DBD::XMLSimple::Table::ISA = qw(DBI::DBD::SqlEngine::Table);
185              
186             sub new
187             {
188             my($class, $data, $attr, $flags) = @_;
189              
190             $attr->{table} = $data;
191             $attr->{readonly} = 1;
192             $attr->{cursor} = 0;
193              
194             my $rc = $class->SUPER::new($data, $attr, $flags);
195              
196             $rc->{col_names} = $attr->{col_names};
197             $rc->{col_nums} = $attr->{col_nums};
198             return $rc;
199             }
200              
201             sub fetch_row($$)
202             {
203             my($self, $data) = @_;
204              
205             if($self->{cursor} >= $data->{rows}) {
206             return;
207             }
208             $self->{cursor}++;
209              
210             my @fields;
211             foreach my $col(@{$self->{'col_names'}}) {
212             push @fields, $self->{'data'}->{$self->{'cursor'}}->{$col};
213             }
214             $self->{row} = \@fields;
215              
216             return $self->{row};
217             }
218              
219             sub seek($$$$)
220             {
221             my($self, $data, $pos, $whence) = @_;
222              
223             print "seek $pos $whence, not yet implemented\n";
224             }
225              
226             sub complete_table_name($$$$)
227             {
228             my($self, $meta, $file, $respect_case, $file_is_table) = @_;
229             }
230              
231             sub open_data
232             {
233             # my($className, $meta, $attrs, $flags) = @_;
234             }
235              
236             sub bootstrap_table_meta
237             {
238             my($class, $dbh, $meta, $table, @other) = @_;
239              
240             $class->SUPER::bootstrap_table_meta($dbh, $meta, $table, @other);
241              
242             $meta->{table} = $table;
243              
244             $meta->{sql_data_source} ||= __PACKAGE__;
245             }
246              
247             sub get_table_meta($$$$;$)
248             {
249             my($class, $dbh, $table, $file_is_table, $respect_case) = @_;
250              
251             my $meta = $class->SUPER::get_table_meta($dbh, $table, $respect_case, $file_is_table);
252              
253             $table = $meta->{table};
254              
255             return unless $table;
256              
257             return($table, $meta);
258             }
259              
260             =head1 AUTHOR
261              
262             Nigel Horne, C<< >>
263              
264             =head1 BUGS
265              
266             Fields must be in the same order so this does not work (yet):
267              
268            
269             a
270             b
271            
272            
273             c
274             d
275            
276              
277             Change x_import to xmls_import once it's been registered
278              
279             =head1 SEE ALSO
280              
281             L, which was also used as a template for this module.
282              
283             =head1 SUPPORT
284              
285             You can find documentation for this module with the perldoc command.
286              
287             perldoc DBD::XMLSimple
288              
289             You can also look for information at:
290              
291             =over 4
292              
293             =item * RT: CPAN's request tracker
294              
295             L
296              
297             =item * AnnoCPAN: Annotated CPAN documentation
298              
299             L
300              
301             =item * CPAN Ratings
302              
303             L
304              
305             =item * Search CPAN
306              
307             L
308              
309             =back
310              
311             =head1 LICENCE AND COPYRIGHT
312              
313             Copyright 2016 Nigel Horne.
314              
315             This program is released under the following licence: GPL
316              
317             =cut
318              
319             1; # End of DBD::XMLSimple