File Coverage

blib/lib/MARC/File/SAX.pm
Criterion Covered Total %
statement 71 72 98.6
branch 31 34 91.1
condition 16 27 59.2
subroutine 12 13 92.3
pod 6 6 100.0
total 136 152 89.4


line stmt bran cond sub pod time code
1             package MARC::File::SAX;
2              
3             =head1 NAME
4              
5             MARC::File::SAX - SAX handler for parsing MARCXML
6              
7             =cut
8              
9 7     7   44 use strict;
  7         17  
  7         190  
10 7     7   246166 use XML::SAX;
  7         34404  
  7         304  
11 7     7   49 use base qw( XML::SAX::Base );
  7         14  
  7         594804  
12 7     7   92289 use Data::Dumper;
  7         24705  
  7         426  
13 7     7   50 use MARC::Record;
  7         14  
  7         224  
14 7     7   3168 use MARC::Charset qw(utf8_to_marc8);
  7         508050  
  7         431  
15 7     7   62 use Carp qw(croak);
  7         14  
  7         3787  
16              
17             =head2 new()
18              
19             Create the handler.
20              
21             =cut
22              
23             sub new {
24 27     27 1 70 my $class = shift;
25 27   33     251 return bless {records => []}, ref($class) || $class;
26             }
27              
28             =head2 records()
29              
30             Get all the MARC::Records that were parsed out of the XML.
31              
32             =cut
33              
34             sub records {
35 0     0 1 0 return shift->{records};
36             }
37              
38             =head2 record()
39              
40             In some contexts you might only expect there to be one record parsed. This
41             is a shorthand for getting it.
42              
43             =cut
44              
45             sub record {
46 26     26 1 875 return shift->{records}[0];
47             }
48              
49             sub start_element {
50 946     946 1 727084 my ( $self, $element ) = @_;
51 946         1780 my $name = $element->{ LocalName };
52 946 100       3223 if ( $name eq 'record' ) {
    100          
    100          
53 26         165 $self->{ record } = MARC::Record->new();
54             } elsif ( $name eq 'collection' ) {
55             # ignore collection wrappers
56             } elsif ( defined $self->{ record } ) {
57 915 100       3229 if ( $name eq 'leader' ) {
    100          
    100          
    50          
58 26         93 $self->{ tag } = 'LDR';
59             } elsif ( $name eq 'controlfield' ) {
60 87         290 $self->{ tag } = $element->{ Attributes }{ '{}tag' }{ Value };
61             } elsif ( $name eq 'datafield' ) {
62 305         749 $self->{ tag } = $element->{ Attributes }{ '{}tag' }{ Value };
63 305         670 $self->{ i1 } = $element->{ Attributes }{ '{}ind1' }{ Value };
64 305         865 $self->{ i2 } = $element->{ Attributes }{ '{}ind2' }{ Value };
65             } elsif ( $name eq 'subfield' ) {
66 497         1518 $self->{ subcode } = $element->{ Attributes }{ '{}code' }{ Value };
67             }
68             } else {
69             # we've reached a new element but haven't started populating
70             # a MARC::Record yet. This either means that we've encountered
71             # some non-MARC21slim stuff or the caller's given us an invalid
72             # doc that doesn't include a element.
73             # In the first case, we'll just ignore the element; in the second
74             # case, we'll thow an exception with a better description.
75             #
76             # TODO: to be more consistent with how MARC::File::USMARC handles
77             # parse errors, rather than throwing an exception we could
78             # instantiate an empty MARC::Record and set its warnings
79             # array.
80             #
81 1 50 33     74 if ( $name eq 'leader' || $name eq 'controlfield' || $name eq 'datafield' || $name eq 'subfield' ) {
      33        
      33        
82 1         292 croak("found MARCXML element $name, but the wrapper is missing");
83             }
84             }
85             }
86              
87             sub end_element {
88 944     944 1 140192 my ( $self, $element ) = @_;
89 944         1629 my $name = $element->{ LocalName };
90 944 100       2824 if ( $name eq 'subfield' ) {
    100          
    100          
    100          
    100          
91 497         702 push @{ $self->{ subfields } }, $self->{ subcode };
  497         1421  
92              
93 497 100       1095 if ($self->{ transcode }) {
94 71         123 push @{ $self->{ subfields } }, utf8_to_marc8($self->{ chars });
  71         287  
95             } else {
96 426         591 push @{ $self->{ subfields } }, $self->{ chars } ;
  426         799  
97             }
98              
99 497         105250 $self->{ chars } = '';
100 497         1280 $self->{ subcode } = '';
101             } elsif ( $name eq 'controlfield' ) {
102             $self->{ record }->append_fields(
103             MARC::Field->new( $self->{ tag }, $self->{ chars } )
104 87         360 );
105 87         4271 $self->{ chars } = '';
106 87         236 $self->{ tag } = '';
107             } elsif ( $name eq 'datafield' ) {
108             $self->{ record }->append_fields(
109             MARC::Field->new(
110             $self->{ tag },
111             $self->{ i1 },
112             $self->{ i2 },
113 305         693 @{ $self->{ subfields } }
  305         1140  
114             )
115             );
116 305         20939 $self->{ tag } = '';
117 305         574 $self->{ i1 } = '';
118 305         495 $self->{ i2 } = '';
119 305         661 $self->{ subfields } = [];
120 305         929 $self->{ chars } = '';
121             } elsif ( $name eq 'leader' ) {
122 26         61 my $ldr = $self->{ chars };
123              
124             $self->{ transcode }++
125 26 50 66     147 if (substr($ldr,9,1) eq 'a' and $self->{toMARC8});
126              
127 26 100       101 substr($ldr,9,1,' ') if ($self->{ transcode });
128              
129 26         128 $self->{ record }->leader( $ldr );
130 26         327 $self->{ chars } = '';
131 26         86 $self->{ tag } = '';
132             } elsif ( $name eq 'record' ) {
133 26         58 push(@{ $self->{ records } }, $self->{ record });
  26         87  
134 26         93 undef $self->{ record };
135             }
136             }
137              
138             sub characters {
139 1881     1881 1 116979 my ( $self, $chars ) = @_;
140 1881 100 100     14001 if (
      100        
      66        
      66        
141             ( exists $self->{ subcode } && $self->{ subcode } ne '')
142             || ( $self->{ tag } && ( $self->{ tag } eq 'LDR' || $self->{ tag } < 10 ))
143             ) {
144 628         1769 $self->{ chars } .= $chars->{ Data };
145             }
146             }
147              
148             1;