| Filename | /usr/share/perl5/MARC/File/XML.pm |
| Statements | Executed 24689 statements in 82.9ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 4263 | 7 | 1 | 34.8ms | 43.4ms | MARC::File::XML::escape |
| 25 | 1 | 1 | 33.9ms | 102ms | MARC::File::XML::record |
| 4107 | 1 | 1 | 6.83ms | 6.83ms | MARC::File::XML::CORE:subst (opcode) |
| 25 | 1 | 1 | 2.44ms | 476ms | MARC::File::XML::decode |
| 4107 | 1 | 1 | 1.78ms | 1.78ms | MARC::File::XML::CORE:regcomp (opcode) |
| 25 | 1 | 1 | 1.53ms | 104ms | MARC::File::XML::encode |
| 1 | 1 | 1 | 738µs | 19.4ms | MARC::File::XML::BEGIN@9 |
| 25 | 1 | 1 | 379µs | 551µs | MARC::File::XML::decideMARC8Binary |
| 25 | 1 | 1 | 362µs | 477ms | MARC::Record::new_from_xml |
| 125 | 5 | 1 | 335µs | 335µs | MARC::File::XML::CORE:match (opcode) |
| 25 | 1 | 1 | 268µs | 104ms | MARC::Record::as_xml |
| 25 | 1 | 1 | 259µs | 259µs | MARC::File::XML::header |
| 25 | 1 | 1 | 201µs | 201µs | MARC::File::XML::default_record_format |
| 25 | 1 | 1 | 114µs | 114µs | MARC::File::XML::footer |
| 1 | 1 | 1 | 22µs | 45µs | MARC::File::XML::BEGIN@3 |
| 6 | 1 | 1 | 20µs | 20µs | MARC::File::XML::CORE:substcont (opcode) |
| 1 | 1 | 1 | 18µs | 210µs | MARC::File::XML::BEGIN@13 |
| 1 | 1 | 1 | 16µs | 139µs | MARC::File::XML::BEGIN@6 |
| 1 | 1 | 1 | 14µs | 18µs | MARC::File::XML::BEGIN@4 |
| 1 | 1 | 1 | 13µs | 94µs | MARC::File::XML::BEGIN@10 |
| 1 | 1 | 1 | 12µs | 41µs | MARC::File::XML::BEGIN@7 |
| 1 | 1 | 1 | 12µs | 68µs | MARC::File::XML::BEGIN@14 |
| 1 | 1 | 1 | 11µs | 57µs | MARC::File::XML::BEGIN@5 |
| 1 | 1 | 1 | 11µs | 74µs | MARC::File::XML::BEGIN@12 |
| 1 | 1 | 1 | 8µs | 8µs | MARC::File::XML::CORE:qr (opcode) |
| 1 | 1 | 1 | 6µs | 6µs | MARC::File::XML::import |
| 1 | 1 | 1 | 6µs | 6µs | MARC::File::XML::BEGIN@8 |
| 1 | 1 | 1 | 6µs | 6µs | MARC::File::XML::BEGIN@15 |
| 0 | 0 | 0 | 0s | 0s | MARC::File::XML::DESTROY |
| 0 | 0 | 0 | 0s | 0s | MARC::File::XML::_next |
| 0 | 0 | 0 | 0s | 0s | MARC::File::XML::_unimarc_encoding |
| 0 | 0 | 0 | 0s | 0s | MARC::File::XML::close |
| 0 | 0 | 0 | 0s | 0s | MARC::File::XML::out |
| 0 | 0 | 0 | 0s | 0s | MARC::File::XML::write |
| 0 | 0 | 0 | 0s | 0s | MARC::Record::as_xml_record |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package MARC::File::XML; | ||||
| 2 | |||||
| 3 | 3 | 37µs | 2 | 68µs | # spent 45µs (22+23) within MARC::File::XML::BEGIN@3 which was called:
# once (22µs+23µs) by C4::Biblio::BEGIN@29 at line 3 # spent 45µs making 1 call to MARC::File::XML::BEGIN@3
# spent 23µs making 1 call to warnings::import |
| 4 | 3 | 39µs | 2 | 22µs | # spent 18µs (14+4) within MARC::File::XML::BEGIN@4 which was called:
# once (14µs+4µs) by C4::Biblio::BEGIN@29 at line 4 # spent 18µs making 1 call to MARC::File::XML::BEGIN@4
# spent 4µs making 1 call to strict::import |
| 5 | 3 | 33µs | 2 | 104µs | # spent 57µs (11+46) within MARC::File::XML::BEGIN@5 which was called:
# once (11µs+46µs) by C4::Biblio::BEGIN@29 at line 5 # spent 57µs making 1 call to MARC::File::XML::BEGIN@5
# spent 46µs making 1 call to vars::import |
| 6 | 3 | 39µs | 2 | 262µs | # spent 139µs (16+123) within MARC::File::XML::BEGIN@6 which was called:
# once (16µs+123µs) by C4::Biblio::BEGIN@29 at line 6 # spent 139µs making 1 call to MARC::File::XML::BEGIN@6
# spent 123µs making 1 call to base::import |
| 7 | 3 | 29µs | 2 | 70µs | # spent 41µs (12+29) within MARC::File::XML::BEGIN@7 which was called:
# once (12µs+29µs) by C4::Biblio::BEGIN@29 at line 7 # spent 41µs making 1 call to MARC::File::XML::BEGIN@7
# spent 29µs making 1 call to Exporter::import |
| 8 | 3 | 24µs | 1 | 6µs | # spent 6µs within MARC::File::XML::BEGIN@8 which was called:
# once (6µs+0s) by C4::Biblio::BEGIN@29 at line 8 # spent 6µs making 1 call to MARC::File::XML::BEGIN@8 |
| 9 | 3 | 141µs | 1 | 19.4ms | # spent 19.4ms (738µs+18.7) within MARC::File::XML::BEGIN@9 which was called:
# once (738µs+18.7ms) by C4::Biblio::BEGIN@29 at line 9 # spent 19.4ms making 1 call to MARC::File::XML::BEGIN@9 |
| 10 | 3 | 39µs | 2 | 175µs | # spent 94µs (13+81) within MARC::File::XML::BEGIN@10 which was called:
# once (13µs+81µs) by C4::Biblio::BEGIN@29 at line 10 # spent 94µs making 1 call to MARC::File::XML::BEGIN@10
# spent 81µs making 1 call to Exporter::import |
| 11 | |||||
| 12 | 3 | 33µs | 2 | 137µs | # spent 74µs (11+63) within MARC::File::XML::BEGIN@12 which was called:
# once (11µs+63µs) by C4::Biblio::BEGIN@29 at line 12 # spent 74µs making 1 call to MARC::File::XML::BEGIN@12
# spent 63µs making 1 call to Exporter::import |
| 13 | 3 | 40µs | 2 | 401µs | # spent 210µs (18+192) within MARC::File::XML::BEGIN@13 which was called:
# once (18µs+192µs) by C4::Biblio::BEGIN@29 at line 13 # spent 210µs making 1 call to MARC::File::XML::BEGIN@13
# spent 192µs making 1 call to Exporter::import |
| 14 | 3 | 34µs | 2 | 124µs | # spent 68µs (12+56) within MARC::File::XML::BEGIN@14 which was called:
# once (12µs+56µs) by C4::Biblio::BEGIN@29 at line 14 # spent 68µs making 1 call to MARC::File::XML::BEGIN@14
# spent 56µs making 1 call to Exporter::import |
| 15 | 3 | 1.88ms | 1 | 6µs | # spent 6µs within MARC::File::XML::BEGIN@15 which was called:
# once (6µs+0s) by C4::Biblio::BEGIN@29 at line 15 # spent 6µs making 1 call to MARC::File::XML::BEGIN@15 |
| 16 | |||||
| 17 | 1 | 800ns | $VERSION = '0.92'; | ||
| 18 | |||||
| 19 | 1 | 11µs | 1 | 31µs | my $factory = XML::SAX::ParserFactory->new(); # spent 31µs making 1 call to XML::SAX::ParserFactory::new |
| 20 | 1 | 3µs | 1 | 6µs | $factory->require_feature(Namespaces); # spent 6µs making 1 call to XML::SAX::ParserFactory::require_feature |
| 21 | |||||
| 22 | # spent 6µs within MARC::File::XML::import which was called:
# once (6µs+0s) by C4::Biblio::BEGIN@29 at line 29 of /usr/share/koha/lib/C4/Biblio.pm | ||||
| 23 | 1 | 900ns | my $class = shift; | ||
| 24 | 1 | 900ns | %_load_args = @_; | ||
| 25 | 1 | 2µs | $_load_args{ DefaultEncoding } ||= 'UTF-8'; | ||
| 26 | 1 | 5µs | $_load_args{ RecordFormat } ||= 'USMARC'; | ||
| 27 | } | ||||
| 28 | |||||
| 29 | =head1 NAME | ||||
| 30 | |||||
| - - | |||||
| 101 | # spent 201µs within MARC::File::XML::default_record_format which was called 25 times, avg 8µs/call:
# 25 times (201µs+0s) by C4::Biblio::GetMarcBiblio at line 1259 of /usr/share/koha/lib/C4/Biblio.pm, avg 8µs/call | ||||
| 102 | 25 | 23µs | my $self = shift; | ||
| 103 | 25 | 22µs | my $format = shift; | ||
| 104 | |||||
| 105 | 25 | 65µs | $_load_args{RecordFormat} = $format if ($format); | ||
| 106 | |||||
| 107 | 25 | 121µs | return $_load_args{RecordFormat}; | ||
| 108 | } | ||||
| 109 | |||||
| 110 | |||||
| 111 | =head2 as_xml() | ||||
| 112 | |||||
| - - | |||||
| 121 | # spent 104ms (268µs+104) within MARC::Record::as_xml which was called 25 times, avg 4.17ms/call:
# 25 times (268µs+104ms) by C4::XSLT::XSLTParse4Display at line 200 of /usr/share/koha/lib/C4/XSLT.pm, avg 4.17ms/call | ||||
| 122 | 25 | 24µs | my $record = shift; | ||
| 123 | 25 | 24µs | my $format = shift || $_load_args{RecordFormat}; | ||
| 124 | 25 | 229µs | 25 | 104ms | return( MARC::File::XML::encode( $record, $format ) ); # spent 104ms making 25 calls to MARC::File::XML::encode, avg 4.16ms/call |
| 125 | } | ||||
| 126 | |||||
| 127 | =head2 as_xml_record([$format]) | ||||
| 128 | |||||
| - - | |||||
| 137 | sub MARC::Record::as_xml_record { | ||||
| 138 | my $record = shift; | ||||
| 139 | my $format = shift || $_load_args{RecordFormat}; | ||||
| 140 | return( MARC::File::XML::encode( $record, $format, 1 ) ); | ||||
| 141 | } | ||||
| 142 | |||||
| 143 | =head2 new_from_xml([$encoding, $format]) | ||||
| 144 | |||||
| - - | |||||
| 157 | # spent 477ms (362µs+476) within MARC::Record::new_from_xml which was called 25 times, avg 19.1ms/call:
# 25 times (362µs+476ms) by C4::Biblio::GetMarcBiblio at line 1263 of /usr/share/koha/lib/C4/Biblio.pm, avg 19.1ms/call | ||||
| 158 | 25 | 47µs | my $xml = shift; | ||
| 159 | ## to allow calling as MARC::Record::new_from_xml() | ||||
| 160 | ## or MARC::Record->new_from_xml() | ||||
| 161 | 25 | 39µs | $xml = shift if ( ref($xml) || ($xml eq "MARC::Record") ); | ||
| 162 | |||||
| 163 | 25 | 24µs | my $enc = shift || $_load_args{BinaryEncoding}; | ||
| 164 | 25 | 21µs | my $format = shift || $_load_args{RecordFormat}; | ||
| 165 | 25 | 234µs | 25 | 476ms | return( MARC::File::XML::decode( $xml, $enc, $format ) ); # spent 476ms making 25 calls to MARC::File::XML::decode, avg 19.1ms/call |
| 166 | } | ||||
| 167 | |||||
| 168 | =pod | ||||
| 169 | |||||
| - - | |||||
| 184 | sub out { | ||||
| 185 | my ( $class, $filename, $enc ) = @_; | ||||
| 186 | my $fh = IO::File->new( ">$filename" ) or croak( $! ); | ||||
| 187 | $enc ||= $_load_args{DefaultEncoding}; | ||||
| 188 | |||||
| 189 | if ($enc =~ /^utf-?8$/oi) { | ||||
| 190 | $fh->binmode(':utf8'); | ||||
| 191 | } else { | ||||
| 192 | $fh->binmode(':raw'); | ||||
| 193 | } | ||||
| 194 | |||||
| 195 | my %self = ( | ||||
| 196 | filename => $filename, | ||||
| 197 | fh => $fh, | ||||
| 198 | header => 0, | ||||
| 199 | encoding => $enc | ||||
| 200 | ); | ||||
| 201 | return( bless \%self, ref( $class ) || $class ); | ||||
| 202 | } | ||||
| 203 | |||||
| 204 | =head2 write() | ||||
| 205 | |||||
| - - | |||||
| 214 | sub write { | ||||
| 215 | my ( $self, $record, $enc ) = @_; | ||||
| 216 | if ( ! $self->{ fh } ) { | ||||
| 217 | croak( "MARC::File::XML object not open for writing" ); | ||||
| 218 | } | ||||
| 219 | if ( ! $record ) { | ||||
| 220 | croak( "must pass write() a MARC::Record object" ); | ||||
| 221 | } | ||||
| 222 | ## print the XML header if we haven't already | ||||
| 223 | if ( ! $self->{ header } ) { | ||||
| 224 | $enc ||= $self->{ encoding } || $_load_args{DefaultEncoding}; | ||||
| 225 | $self->{ fh }->print( header( $enc ) ); | ||||
| 226 | $self->{ header } = 1; | ||||
| 227 | } | ||||
| 228 | ## print out the record | ||||
| 229 | $self->{ fh }->print( record( $record ) ) || croak( $! ); | ||||
| 230 | return( 1 ); | ||||
| 231 | } | ||||
| 232 | |||||
| 233 | =head2 close() | ||||
| 234 | |||||
| - - | |||||
| 241 | sub close { | ||||
| 242 | my $self = shift; | ||||
| 243 | if ( $self->{ fh } ) { | ||||
| 244 | $self->{ fh }->print( footer() ) if $self->{ header }; | ||||
| 245 | $self->{ fh } = undef; | ||||
| 246 | $self->{ filename } = undef; | ||||
| 247 | $self->{ header } = undef; | ||||
| 248 | } | ||||
| 249 | return( 1 ); | ||||
| 250 | } | ||||
| 251 | |||||
| 252 | ## makes sure that the XML file is closed off | ||||
| 253 | |||||
| 254 | sub DESTROY { | ||||
| 255 | shift->close(); | ||||
| 256 | } | ||||
| 257 | |||||
| 258 | =pod | ||||
| 259 | |||||
| - - | |||||
| 278 | # spent 259µs within MARC::File::XML::header which was called 25 times, avg 10µs/call:
# 25 times (259µs+0s) by MARC::File::XML::encode at line 480, avg 10µs/call | ||||
| 279 | 25 | 32µs | my $enc = shift; | ||
| 280 | 25 | 51µs | $enc = shift if ( $enc && (ref($enc) || ($enc eq "MARC::File::XML")) ); | ||
| 281 | 25 | 11µs | $enc ||= 'UTF-8'; | ||
| 282 | 25 | 180µs | return( <<MARC_XML_HEADER ); | ||
| 283 | <?xml version="1.0" encoding="$enc"?> | ||||
| 284 | <collection | ||||
| 285 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 286 | xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd" | ||||
| 287 | xmlns="http://www.loc.gov/MARC21/slim"> | ||||
| 288 | MARC_XML_HEADER | ||||
| 289 | } | ||||
| 290 | |||||
| 291 | =head2 footer() | ||||
| 292 | |||||
| - - | |||||
| 297 | # spent 114µs within MARC::File::XML::footer which was called 25 times, avg 5µs/call:
# 25 times (114µs+0s) by MARC::File::XML::encode at line 486, avg 5µs/call | ||||
| 298 | 25 | 137µs | return( "</collection>" ); | ||
| 299 | } | ||||
| 300 | |||||
| 301 | =head2 record() | ||||
| 302 | |||||
| - - | |||||
| 307 | # spent 102ms (33.9+68.3) within MARC::File::XML::record which was called 25 times, avg 4.09ms/call:
# 25 times (33.9ms+68.3ms) by MARC::File::XML::encode at line 485, avg 4.09ms/call | ||||
| 308 | 25 | 17µs | my $record = shift; | ||
| 309 | 25 | 21µs | my $format = shift; | ||
| 310 | 25 | 14µs | my $include_full_record_header = shift; | ||
| 311 | 25 | 15µs | my $enc = shift; | ||
| 312 | |||||
| 313 | 25 | 14µs | $format ||= $_load_args{RecordFormat}; | ||
| 314 | |||||
| 315 | 25 | 18µs | my $_transcode = 0; | ||
| 316 | 25 | 170µs | 25 | 208µs | my $ldr = $record->leader; # spent 208µs making 25 calls to MARC::Record::leader, avg 8µs/call |
| 317 | 25 | 43µs | my $original_encoding = substr($ldr,9,1); | ||
| 318 | |||||
| 319 | # Does the record think it is already Unicode? | ||||
| 320 | 25 | 30µs | if ($original_encoding ne 'a' && lc($format) !~ /^unimarc/o) { | ||
| 321 | # If not, we'll make it so | ||||
| 322 | $_transcode++; | ||||
| 323 | substr($ldr,9,1,'a'); | ||||
| 324 | $record->leader( $ldr ); | ||||
| 325 | } | ||||
| 326 | |||||
| 327 | 25 | 32µs | my @xml = (); | ||
| 328 | |||||
| 329 | 25 | 27µs | if ($include_full_record_header) { | ||
| 330 | push @xml, <<HEADER | ||||
| 331 | <?xml version="1.0" encoding="$enc"?> | ||||
| 332 | <record | ||||
| 333 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 334 | xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd" | ||||
| 335 | xmlns="http://www.loc.gov/MARC21/slim"> | ||||
| 336 | HEADER | ||||
| 337 | |||||
| 338 | } else { | ||||
| 339 | 25 | 35µs | push( @xml, "<record>" ); | ||
| 340 | } | ||||
| 341 | |||||
| 342 | 25 | 207µs | 50 | 725µs | push( @xml, " <leader>" . escape( $record->leader ) . "</leader>" ); # spent 610µs making 25 calls to MARC::File::XML::escape, avg 24µs/call
# spent 114µs making 25 calls to MARC::Record::leader, avg 5µs/call |
| 343 | |||||
| 344 | 25 | 216µs | 25 | 285µs | foreach my $field ( $record->fields() ) { # spent 285µs making 25 calls to MARC::Record::fields, avg 11µs/call |
| 345 | 544 | 3.00ms | 1088 | 7.68ms | my ($tag) = escape( $field->tag() ); # spent 5.43ms making 544 calls to MARC::File::XML::escape, avg 10µs/call
# spent 2.25ms making 544 calls to MARC::Field::tag, avg 4µs/call |
| 346 | 544 | 1.96ms | 544 | 1.80ms | if ( $field->is_control_field() ) { # spent 1.80ms making 544 calls to MARC::Field::is_control_field, avg 3µs/call |
| 347 | 32 | 142µs | 32 | 413µs | my $data = $field->data; # spent 413µs making 32 calls to MARC::Field::data, avg 13µs/call |
| 348 | 32 | 191µs | 32 | 325µs | push( @xml, qq( <controlfield tag="$tag">) . # spent 325µs making 32 calls to MARC::File::XML::escape, avg 10µs/call |
| 349 | escape( ($_transcode ? marc8_to_utf8($data) : $data) ). qq(</controlfield>) ); | ||||
| 350 | } else { | ||||
| 351 | 512 | 2.30ms | 1024 | 9.90ms | my ($i1) = escape( $field->indicator( 1 ) ); # spent 5.06ms making 512 calls to MARC::Field::indicator, avg 10µs/call
# spent 4.84ms making 512 calls to MARC::File::XML::escape, avg 9µs/call |
| 352 | 512 | 2.37ms | 1024 | 9.39ms | my ($i2) = escape( $field->indicator( 2 ) ); # spent 4.79ms making 512 calls to MARC::File::XML::escape, avg 9µs/call
# spent 4.60ms making 512 calls to MARC::Field::indicator, avg 9µs/call |
| 353 | 512 | 1.03ms | push( @xml, qq( <datafield tag="$tag" ind1="$i1" ind2="$i2">) ); | ||
| 354 | 512 | 2.27ms | 512 | 10.2ms | foreach my $subfield ( $field->subfields() ) { # spent 10.2ms making 512 calls to MARC::Field::subfields, avg 20µs/call |
| 355 | 1319 | 4.41ms | 1319 | 13.6ms | my ( $code, $data ) = ( escape( $$subfield[0] ), $$subfield[1] ); # spent 13.6ms making 1319 calls to MARC::File::XML::escape, avg 10µs/call |
| 356 | 1319 | 7.05ms | 1319 | 13.8ms | push( @xml, qq( <subfield code="$code">). # spent 13.8ms making 1319 calls to MARC::File::XML::escape, avg 10µs/call |
| 357 | escape( ($_transcode ? marc8_to_utf8($data) : $data) ).qq(</subfield>) ); | ||||
| 358 | } | ||||
| 359 | 512 | 646µs | push( @xml, " </datafield>" ); | ||
| 360 | } | ||||
| 361 | } | ||||
| 362 | 25 | 24µs | push( @xml, "</record>\n" ); | ||
| 363 | |||||
| 364 | 25 | 11µs | if ($_transcode) { | ||
| 365 | substr($ldr,9,1,$original_encoding); | ||||
| 366 | $record->leader( $ldr ); | ||||
| 367 | } | ||||
| 368 | |||||
| 369 | 25 | 1.89ms | return( join( "\n", @xml ) ); | ||
| 370 | } | ||||
| 371 | |||||
| 372 | 1 | 4µs | my %ESCAPES = ( | ||
| 373 | '&' => '&', | ||||
| 374 | '<' => '<', | ||||
| 375 | '>' => '>', | ||||
| 376 | ); | ||||
| 377 | 3 | 3µs | my $ESCAPE_REGEX = | ||
| 378 | eval 'qr/' . | ||||
| 379 | 1 | 48µs | join( '|', map { $_ = "\Q$_\E" } keys %ESCAPES ) . # spent 20µs executing statements in string eval | ||
| 380 | '/;' | ||||
| 381 | ; | ||||
| 382 | |||||
| 383 | # spent 43.4ms (34.8+8.63) within MARC::File::XML::escape which was called 4263 times, avg 10µs/call:
# 1319 times (11.5ms+2.34ms) by MARC::File::XML::record at line 356, avg 10µs/call
# 1319 times (10.8ms+2.80ms) by MARC::File::XML::record at line 355, avg 10µs/call
# 544 times (4.33ms+1.10ms) by MARC::File::XML::record at line 345, avg 10µs/call
# 512 times (3.75ms+1.09ms) by MARC::File::XML::record at line 351, avg 9µs/call
# 512 times (3.78ms+1.01ms) by MARC::File::XML::record at line 352, avg 9µs/call
# 32 times (247µs+78µs) by MARC::File::XML::record at line 348, avg 10µs/call
# 25 times (400µs+210µs) by MARC::File::XML::record at line 342, avg 24µs/call | ||||
| 384 | 4263 | 2.40ms | my $string = shift; | ||
| 385 | 4263 | 3.01ms | return '' if ! defined $string or $string eq ''; | ||
| 386 | 4107 | 28.4ms | 8220 | 8.63ms | $string =~ s/($ESCAPE_REGEX)/$ESCAPES{$1}/oge; # spent 6.83ms making 4107 calls to MARC::File::XML::CORE:subst, avg 2µs/call
# spent 1.78ms making 4107 calls to MARC::File::XML::CORE:regcomp, avg 432ns/call
# spent 20µs making 6 calls to MARC::File::XML::CORE:substcont, avg 3µs/call |
| 387 | 4107 | 12.7ms | return( $string ); | ||
| 388 | } | ||||
| 389 | |||||
| 390 | sub _next { | ||||
| 391 | my $self = shift; | ||||
| 392 | my $fh = $self->{ fh }; | ||||
| 393 | |||||
| 394 | ## return undef at the end of the file | ||||
| 395 | return if eof($fh); | ||||
| 396 | |||||
| 397 | ## get a chunk of xml for a record | ||||
| 398 | local $/ = '</record>'; | ||||
| 399 | my $xml = <$fh>; | ||||
| 400 | |||||
| 401 | ## trim stuff before the start record element | ||||
| 402 | $xml =~ s/.*<record.*?>/<record>/s; | ||||
| 403 | |||||
| 404 | ## return undef if there isn't a good chunk of xml | ||||
| 405 | return if ( $xml !~ m|<record>.*</record>|s ); | ||||
| 406 | |||||
| 407 | ## return the chunk of xml | ||||
| 408 | return( $xml ); | ||||
| 409 | } | ||||
| 410 | |||||
| 411 | =head2 decode() | ||||
| 412 | |||||
| - - | |||||
| 420 | # spent 476ms (2.44+474) within MARC::File::XML::decode which was called 25 times, avg 19.1ms/call:
# 25 times (2.44ms+474ms) by MARC::Record::new_from_xml at line 165, avg 19.1ms/call | ||||
| 421 | 25 | 14µs | my $text; | ||
| 422 | 25 | 24µs | my $location = ''; | ||
| 423 | 25 | 31µs | my $self = shift; | ||
| 424 | |||||
| 425 | ## see MARC::File::USMARC::decode for explanation of what's going on | ||||
| 426 | ## here | ||||
| 427 | 25 | 162µs | 25 | 34µs | if ( ref($self) =~ /^MARC::File/ ) { # spent 34µs making 25 calls to MARC::File::XML::CORE:match, avg 1µs/call |
| 428 | $location = 'in record '.$self->{recnum}; | ||||
| 429 | $text = shift; | ||||
| 430 | } else { | ||||
| 431 | 25 | 28µs | $location = 'in record 1'; | ||
| 432 | 25 | 206µs | 25 | 94µs | $text = $self=~/MARC::File/ ? shift : $self; # spent 94µs making 25 calls to MARC::File::XML::CORE:match, avg 4µs/call |
| 433 | } | ||||
| 434 | |||||
| 435 | 25 | 30µs | my $enc = shift || $_load_args{BinaryEncoding}; | ||
| 436 | 25 | 21µs | my $format = shift || $_load_args{RecordFormat}; | ||
| 437 | |||||
| 438 | 25 | 162µs | 25 | 303µs | my $handler = MARC::File::SAX->new(); # spent 303µs making 25 calls to MARC::File::SAX::new, avg 12µs/call |
| 439 | 25 | 220µs | 25 | 3.95ms | my $parser = $factory->parser( # spent 3.95ms making 25 calls to XML::SAX::ParserFactory::parser, avg 158µs/call |
| 440 | Handler => $handler, | ||||
| 441 | ProtocolEncoding => $_load_args{DefaultEncoding} | ||||
| 442 | ); | ||||
| 443 | 25 | 157µs | 25 | 551µs | $parser->{ Handler }{ toMARC8 } = decideMARC8Binary($format,$enc); # spent 551µs making 25 calls to MARC::File::XML::decideMARC8Binary, avg 22µs/call |
| 444 | |||||
| 445 | 25 | 126µs | 25 | 469ms | $parser->parse_string( $text ); # spent 469ms making 25 calls to XML::SAX::Base::parse_string, avg 18.8ms/call |
| 446 | |||||
| 447 | 25 | 1.26ms | 25 | 147µs | return( $handler->record() ); # spent 147µs making 25 calls to MARC::File::SAX::record, avg 6µs/call |
| 448 | } | ||||
| 449 | |||||
| 450 | # spent 551µs (379+172) within MARC::File::XML::decideMARC8Binary which was called 25 times, avg 22µs/call:
# 25 times (379µs+172µs) by MARC::File::XML::decode at line 443, avg 22µs/call | ||||
| 451 | 25 | 22µs | my $format = shift; | ||
| 452 | 25 | 21µs | my $enc = shift; | ||
| 453 | |||||
| 454 | 25 | 134µs | 25 | 17µs | return 0 if (defined($format) && lc($format) =~ /^unimarc/o); # spent 17µs making 25 calls to MARC::File::XML::CORE:match, avg 676ns/call |
| 455 | 25 | 375µs | 25 | 155µs | return 0 if (defined($enc) && lc($enc) =~ /^utf-?8/o); # spent 155µs making 25 calls to MARC::File::XML::CORE:match, avg 6µs/call |
| 456 | return 1; | ||||
| 457 | } | ||||
| 458 | |||||
| 459 | |||||
| 460 | =head2 encode() | ||||
| 461 | |||||
| - - | |||||
| 469 | # spent 104ms (1.53+103) within MARC::File::XML::encode which was called 25 times, avg 4.16ms/call:
# 25 times (1.53ms+103ms) by MARC::Record::as_xml at line 124, avg 4.16ms/call | ||||
| 470 | 25 | 23µs | my $record = shift; | ||
| 471 | 25 | 25µs | my $format = shift || $_load_args{RecordFormat}; | ||
| 472 | 25 | 18µs | my $without_collection_header = shift; | ||
| 473 | 25 | 82µs | my $enc = shift || $_load_args{DefaultEncoding}; | ||
| 474 | |||||
| 475 | 25 | 173µs | 25 | 35µs | if (lc($format) =~ /^unimarc/o) { # spent 35µs making 25 calls to MARC::File::XML::CORE:match, avg 1µs/call |
| 476 | $enc = _unimarc_encoding( $format => $record ); | ||||
| 477 | } | ||||
| 478 | |||||
| 479 | 25 | 33µs | my @xml = (); | ||
| 480 | 25 | 163µs | 25 | 259µs | push( @xml, header( $enc ) ) unless ($without_collection_header); # spent 259µs making 25 calls to MARC::File::XML::header, avg 10µs/call |
| 481 | # verbose, but naming the header output flags this way to avoid | ||||
| 482 | # the potential confusion identified in CPAN bug #34082 | ||||
| 483 | # http://rt.cpan.org/Public/Bug/Display.html?id=34082 | ||||
| 484 | 25 | 30µs | my $include_full_record_header = ($without_collection_header) ? 1 : 0; | ||
| 485 | 25 | 315µs | 25 | 102ms | push( @xml, record( $record, $format, $include_full_record_header, $enc ) ); # spent 102ms making 25 calls to MARC::File::XML::record, avg 4.09ms/call |
| 486 | 25 | 131µs | 25 | 114µs | push( @xml, footer() ) unless ($without_collection_header); # spent 114µs making 25 calls to MARC::File::XML::footer, avg 5µs/call |
| 487 | |||||
| 488 | 25 | 493µs | return( join( "\n", @xml ) ); | ||
| 489 | } | ||||
| 490 | |||||
| 491 | sub _unimarc_encoding { | ||||
| 492 | my $f = shift; | ||||
| 493 | my $r = shift; | ||||
| 494 | |||||
| 495 | my $pos = 26; | ||||
| 496 | $pos = 13 if (lc($f) eq 'unimarcauth'); | ||||
| 497 | |||||
| 498 | my $enc = substr( $r->subfield(100 => 'a'), $pos, 2 ); | ||||
| 499 | |||||
| 500 | if ($enc eq '01' || $enc eq '03') { | ||||
| 501 | return 'ISO-8859-1'; | ||||
| 502 | } elsif ($enc eq '50') { | ||||
| 503 | return 'UTF-8'; | ||||
| 504 | } else { | ||||
| 505 | die "Unsupported UNIMARC character encoding [$enc] for XML output for $f; 100\$a -> " . $r->subfield(100 => 'a'); | ||||
| 506 | } | ||||
| 507 | } | ||||
| 508 | |||||
| 509 | =head1 TODO | ||||
| 510 | |||||
| - - | |||||
| 543 | 1 | 8µs | 1; | ||
# spent 335µs within MARC::File::XML::CORE:match which was called 125 times, avg 3µs/call:
# 25 times (155µs+0s) by MARC::File::XML::decideMARC8Binary at line 455, avg 6µs/call
# 25 times (94µs+0s) by MARC::File::XML::decode at line 432, avg 4µs/call
# 25 times (35µs+0s) by MARC::File::XML::encode at line 475, avg 1µs/call
# 25 times (34µs+0s) by MARC::File::XML::decode at line 427, avg 1µs/call
# 25 times (17µs+0s) by MARC::File::XML::decideMARC8Binary at line 454, avg 676ns/call | |||||
# spent 8µs within MARC::File::XML::CORE:qr which was called:
# once (8µs+0s) by C4::Biblio::BEGIN@29 at line 1 of (eval 961)[MARC/File/XML.pm:379] | |||||
# spent 1.78ms within MARC::File::XML::CORE:regcomp which was called 4107 times, avg 432ns/call:
# 4107 times (1.78ms+0s) by MARC::File::XML::escape at line 386, avg 432ns/call | |||||
# spent 6.83ms within MARC::File::XML::CORE:subst which was called 4107 times, avg 2µs/call:
# 4107 times (6.83ms+0s) by MARC::File::XML::escape at line 386, avg 2µs/call | |||||
# spent 20µs within MARC::File::XML::CORE:substcont which was called 6 times, avg 3µs/call:
# 6 times (20µs+0s) by MARC::File::XML::escape at line 386, avg 3µs/call |