File Coverage

blib/lib/MARC/Parser/XML.pm
Criterion Covered Total %
statement 12 14 85.7
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 17 19 89.4


line stmt bran cond sub pod time code
1             package MARC::Parser::XML;
2              
3 2     2   13596 use strict;
  2         4  
  2         48  
4 2     2   6 use warnings;
  2         2  
  2         41  
5 2     2   47 use 5.008_005;
  2         4  
6             our $VERSION = '0.01';
7              
8 2     2   7 use Carp qw(croak);
  2         2  
  2         129  
9 2     2   1049 use XML::LibXML::Reader;
  0            
  0            
10              
11             sub new {
12             my ( $class, $input ) = @_;
13              
14             my $self = bless { input => $input, rec_number => 0, }, $class;
15              
16             # check for file or filehandle
17             my $ishandle = eval { fileno($input); };
18             if ( !$@ && defined $ishandle ) {
19             binmode $input; # drop all PerlIO layers, as required by libxml2
20             my $reader = XML::LibXML::Reader->new( IO => $input )
21             or croak "cannot read from filehandle $input\n";
22             $self->{xml_reader} = $reader;
23             }
24             elsif ( defined $input && $input !~ /\n/ && -e $input ) {
25             my $reader = XML::LibXML::Reader->new( location => $input )
26             or croak "cannot read from file $input\n";
27             $self->{xml_reader} = $reader;
28             }
29             elsif ( defined $input && length $input > 0 ) {
30             $input = ${$input} if ( ref($input) // '' eq 'SCALAR' );
31             my $reader = XML::LibXML::Reader->new( string => $input )
32             or croak "cannot read XML string $input\n";
33             $self->{xml_reader} = $reader;
34             }
35             else {
36             croak "file, filehande or string $input does not exists";
37             }
38             return $self;
39             }
40              
41             sub next {
42             my ($self) = @_;
43              
44             return
45             unless $self->{xml_reader}
46             ->nextElement( 'record', 'http://www.loc.gov/MARC21/slim' );
47              
48             if ( my $record = $self->_decode() ) {
49             return $record;
50             }
51             else {
52             return $self->next;
53             }
54              
55             return;
56             }
57              
58             sub _decode {
59             my ($self) = @_;
60             my @record;
61              
62             foreach my $field_node (
63             $self->{xml_reader}->copyCurrentNode(1)->getChildrenByTagName('*') )
64             {
65              
66             if ( $field_node->localName =~ m/leader/ ) {
67             push @record,
68             [ 'ldr', undef, undef, '_', $field_node->textContent ];
69             }
70             elsif ( $field_node->localName =~ m/controlfield/ ) {
71             push @record,
72             [
73             $field_node->getAttribute('tag'), undef,
74             undef, '_',
75             $field_node->textContent
76             ];
77             }
78             elsif ( $field_node->localName eq 'datafield' ) {
79             push @record,
80             [
81             $field_node->getAttribute('tag'),
82             $field_node->getAttribute('ind1') // '',
83             $field_node->getAttribute('ind2') // '',
84             map { $_->getAttribute('code'), $_->textContent }
85             $field_node->getChildrenByTagName('*')
86             ];
87             }
88             }
89             return \@record;
90             }
91              
92             1;
93             __END__