Skip to content

Commit

Permalink
Replace XML::Simple with XML::LibXML
Browse files Browse the repository at this point in the history
This PR replaces use of XML::Simple with XML::LibXML.

XML::Simple is documented as `PLEASE DO NOT USE THIS MODULE IN NEW CODE`.

This affects the ISO20022 CAMT053 bank statement file import, which
has been refactored to use the new XML module.

This change does not introduce a new dependency to lsmb. Rather
it removes a dependency, as XML::LibXML was already a dependency
of the XML::Simple module previously in use.
  • Loading branch information
nick-prater committed Apr 18, 2020
1 parent 0489e07 commit e32f6c2
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 44 deletions.
1 change: 1 addition & 0 deletions Changelog
Expand Up @@ -81,6 +81,7 @@ Dependency updates
* PGObject::Type::BigFloat >= 2.0.1 (from 1.0.0)
* PGObject::Type::DateTime >= 2.0.2 (from 1.0.4)
* PGObject::Type::ByteString >= 1.2.3 (from 1.1.1)
* XML::Simple (dropped)


Changelog for 1.7 Series
Expand Down
2 changes: 1 addition & 1 deletion cpanfile
Expand Up @@ -68,7 +68,7 @@ requires 'Text::CSV';
requires 'Text::Markdown';
requires 'Try::Tiny';
requires 'Version::Compare';
requires 'XML::Simple';
requires 'XML::LibXML';
requires 'namespace::autoclean';

recommends 'Math::BigInt::GMP';
Expand Down
84 changes: 42 additions & 42 deletions lib/LedgerSMB/FileFormats/ISO20022/CAMT053.pm
Expand Up @@ -2,7 +2,7 @@ package LedgerSMB::FileFormats::ISO20022::CAMT053;
use strict;
use warnings;

use XML::Simple;
use XML::LibXML;
use Try::Tiny;

=head1 NAME
Expand All @@ -11,20 +11,21 @@ LedgerSMB::FileFormats::ISO20022::CAMT053 - Parse SEPA CAMT053 files
=head1 SYNOPSIS
LedgerSMB::FileFormats::ISO20022::CAMT053->new($filename);
LedgerSMB::FileFormats::ISO20022::CAMT053->new($filecontents);
my $camt = LedgerSMB::FileFormats::ISO20022::CAMT053->new($filecontents);
my @transactions = $camt->lineitems_simple;
=head1 DESCRIPTION
This module provides basic management functions for CAMT053 files for LedgerSMB
This module provides basic parsing and data extraction of CAMT053 bank statement
files for LedgerSMB.
=head1 AUTODETECTION
The constructor returns UNDEF if the file is not a CAMT053 docuent.
The constructor returns C<undef> if the file is not a CAMT053 docuent.
=head1 METHODS
=head2 new($xml_data)
=head2 new($xml_string)
Pass in a string of XML data. Returns undef if the string is not valid XML or
not identified as a CAMT053 document.
Expand All @@ -35,47 +36,34 @@ sub new {
my ($class, $content) = @_;
return unless defined $content;

my $parser = XML::Simple->new();
my $raw;

# XML::Simple will die if content is not valid XML (it might be csv).
# Use parse_string() as the standard XMLin() parser scans the string
# for '<' and '>' characters and, if none are found, interprets
# the content as a filename to try reading from the filesystem.
my ($dom, $ns);
try {
$raw = $parser->parse_string($content);
$dom = XML::LibXML->load_xml(
string => $content
);
$ns = $dom->documentElement->namespaceURI;
};

return unless $raw
and $raw->{xmlns}
and $raw->{xmlns} eq 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.02';
return unless $dom
and $ns
and $ns eq 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.02';

return bless ({struct => $raw}, $class);
return bless ({dom => $dom}, $class);
}

=head1 PROPERTIES
=head2 raw_struct
=head2 dom
Returns the raw structure
Returns the XML::LibXML DOM tree representing the input xml.
=cut

sub raw_struct {
sub dom {
my ($self) = @_;
return $self->{struct}
return $self->{dom};
}

=head2 lineitems_full
Returns a simple list of data structures representing the statement lines
=cut

sub lineitems_full {
my ($self) = @_;
return @{$self->raw_struct->{BkToCstmrStmt}->{Stmt}->{Ntry}};
}

=head2 lineitems_simple
Expand All @@ -87,8 +75,6 @@ Returns a flattened list with the following elements:
=item acc_id
=item counterparty_name
=item amount
=item currency
Expand All @@ -112,21 +98,35 @@ sub _decode_crdt {

sub lineitems_simple {
my ($self) = @_;

my $xpc = XML::LibXML::XPathContext->new;
$xpc->registerNs(
'camt' => 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.02'
);
$xpc->setContextNode($self->dom);

my $transactions = $xpc->find(
'//camt:Document/camt:BkToCstmrStmt/camt:Stmt/camt:Ntry'
);

return map {
$xpc->setContextNode($_);
{
entry_id => $_->{NtryRef},
acc_id => $_->{AcctSvcrRef},
amount => $_->{Amt}->{content},
currency => $_->{Amt}->{Ccy},
booked_date => $_->{BookgDt}->{Dt},
credit_debit => _decode_crdt($_->{CdtDbtInd}),
entry_id => $xpc->findvalue('camt:NtryRef'),
acc_id => $xpc->findvalue('camt:AcctSvcrRef'),
amount => $xpc->findvalue('camt:Amt'),
currency => $xpc->findvalue('camt:Amt/@Ccy'),
booked_date => $xpc->findvalue('camt:BookgDt/camt:Dt'),
credit_debit => _decode_crdt(
$xpc->findvalue('camt:CdtDbtInd')
),
}
} $self->lineitems_full;
} @{$transactions};
}

=head1 LICENSE AND COPYRIGHT
Copyright (C) 2016-2018 The LedgerSMB Core Team
Copyright (C) 2016-2020 The LedgerSMB Core Team
This file is licensed under the GNU General Public License version 2, or at your
option any later version. A copy of the license should have been included with
Expand Down
1 change: 0 additions & 1 deletion t/20-camt053.t
Expand Up @@ -21,7 +21,6 @@ ok(! LedgerSMB::FileFormats::ISO20022::CAMT053->new(
'<?xml version="1.0" ?> <foo />'
), 'Autodetection of wrong xml type correct');

is(scalar $camt->lineitems_full(), 10, 'correct number of line items, raw');
is(scalar $camt->lineitems_simple(), 10, 'correct number of line items, flattened');

done_testing;

0 comments on commit e32f6c2

Please sign in to comment.