Bug 20540: Fix TransformHtmlToXml if last tag is empty

This bug has been found during testing bug 19289.

In some conditions C4::Biblio::TransformHtmlToXml will generate a malformed XML structure. The last </datafield> can be duplicated.

For instance, if a call like:
my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values );

with the last value of @field_values is empty, it will return:

<?xml version="1.0" encoding="UTF-8"?>
<collection
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
  xmlns="http://www.loc.gov/MARC21/slim">
<record>
<datafield2 tag="020" ind1=" " ind2=" ">
<subfield code="a">l</subfield>
</datafield>
<datafield1 tag="100" ind1=" " ind2=" ">
<subfield code="a">k</subfield>
</datafield>
<datafield1 tag="245" ind1=" " ind2=" ">
<subfield code="a">k</subfield>
</datafield>
<datafield1 tag="250" ind1=" " ind2=" ">
<subfield code="a">k</subfield>
</datafield>
<datafield1 tag="260" ind1=" " ind2=" ">
<subfield code="b">k</subfield>
<subfield code="c">k</subfield>
</datafield>
</datafield>
</record>
</collection>

Which will result later in the following error:
:23: parser error : Opening and ending tag mismatch: record line 6 and datafield
</datafield>
            ^
:24: parser error : Opening and ending tag mismatch: collection line 2 and record
</record>
         ^
:25: parser error : Extra content at the end of the document
</collection>

Test plan:
You can test it along with bug 19289 and confirm that it fixes the problem
raised on bug 19289 comment 30

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
Jonathan Druart 2018-04-06 17:16:30 -03:00
parent d8b6fde9b7
commit cc8f3dc1cc
2 changed files with 13 additions and 7 deletions

View File

@ -2263,6 +2263,7 @@ sub TransformHtmlToXml {
my $prevtag = -1;
my $first = 1;
my $j = -1;
my $close_last_tag;
for ( my $i = 0 ; $i < @$tags ; $i++ ) {
if ( C4::Context->preference('marcflavour') eq 'UNIMARC' and @$tags[$i] eq "100" and @$subfields[$i] eq "a" ) {
@ -2283,6 +2284,7 @@ sub TransformHtmlToXml {
@$values[$i] =~ s/'/&apos;/g;
if ( ( @$tags[$i] ne $prevtag ) ) {
$close_last_tag = 0;
$j++ unless ( @$tags[$i] eq "" );
my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) };
my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) };
@ -2301,6 +2303,7 @@ sub TransformHtmlToXml {
$xml .= "<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
$xml .= "<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
$first = 0;
$close_last_tag = 1;
} else {
$first = 1;
}
@ -2320,6 +2323,7 @@ sub TransformHtmlToXml {
$xml .= "<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
$xml .= "<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
$first = 0;
$close_last_tag = 1;
}
}
}
@ -2339,13 +2343,14 @@ sub TransformHtmlToXml {
if ($first) {
$xml .= "<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
$first = 0;
$close_last_tag = 1;
}
$xml .= "<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
}
}
$prevtag = @$tags[$i];
}
$xml .= "</datafield>\n" if $xml =~ m/<datafield/;
$xml .= "</datafield>\n" if $close_last_tag;
if ( C4::Context->preference('marcflavour') eq 'UNIMARC' and !$unimarc_and_100_exist ) {
# warn "SETTING 100 for $auth_type";
@ -2362,6 +2367,7 @@ sub TransformHtmlToXml {
}
$xml .= "</record>\n";
$xml .= MARC::File::XML::footer();
use Data::Printer colored => 1; warn p $xml;
return $xml;
}

View File

@ -33,14 +33,14 @@ sub run_tests {
my ( $tags, $subfields );
if ( $marc_flavour eq 'UNIMARC' ) {
$tags= [ '001', '600', '200', '200' ];
$subfields = [ '', 'a', 'a', 'c' ];
$tags= [ '001', '600', '200', '200', '400' ];
$subfields = [ '', 'a', 'a', 'c', 'a' ];
} else {
$tags= [ '001', '100', '245', '245' ];
$subfields = [ '', 'a', 'a', 'c' ];
$tags= [ '001', '100', '245', '245', '400' ];
$subfields = [ '', 'a', 'a', 'c', 'a' ];
}
my $values = [ '12345', 'author', 'title', 'resp' ];
my $ind = [ ' ', '00', ' 9', ' ' ];
my $values = [ '12345', 'author', 'title', 'resp', '' ];
my $ind = [ ' ', '00', ' 9', ' ', ' ' ];
my $xml = TransformHtmlToXml( $tags, $subfields, $values, $ind, undef, $marc_flavour );
my $xmlh = XML::Simple->new->XMLin( $xml );