File Coverage

blib/lib/DBD/XMLSimple.pm
Criterion Covered Total %
statement 34 50 68.0
branch 0 8 0.0
condition n/a
subroutine 12 17 70.5
pod n/a
total 46 75 61.3


line stmt bran cond sub pod time code
1             package DBD::XMLSimple;
2              
3 1     1   86592 use warnings;
  1         2  
  1         29  
4 1     1   3 use strict;
  1         1  
  1         23  
5              
6             =head1 NAME
7              
8             DBD::XMLSimple - Access XML data via the DBI interface
9              
10             =head1 VERSION
11              
12             Version 0.05
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         613  
54              
55 1     1   144275 use vars qw($VERSION $drh $methods_already_installed);
  1         1  
  1         155  
56              
57             our $VERSION = '0.05';
58             our $drh = undef;
59              
60             sub driver
61             {
62 0 0   0     return $drh if $drh;
63              
64 0           my($class, $attr) = @_;
65              
66             # $class .= '::dr';
67             # $drh = DBI::_new_drh($class, {
68             # $drh = DBI::_new_drh("$class::dr", {
69 0           $drh = $class->SUPER::driver({
70             'Name' => 'XML',
71             'Version' => $VERSION,
72             'Attribution' => 'DBD::XMLSimple by Nigel Horne',
73             });
74              
75 0 0         if($drh) {
76 0 0         unless($methods_already_installed++) {
77 0           DBI->setup_driver(__PACKAGE__);
78 0           DBD::XMLSimple::db->install_method('x_import');
79             }
80             }
81              
82 0           return $drh;
83             }
84              
85             sub CLONE
86             {
87 0     0     undef $drh;
88             }
89              
90             package DBD::XMLSimple::dr;
91              
92 1     1   4 use vars qw($imp_data_size);
  1         1  
  1         66  
93              
94             sub disconnect_all
95             {
96 0     0     shift->{tables} = {};
97             }
98              
99             sub DESTROY
100             {
101 0     0     shift->{tables} = {};
102             }
103              
104             package DBD::XMLSimple::db;
105              
106 1     1   4 use vars qw($imp_data_size);
  1         1  
  1         83  
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 0     0     my($dbh, $table_name, $format, $file_name, $flags) = @_;
114              
115 0 0         die if($format ne 'XML');
116              
117 0           $dbh->{filename} = $file_name;
118             }
119              
120             package DBD::XMLSimple::st;
121              
122 1     1   4 use strict;
  1         1  
  1         18  
123 1     1   3 use warnings;
  1         1  
  1         31  
124              
125 1     1   3 use vars qw($imp_data_size);
  1         2  
  1         44  
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 1     1   3 use strict;
  1         1  
  1         17  
133 1     1   3 use warnings;
  1         1  
  1         22  
134 1     1   1898 use XML::Twig;
  0            
  0            
135             use Carp;
136              
137             @DBD::XMLSimple::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement);
138              
139             sub open_table($$$$$)
140             {
141             my($self, $data, $tname, $createMode, $lockMode) = @_;
142             my $dbh = $data->{Database};
143              
144             my $twig = XML::Twig->new();
145             my $source = $dbh->{filename};
146             if(ref($source) eq 'ARRAY') {
147             $twig->parse(join('', @{$source}));
148             } else {
149             $twig->parsefile($source);
150             }
151              
152             my $root = $twig->root;
153             my %table;
154             my $rows = 0;
155             my %col_nums;
156             my @col_names;
157             foreach my $record($root->children()) {
158             my %row;
159             my $index = 0;
160             foreach my $leaf($record->children) {
161             my $key = $leaf->name();
162             $row{$key} = $leaf->field();
163             if(!exists($col_nums{$key})) {
164             $col_nums{$key} = $index++;
165             push @col_names, $key;
166             }
167             }
168             $table{data}->{$record->att('id')} = \%row;
169             $rows++;
170             }
171              
172             carp "No data found to import" if($rows == 0);
173             carp "Can't determine column names" if(scalar(@col_names) == 0);
174              
175             $data->{'rows'} = $rows;
176              
177             $table{'table_name'} = $tname;
178             $table{'col_names'} = \@col_names;
179             $table{'col_nums'} = \%col_nums;
180              
181             return DBD::XMLSimple::Table->new($data, \%table);
182             }
183              
184             package DBD::XMLSimple::Table;
185              
186             use strict;
187             use warnings;
188              
189             @DBD::XMLSimple::Table::ISA = qw(DBI::DBD::SqlEngine::Table);
190              
191             sub new
192             {
193             my($class, $data, $attr, $flags) = @_;
194              
195             $attr->{table} = $data;
196             $attr->{readonly} = 1;
197             $attr->{cursor} = 0;
198              
199             my $rc = $class->SUPER::new($data, $attr, $flags);
200              
201             $rc->{col_names} = $attr->{col_names};
202             $rc->{col_nums} = $attr->{col_nums};
203             return $rc;
204             }
205              
206             sub fetch_row($$)
207             {
208             my($self, $data) = @_;
209              
210             if($self->{cursor} >= $data->{rows}) {
211             return;
212             }
213             $self->{cursor}++;
214              
215             my @fields;
216             foreach my $col(@{$self->{'col_names'}}) {
217             push @fields, $self->{'data'}->{$self->{'cursor'}}->{$col};
218             }
219             $self->{row} = \@fields;
220              
221             return $self->{row};
222             }
223              
224             sub seek($$$$)
225             {
226             my($self, $data, $pos, $whence) = @_;
227              
228             print "seek $pos $whence, not yet implemented\n";
229             }
230              
231             sub complete_table_name($$$$)
232             {
233             my($self, $meta, $file, $respect_case, $file_is_table) = @_;
234             }
235              
236             sub open_data
237             {
238             # my($className, $meta, $attrs, $flags) = @_;
239             }
240              
241             sub bootstrap_table_meta
242             {
243             my($class, $dbh, $meta, $table, @other) = @_;
244              
245             $class->SUPER::bootstrap_table_meta($dbh, $meta, $table, @other);
246              
247             $meta->{table} = $table;
248              
249             $meta->{sql_data_source} ||= __PACKAGE__;
250             }
251              
252             sub get_table_meta($$$$;$)
253             {
254             my($class, $dbh, $table, $file_is_table, $respect_case) = @_;
255              
256             my $meta = $class->SUPER::get_table_meta($dbh, $table, $respect_case, $file_is_table);
257              
258             $table = $meta->{table};
259              
260             return unless $table;
261              
262             return($table, $meta);
263             }
264              
265             =head1 AUTHOR
266              
267             Nigel Horne, C<< >>
268              
269             =head1 BUGS
270              
271             Change x_import to xmls_import once it's been registered
272              
273             =head1 SEE ALSO
274              
275             L, which was also used as a template for this module.
276              
277             =head1 SUPPORT
278              
279             You can find documentation for this module with the perldoc command.
280              
281             perldoc DBD::XMLSimple
282              
283             You can also look for information at:
284              
285             =over 4
286              
287             =item * RT: CPAN's request tracker
288              
289             L
290              
291             =item * AnnoCPAN: Annotated CPAN documentation
292              
293             L
294              
295             =item * CPAN Ratings
296              
297             L
298              
299             =item * Search CPAN
300              
301             L
302              
303             =back
304              
305             =head1 LICENCE AND COPYRIGHT
306              
307             Copyright 2016 Nigel Horne.
308              
309             This program is released under the following licence: GPL
310              
311             =cut
312              
313             1; # End of DBD::XMLSimple