Projekt

Allgemein

Profil

Herunterladen (3,24 KB) Statistiken
| Zweig: | Markierung: | Revision:
335b5ab6 Johannes Grassler
package SL::XMLInvoice;

1522aeb7 Johannes Grassler
use strict;
use warnings;

11624cb8 Sven Schöling
use List::Util qw(first);
1522aeb7 Johannes Grassler
use XML::LibXML;

11624cb8 Sven Schöling
use SL::Locale::String qw(t8);
use SL::XMLInvoice::UBL;
use SL::XMLInvoice::CrossIndustryInvoice;
use SL::XMLInvoice::CrossIndustryDocument;
350c829a Sven Schöling
1522aeb7 Johannes Grassler
use constant RES_OK => 0;
use constant RES_XML_PARSING_FAILED => 1;
use constant RES_UNKNOWN_ROOT_NODE_TYPE => 2;

11624cb8 Sven Schöling
our @document_modules = qw(
SL::XMLInvoice::CrossIndustryDocument
SL::XMLInvoice::CrossIndustryInvoice
SL::XMLInvoice::UBL
);

335b5ab6 Johannes Grassler
=head1 NAME

SL::XMLInvoice - Top level factory class for XML Invoice parsers.

=head1 DESCRIPTION

C<SL::XMLInvoice> is an abstraction layer allowing the application to pass any
supported XML invoice document for parsing, with C<SL::XMLInvoice> handling all
details from there: depending on its document type declaration, this class will
pick and instatiate the appropriate child class for parsing the document and
return an object exposing its data with the standardized structure outlined
below.

11624cb8 Sven Schöling
See L <SL::XMLInvoice::Base>
for details on the shared interface of the returned instances.

335b5ab6 Johannes Grassler
=head1 SYNOPSIS

# $xml_data contains an XML document as flat scalar
my $invoice_parser = SL::XMLInvoice->new($xml_data);

# %metadata is a hash of document level metadata items
my %metadata = %{$invoice_parser->metadata};

# @items is an array of hashes, each representing a line
# item on the bill
my @items = @{$invoice_parser->items};
ba845b8d Tamino Steinert
335b5ab6 Johannes Grassler
=cut

1522aeb7 Johannes Grassler
sub new {
11624cb8 Sven Schöling
my ($class, $xml_data) = @_;
my $self = {};
335b5ab6 Johannes Grassler
$self->{message} = '';
$self->{dom} = eval { XML::LibXML->load_xml(string => $xml_data) };

if ( ! $self->{dom} ) {
51c76e20 Johannes Grassler
$self->{message} = t8("Parsing the XML data failed: #1", $xml_data);
335b5ab6 Johannes Grassler
$self->{result} = RES_XML_PARSING_FAILED;
return $self;
1522aeb7 Johannes Grassler
}
335b5ab6 Johannes Grassler
# Determine parser class to use
11624cb8 Sven Schöling
my $type = first {
$_->check_signature($self->{dom})
} @document_modules;
335b5ab6 Johannes Grassler
unless ( $type ) {
$self->{result} = RES_UNKNOWN_ROOT_NODE_TYPE;
652aebcf Johannes Grassler
11624cb8 Sven Schöling
my @supported = map { $_->supported } @document_modules;
652aebcf Johannes Grassler
$self->{message} = t8("Could not parse XML Invoice: unknown XML invoice type\nsupported: #1",
11624cb8 Sven Schöling
join ",\n", @supported
51c76e20 Johannes Grassler
);
335b5ab6 Johannes Grassler
return $self;
1522aeb7 Johannes Grassler
}
335b5ab6 Johannes Grassler
bless $self, $type;

# Implementation sanity check for child classes: make sure they are aware of
# the keys the hash returned by their metadata() method must contain.
51c76e20 Johannes Grassler
my @missing_data_keys = grep { !${$self->_data_keys}{$_} } @{ $self->data_keys };
335b5ab6 Johannes Grassler
if ( scalar(@missing_data_keys) > 0 ) {
die "Incomplete implementation: the following metadata keys appear to be missing from $type: " . join(", ", @missing_data_keys);
}

# Implementation sanity check for child classes: make sure they are aware of
# the keys the hashes returned by their items() method must contain.
my @missing_item_keys = ();
1522aeb7 Johannes Grassler
foreach my $item_key ( @{$self->item_keys} ) {
335b5ab6 Johannes Grassler
unless ( ${$self->_item_keys}{$item_key}) { push @missing_item_keys, $item_key; }
1522aeb7 Johannes Grassler
}
335b5ab6 Johannes Grassler
if ( scalar(@missing_item_keys) > 0 ) {
die "Incomplete implementation: the following item keys appear to be missing from $type: " . join(", ", @missing_item_keys);
}

$self->parse_xml;

# Ensure these methods are implemented in the child class
$self->metadata;
$self->items;

$self->{result} = RES_OK;
return $self;
1522aeb7 Johannes Grassler
}
335b5ab6 Johannes Grassler
1;