Skip to content

Commit

Permalink
xmlwriter: fix issue with control chartacter in data elements
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcnamara committed Dec 17, 2023
1 parent 6cad7c8 commit fbdb693
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
24 changes: 24 additions & 0 deletions lib/Excel/Writer/XLSX/Package/XMLwriter.pm
Expand Up @@ -232,6 +232,7 @@ sub xml_data_element {
}

$data = _escape_data( $data );
$data = _escape_control_characters( $data );

local $\ = undef;
print { $self->{_fh} } "<$tag>$data</$end_tag>";
Expand Down Expand Up @@ -494,6 +495,29 @@ sub _escape_data {
}


###############################################################################
#
# _escape_control_characters()
#
# Excel escapes control characters with _xHHHH_ and also escapes any
# literal strings of that type by encoding the leading underscore. So
# "\0" -> _x0000_ and "_x0000_" -> _x005F_x0000_.
# The following substitutions deal with those cases.
#
sub _escape_control_characters {

my $str = $_[0];

# Escape the escape.
$str =~ s/(_x[0-9a-fA-F]{4}_)/_x005F$1/g;

# Convert control character to the _xHHHH_ escape.
$str =~ s/([\x00-\x08\x0B-\x1F])/sprintf "_x%04X_", ord($1)/eg;

return $str;
}


1;


Expand Down
90 changes: 90 additions & 0 deletions t/regression/escapes09.t
@@ -0,0 +1,90 @@
###############################################################################
#
# Tests the output of Excel::Writer::XLSX against Excel generated files.
#
# Copyright 2000-2023, John McNamara, jmcnamara@cpan.org
#
# SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
#

use lib 't/lib';
use TestFunctions qw(_compare_xlsx_files _is_deep_diff);
use strict;
use warnings;

use Test::More tests => 1;

###############################################################################
#
# Tests setup.
#
my $filename = 'escapes09.xlsx';
my $dir = 't/regression/';
my $got_filename = $dir . "ewx_$filename";
my $exp_filename = $dir . 'xlsx_files/' . $filename;

my $ignore_members = [];

my $ignore_elements = {};


###############################################################################
#
# Test the creation of a simple Excel::Writer::XLSX file.
#
use Excel::Writer::XLSX;

my $workbook = Excel::Writer::XLSX->new( $got_filename );
my $worksheet = $workbook->add_worksheet();
my $chart = $workbook->add_chart( type => 'line', embedded => 1 );

# For testing, copy the randomly generated axis ids in the target xlsx file.
$chart->{_axis_ids} = [ 52721920, 53133312 ];


$worksheet->write( 0, 0, "Data\x1b[32m1" );
$worksheet->write( 1, 0, "Data\x1b[32m2" );
$worksheet->write( 2, 0, "Data\x1b[32m3" );
$worksheet->write( 3, 0, "Data\x1b[32m4" );

$worksheet->write( 0, 1, 10 );
$worksheet->write( 1, 1, 20 );
$worksheet->write( 2, 1, 10 );
$worksheet->write( 3, 1, 30 );

$chart->add_series(
categories => '=Sheet1!$A$1:$A$4',
values => '=Sheet1!$B$1:$B$4'
);

$worksheet->insert_chart( 'E9', $chart );

$workbook->close();


###############################################################################
#
# Compare the generated and existing Excel files.
#

my ( $got, $expected, $caption ) = _compare_xlsx_files(

$got_filename,
$exp_filename,
$ignore_members,
$ignore_elements,
);

_is_deep_diff( $got, $expected, $caption );


###############################################################################
#
# Cleanup.
#
unlink $got_filename;

__END__
Binary file added t/regression/xlsx_files/escapes09.xlsx
Binary file not shown.

0 comments on commit fbdb693

Please sign in to comment.