# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::System::XML;
## nofilter(TidyAll::Plugin::OTRS::Perl::Require)
use strict;
use warnings;
use Digest::MD5;
our @ObjectDependencies = (
'Kernel::System::Cache',
'Kernel::System::DB',
'Kernel::System::Encode',
'Kernel::System::Log',
);
=head1 NAME
Kernel::System::XML - xml lib
=head1 DESCRIPTION
All xml related functions.
=head1 PUBLIC INTERFACE
=head2 new()
Don't use the constructor directly, use the ObjectManager instead:
my $XMLObject = $Kernel::OM->Get('Kernel::System::XML');
=cut
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
return $Self;
}
=head2 XMLHashAdd()
add an XMLHash to storage
my $Key = $XMLObject->XMLHashAdd(
Type => 'SomeType',
Key => '123',
XMLHash => \@XMLHash,
);
my $AutoKey = $XMLObject->XMLHashAdd(
Type => 'SomeType',
KeyAutoIncrement => 1,
XMLHash => \@XMLHash,
);
=cut
sub XMLHashAdd {
my ( $Self, %Param ) = @_;
# check needed stuff
for (qw(Type XMLHash)) {
if ( !$Param{$_} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $_!"
);
return;
}
}
if ( !$Param{Key} && !$Param{KeyAutoIncrement} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Key or KeyAutoIncrement param!',
);
return;
}
my %ValueHASH = $Self->XMLHash2D( XMLHash => $Param{XMLHash} );
if (%ValueHASH) {
if ( !$Param{Key} ) {
$Param{Key} = $Self->_XMLHashAddAutoIncrement(%Param);
}
if ( !$Param{Key} ) {
return;
}
$Self->XMLHashDelete(%Param);
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
# create rand number
my $Rand = int( rand(1000000) );
my $TmpKey = "TMP-$Rand-$Param{Type}";
for my $Key ( sort keys %ValueHASH ) {
$DBObject->Do(
SQL =>
'INSERT INTO xml_storage (xml_type, xml_key, xml_content_key, xml_content_value) VALUES (?, ?, ?, ?)',
Bind => [ \$TmpKey, \$Param{Key}, \$Key, \$ValueHASH{$Key}, ],
);
}
# move new hash if insert is complete
$Self->XMLHashMove(
OldType => $TmpKey,
OldKey => $Param{Key},
NewType => $Param{Type},
NewKey => $Param{Key},
);
return $Param{Key};
}
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Got no %ValueHASH from XMLHash2D()',
);
return;
}
=head2 XMLHashUpdate()
update an XMLHash to storage
$XMLHash[1]->{Name}->[1]->{Content} = 'Some Name';
$XMLObject->XMLHashUpdate(
Type => 'SomeType',
Key => '123',
XMLHash => \@XMLHash,
);
=cut
sub XMLHashUpdate {
my ( $Self, %Param ) = @_;
# check needed stuff
for (qw(Type Key XMLHash)) {
if ( !$Param{$_} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $_!"
);
return;
}
}
return $Self->XMLHashAdd(%Param);
}
=head2 XMLHashGet()
get an XMLHash from the database
my @XMLHash = $XMLObject->XMLHashGet(
Type => 'SomeType',
Key => '123',
);
my @XMLHash = $XMLObject->XMLHashGet(
Type => 'SomeType',
Key => '123',
Cache => 0, # (optional) do not use cached data
);
=cut
sub XMLHashGet {
my ( $Self, %Param ) = @_;
my $Content = '';
my @XMLHash;
# check needed stuff
for (qw(Type Key)) {
if ( !$Param{$_} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $_!"
);
return;
}
}
if ( !defined $Param{Cache} ) {
$Param{Cache} = 1;
}
# get cache object
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
# check cache
if ( $Param{Cache} ) {
my $Cache = $CacheObject->Get(
Type => 'XML',
Key => "$Param{Type}-$Param{Key}",
# Don't store complex structure in memory as it will be modified later.
CacheInMemory => 0,
);
return @{$Cache} if $Cache;
}
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
# sql
return if !$DBObject->Prepare(
SQL => 'SELECT xml_content_key, xml_content_value '
. ' FROM xml_storage WHERE xml_type = ? AND xml_key = ?',
Bind => [ \$Param{Type}, \$Param{Key} ],
);
while ( my @Data = $DBObject->FetchrowArray() ) {
if ( defined $Data[1] ) {
$Data[1] =~ s/\\/\\\\/g;
$Data[1] =~ s/'/\\'/g;
}
else {
$Data[1] = '';
}
$Content .= '$XMLHash' . $Data[0] . " = '$Data[1]';\n 1;\n";
}
if ( $Content && !eval $Content ) { ## no critic
print STDERR "ERROR: XML.pm $@\n";
}
# set cache
if ( $Param{Cache} && $Content ) {
$CacheObject->Set(
Type => 'XML',
Key => "$Param{Type}-$Param{Key}",
Value => \@XMLHash,
TTL => 24 * 60 * 60,
# Don't store complex structure in memory as it will be modified later.
CacheInMemory => 0,
);
}
return @XMLHash;
}
=head2 XMLHashDelete()
delete an XMLHash from the database
$XMLObject->XMLHashDelete(
Type => 'SomeType',
Key => '123',
);
=cut
sub XMLHashDelete {
my ( $Self, %Param ) = @_;
# check needed stuff
for (qw(Type Key)) {
if ( !defined $Param{$_} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $_!"
);
return;
}
}
# remove cache
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
Type => 'XML',
Key => "$Param{Type}-$Param{Key}",
);
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
return if !$DBObject->Do(
SQL => 'DELETE FROM xml_storage WHERE xml_type = ? AND xml_key = ?',
Bind => [ \$Param{Type}, \$Param{Key} ],
);
return 1;
}
=head2 XMLHashMove()
move an XMLHash from one type or/and key to another
$XMLObject->XMLHashMove(
OldType => 'SomeType',
OldKey => '123',
NewType => 'NewType',
NewKey => '321',
);
=cut
sub XMLHashMove {
my ( $Self, %Param ) = @_;
# check needed stuff
for (qw(OldType OldKey NewType NewKey)) {
if ( !$Param{$_} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $_!"
);
return;
}
}
# get cache object
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
# remove cache
$CacheObject->Delete(
Type => 'XML',
Key => "$Param{OldType}-$Param{OldKey}",
);
$CacheObject->Delete(
Type => 'XML',
Key => "$Param{NewType}-$Param{NewKey}",
);
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
# delete existing xml hash
$DBObject->Do(
SQL => 'DELETE FROM xml_storage WHERE xml_type = ? AND xml_key = ?',
Bind => [ \$Param{NewType}, \$Param{NewKey} ],
);
# update xml hash
return if !$DBObject->Do(
SQL => 'UPDATE xml_storage SET xml_type = ?, xml_key = ? '
. 'WHERE xml_type = ? AND xml_key = ?',
Bind => [ \$Param{NewType}, \$Param{NewKey}, \$Param{OldType}, \$Param{OldKey} ],
);
return 1;
}
=head2 XMLHashSearch()
Search an XMLHash in the database.
my @Keys = $XMLObject->XMLHashSearch(
Type => 'SomeType',
What => [
# each array element is a and condition
{
# or condition in hash
"[%]{'ElementA'}[%]{'ElementB'}[%]{'Content'}" => '%contentA%',
"[%]{'ElementA'}[%]{'ElementC'}[%]{'Content'}" => '%contentA%',
},
{
"[%]{'ElementA'}[%]{'ElementB'}[%]{'Content'}" => '%contentB%',
"[%]{'ElementA'}[%]{'ElementC'}[%]{'Content'}" => '%contentB%',
},
{
# use array reference if different content with same key was searched
"[%]{'ElementA'}[%]{'ElementB'}[%]{'Content'}" => ['%contentC%', '%contentD%', '%contentE%'],
"[%]{'ElementA'}[%]{'ElementC'}[%]{'Content'}" => ['%contentC%', '%contentD%', '%contentE%'],
},
],
);
=cut
sub XMLHashSearch {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Type} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Type!'
);
return;
}
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
return if !$DBObject->Prepare(
SQL => 'SELECT DISTINCT(xml_key) FROM xml_storage WHERE xml_type = ?',
Bind => [ \$Param{Type} ],
);
# the keys of this hash will be returned
my %Hash;
# initially all keys with the correct type are possible
while ( my @Data = $DBObject->FetchrowArray() ) {
$Hash{ $Data[0] } = 1;
}
if ( $Param{What} && ref $Param{What} eq 'ARRAY' ) {
# get like escape string needed for some databases (e.g. oracle)
my $LikeEscapeString = $DBObject->GetDatabaseFunction('LikeEscapeString');
# the array elements are 'and' combined
for my $And ( @{ $Param{What} } ) {
# the key/value pairs are 'or' combined
my @OrConditions;
for my $Key ( sort keys %{$And} ) {
my $Value = $DBObject->Quote( $And->{$Key} );
$Key = $DBObject->Quote( $Key, 'Like' );
if ( $Value && ref $Value eq 'ARRAY' ) {
# when an array of possible values is given,
# we use 'LIKE'-conditions and combine them with 'OR'
for my $Element ( @{$Value} ) {
$Element = $DBObject->Quote( $Element, 'Like' );
push @OrConditions,
" (xml_content_key LIKE '$Key' $LikeEscapeString "
. "AND xml_content_value LIKE '$Element' $LikeEscapeString)";
}
}
else {
# when a single possible value is given,
# we use a 'LIKE'-condition
$Value = $DBObject->Quote( $Value, 'Like' );
push @OrConditions,
" (xml_content_key LIKE '$Key' $LikeEscapeString "
. "AND xml_content_value LIKE '$Value' $LikeEscapeString )";
}
}
# assemble the SQL
my $SQL = 'SELECT DISTINCT(xml_key) FROM xml_storage WHERE xml_type = ? ';
if (@OrConditions) {
$SQL .= 'AND ( ' . join( ' OR ', @OrConditions ) . ' ) ';
}
# execute
$DBObject->Prepare(
SQL => $SQL,
Bind => [ \$Param{Type} ],
);
# intersection between the current key set, and the keys from the last 'SELECT'
# only the keys which are in all results survive
my %HashNew;
while ( my @Data = $DBObject->FetchrowArray() ) {
if ( $Hash{ $Data[0] } ) {
$HashNew{ $Data[0] } = 1;
}
}
%Hash = %HashNew;
}
}
my @Keys = keys %Hash;
return @Keys;
}
=head2 XMLHashList()
generate a list of XMLHashes in the database
my @Keys = $XMLObject->XMLHashList(
Type => 'SomeType',
);
=cut
sub XMLHashList {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Type} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Type!'
);
return;
}
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
return if !$DBObject->Prepare(
SQL => 'SELECT distinct(xml_key) FROM xml_storage WHERE xml_type = ?',
Bind => [ \$Param{Type} ],
);
my @Keys;
while ( my @Data = $DBObject->FetchrowArray() ) {
push @Keys, $Data[0];
}
return @Keys;
}
=head2 XMLHash2XML()
generate an XML string from an XMLHash
my $XMLString = $XMLObject->XMLHash2XML(@XMLHash);
=cut
sub XMLHash2XML {
my ( $Self, @XMLHash ) = @_;
my $Output = '' . "\n";
$Self->{XMLHash2XMLLayer} = 0;
for my $Key (@XMLHash) {
$Output .= $Self->_ElementBuild( %{$Key} );
}
return $Output;
}
=head2 XMLParse2XMLHash()
parse an XML file and return an XMLHash structure
my @XMLHash = $XMLObject->XMLParse2XMLHash( String => $FileString );
XML:
====
Example Inc.
info@exampe.com1234.com
sales@example.com
+49-999-99999
ARRAY:
======
@XMLHash = (
undef,
{
Contact => [
undef,
{
role => 'admin',
type => 'organization',
Name => [
undef,
{
Content => 'Example Inc.',
type => 'long',
},
],
Email => [
undef,
{
type => 'primary',
Content => 'info@exampe.com',
Domain => [
undef,
{
Content => '1234.com',
},
],
},
{
type => 'secondary',
Content => 'sales@exampe.com',
},
],
Telephone => [
undef,
{
country => 'germany',
Content => '+49-999-99999',
},
],
}
],
}
);
$XMLHash[1]{Contact}[1]{TagKey} = "[1]{'Contact'}[1]";
$XMLHash[1]{Contact}[1]{role} = "admin";
$XMLHash[1]{Contact}[1]{type} = "organization";
$XMLHash[1]{Contact}[1]{Name}[1]{TagKey} = "[1]{'Contact'}[1]{'Name'}[1]";
$XMLHash[1]{Contact}[1]{Name}[1]{Content} = "Example Inc.";
$XMLHash[1]{Contact}[1]{Name}[1]{type} = "long";
$XMLHash[1]{Contact}[1]{Email}[1]{TagKey} = "[1]{'Contact'}[1]{'Email'}[1]";
$XMLHash[1]{Contact}[1]{Email}[1]{Content} = "info\@exampe.com";
$XMLHash[1]{Contact}[1]{Email}[1]{Domain}[1]{TagKey} = "[1]{'Contact'}[1]{'Email'}[1]{'Domain'}[1]";
$XMLHash[1]{Contact}[1]{Email}[1]{Domain}[1]{Content} = "1234.com";
$XMLHash[1]{Contact}[1]{Email}[2]{TagKey} = "[1]{'Contact'}[1]{'Email'}[2]";
$XMLHash[1]{Contact}[1]{Email}[2]{type} = "secondary";
$XMLHash[1]{Contact}[1]{Email}[2]{Content} = "sales\@exampe.com";
=cut
sub XMLParse2XMLHash {
my ( $Self, %Param ) = @_;
my @XMLStructure = $Self->XMLParse(%Param);
return () if !@XMLStructure;
my @XMLHash = ( undef, $Self->XMLStructure2XMLHash( XMLStructure => \@XMLStructure ) );
return @XMLHash;
}
=head2 XMLHash2D()
returns a simple hash with tag keys as keys and the values of C as values.
As a side effect the data structure C is enriched with tag keys.
my %Hash = $XMLObject->XMLHash2D( XMLHash => \@XMLHash );
For example:
$Hash{"[1]{'Planet'}[1]{'Content'}"'} = 'Sun';
=cut
sub XMLHash2D {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !defined $Param{XMLHash} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'XMLHash not defined!',
);
return;
}
$Self->{XMLLevel} = 0;
$Self->{XMLTagCount} = 0;
$Self->{XMLHash} = {};
$Self->{XMLHashReturn} = 1;
undef $Self->{XMLLevelTag};
undef $Self->{XMLLevelCount};
my $Count = 0;
for my $Item ( @{ $Param{XMLHash} } ) {
if ( ref $Item eq 'HASH' ) {
for ( sort keys %{$Item} ) {
$Self->_XMLHash2D(
Key => $Item->{Tag},
Item => $Item,
Counter => $Count
);
}
}
$Count++;
}
$Self->{XMLHashReturn} = 0;
return %{ $Self->{XMLHash} };
}
=head2 XMLStructure2XMLHash()
get an @XMLHash from a @XMLStructure with current TagKey param
my @XMLHash = $XMLObject->XMLStructure2XMLHash( XMLStructure => \@XMLStructure );
=cut
sub XMLStructure2XMLHash {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !defined $Param{XMLStructure} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'XMLStructure not defined!'
);
return;
}
$Self->{Tll} = 0;
$Self->{XMLTagCount} = 0;
$Self->{XMLHash2} = {};
$Self->{XMLHashReturn} = 1;
undef $Self->{XMLLevelTag};
undef $Self->{XMLLevelCount};
for my $Item ( @{ $Param{XMLStructure} } ) {
if ( ref $Item eq 'HASH' ) {
$Self->_XMLStructure2XMLHash(
Key => $Item->{Tag},
Item => $Item,
Type => 'ARRAY'
);
}
}
$Self->{XMLHashReturn} = 0;
return ( \%{ $Self->{XMLHash2} } );
}
=head2 XMLParse()
parse an XML file
my @XMLStructure = $XMLObject->XMLParse( String => $FileString );
my @XMLStructure = $XMLObject->XMLParse( String => \$FileStringScalar );
=cut
sub XMLParse {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !defined $Param{String} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'String not defined!'
);
return;
}
# check input type
if ( ref $Param{String} ) {
$Param{String} = ${ $Param{String} };
}
# get encode object
my $EncodeObject = $Kernel::OM->Get('Kernel::System::Encode');
# create checksum
my $CookedString = $Param{String};
$EncodeObject->EncodeOutput( \$CookedString );
my $MD5Object = Digest::MD5->new();
$MD5Object->add($CookedString);
my $Checksum = $MD5Object->hexdigest();
# get cache object
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
# check cache
if ($Checksum) {
# set CacheInMemory to 0 to prevent modification of the cache from outside
# See bug#[12761](https://bugs.otrs.org/show_bug.cgi?id=12761) for further details
my $Cache = $CacheObject->Get(
Type => 'XMLParse',
Key => $Checksum,
CacheInMemory => 0,
);
return @{$Cache} if $Cache;
}
# cleanup global vars
undef $Self->{XMLARRAY};
$Self->{XMLLevel} = 0;
$Self->{XMLTagCount} = 0;
undef $Self->{XMLLevelTag};
undef $Self->{XMLLevelCount};
# convert string
if ( $Param{String} =~ /(<.+?>)/ ) {
if ( $1 !~ /(utf-8|utf8)/i && $1 =~ /encoding=('|")(.+?)('|")/i ) {
my $SourceCharset = $2;
$Param{String} =~ s/$SourceCharset/utf-8/i;
$Param{String} = $EncodeObject->Convert(
Text => $Param{String},
From => $SourceCharset,
To => 'utf-8',
Force => 1,
);
}
}
# load parse package and parse
my $UseFallback = 1;
if ( eval 'require XML::Parser' ) { ## no critic
my $Parser = XML::Parser->new(
Handlers => {
Start => sub { $Self->_HS(@_); },
End => sub { $Self->_ES(@_); },
Char => sub { $Self->_CS(@_); },
ExternEnt => sub { return '' }, # suppress loading of external entities
},
);
# get sourcename now to avoid a possible race condition where
# $@ could get altered after a failing eval!
my $Sourcename = $Param{Sourcename} ? "\n\n($Param{Sourcename})" : '';
if ( eval { $Parser->parse( $Param{String} ) } ) {
$UseFallback = 0;
# remember, XML::Parser is managing e. g. & by it self
$Self->{XMLQuote} = 0;
}
else {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "C-Parser: $@!$Sourcename"
);
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message =>
"XML::Parser had errors, falling back to XML::Parser::Lite. Offending XML was: $Param{String}",
);
}
}
if ($UseFallback) {
require XML::Parser::Lite; ## no critic
my $Parser = XML::Parser::Lite->new(
Handlers => {
Start => sub { $Self->_HS(@_); },
End => sub { $Self->_ES(@_); },
Char => sub { $Self->_CS(@_); },
ExternEnt => sub { return '' }, # suppress loading of external entities
},
);
$Parser->parse( $Param{String} );
# remember, XML::Parser::Lite is managing e. g. & NOT by it self
$Self->{XMLQuote} = 1;
}
# quote
for my $XMLElement ( @{ $Self->{XMLARRAY} } ) {
$Self->_Decode($XMLElement);
}
# set cache
if ($Checksum) {
# set CacheInMemory to 0 to prevent modification of the cache from outside
# See bug#[12761](https://bugs.otrs.org/show_bug.cgi?id=12761) for further details
$CacheObject->Set(
Type => 'XMLParse',
Key => $Checksum,
Value => $Self->{XMLARRAY},
TTL => 30 * 24 * 60 * 60,
CacheInMemory => 0,
);
}
return @{ $Self->{XMLARRAY} };
}
=begin Internal:
=head2 _XMLHashAddAutoIncrement()
Generate a new integer key.
All keys for that type must be integers.
my $Key = $XMLObject->_XMLHashAddAutoIncrement(
Type => 'SomeType',
KeyAutoIncrement => 1,
);
=cut
sub _XMLHashAddAutoIncrement {
my ( $Self, %Param ) = @_;
my $KeyAutoIncrement = 0;
my @KeysExists;
# check needed stuff
for (qw(Type KeyAutoIncrement)) {
if ( !$Param{$_} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $_!"
);
return;
}
}
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
return if !$DBObject->Prepare(
SQL => 'SELECT DISTINCT(xml_key) FROM xml_storage WHERE xml_type = ?',
Bind => [ \$Param{Type} ],
);
while ( my @Data = $DBObject->FetchrowArray() ) {
if ( $Data[0] ) {
push @KeysExists, $Data[0];
}
}
for my $Key (@KeysExists) {
if ( $Key !~ /^\d{1,99}$/ ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No KeyAutoIncrement possible, no int key exists ($Key)!",
);
return;
}
if ( $Key > $KeyAutoIncrement ) {
$KeyAutoIncrement = $Key;
}
}
$KeyAutoIncrement++;
return $KeyAutoIncrement;
}
sub _ElementBuild {
my ( $Self, %Param ) = @_;
my @Tag;
my @Sub;
my $Output = '';
if ( $Param{Key} ) {
$Self->{XMLHash2XMLLayer}++;
$Output .= "<$Param{Key}";
}
for ( sort keys %Param ) {
if ( ref $Param{$_} eq 'ARRAY' ) {
push @Tag, $_;
push @Sub, $Param{$_};
}
elsif ( $_ ne 'Content' && $_ ne 'Key' && $_ !~ /^Tag/ ) {
if ( defined $Param{$_} ) {
$Param{$_} =~ s/&/&/g;
$Param{$_} =~ s/</g;
$Param{$_} =~ s/>/>/g;
$Param{$_} =~ s/"/"/g;
}
$Output .= " $_=\"$Param{$_}\"";
}
}
if ( $Param{Key} ) {
$Output .= '>';
}
if ( defined $Param{Content} ) {
# encode
$Param{Content} =~ s/&/&/g;
$Param{Content} =~ s/</g;
$Param{Content} =~ s/>/>/g;
$Param{Content} =~ s/"/"/g;
$Output .= $Param{Content};
}
else {
$Output .= "\n";
}
for ( 0 .. $#Sub ) {
for my $K ( @{ $Sub[$_] } ) {
if ( defined $K ) {
$Output .= $Self->_ElementBuild(
%{$K},
Key => $Tag[$_],
);
}
}
}
if ( $Param{Key} ) {
$Output .= "$Param{Key}>\n";
$Self->{XMLHash2XMLLayer} = $Self->{XMLHash2XMLLayer} - 1;
}
return $Output;
}
sub _XMLHash2D {
my ( $Self, %Param ) = @_;
if ( !defined $Param{Item} ) {
return '';
}
elsif ( ref $Param{Item} eq 'HASH' ) {
$Self->{XMLLevel}++;
$Self->{XMLTagCount}++;
$Self->{XMLLevelTag}->{ $Self->{XMLLevel} } = $Param{Key};
if ( $Self->{Tll} && $Self->{Tll} > $Self->{XMLLevel} ) {
for ( ( $Self->{XMLLevel} + 1 ) .. 30 ) {
undef $Self->{XMLLevelCount}->{$_}; #->{$Element} = 0;
}
}
$Self->{XMLLevelCount}->{ $Self->{XMLLevel} }->{ $Param{Key} || '' }++;
# remember old level
$Self->{Tll} = $Self->{XMLLevel};
my $Key = "[$Param{Counter}]";
for ( 2 .. ( $Self->{XMLLevel} ) ) {
$Key .= "{'$Self->{XMLLevelTag}->{$_}'}";
$Key .= "[" . $Self->{XMLLevelCount}->{$_}->{ $Self->{XMLLevelTag}->{$_} } . "]";
}
# add tag key to the passed in data structure
$Param{Item}->{TagKey} = $Key;
for ( sort keys %{ $Param{Item} } ) {
if ( defined $Param{Item}->{$_} && ref $Param{Item}->{$_} ne 'ARRAY' ) {
$Self->{XMLHash}->{ $Key . "{'$_'}" } = $Param{Item}->{$_};
}
$Self->_XMLHash2D(
Key => $_,
Item => $Param{Item}->{$_},
Counter => $Param{Counter}
);
}
$Self->{XMLLevel} = $Self->{XMLLevel} - 1;
}
elsif ( ref $Param{Item} eq 'ARRAY' ) {
for ( @{ $Param{Item} } ) {
$Self->_XMLHash2D(
Key => $Param{Key},
Item => $_,
Counter => $Param{Counter}
);
}
}
return 1;
}
sub _XMLStructure2XMLHash {
my ( $Self, %Param ) = @_;
my $Output = '';
if ( !defined $Param{Item} ) {
return;
}
elsif ( ref $Param{Item} eq 'HASH' ) {
if ( $Param{Item}->{TagType} eq 'End' ) {
return '';
}
$Self->{XMLTagCount}++;
$Self->{XMLLevelTag}->{ $Param{Item}->{TagLevel} } = $Param{Key};
if ( $Self->{Tll} && $Self->{Tll} > $Param{Item}->{TagLevel} ) {
for ( ( $Param{Item}->{TagLevel} + 1 ) .. 30 ) {
undef $Self->{XMLLevelCount}->{$_};
}
}
$Self->{XMLLevelCount}->{ $Param{Item}->{TagLevel} }->{ $Param{Key} }++;
# remember old level
$Self->{Tll} = $Param{Item}->{TagLevel};
if ( $Param{Item}->{TagLevel} == 1 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 2 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 3 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 4 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 5 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 6 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 7 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 8 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 9 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 10 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]
->{ $Self->{XMLLevelTag}->{10} }
->[ $Self->{XMLLevelCount}->{10}->{ $Self->{XMLLevelTag}->{10} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 11 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]
->{ $Self->{XMLLevelTag}->{10} }
->[ $Self->{XMLLevelCount}->{10}->{ $Self->{XMLLevelTag}->{10} } ]
->{ $Self->{XMLLevelTag}->{11} }
->[ $Self->{XMLLevelCount}->{11}->{ $Self->{XMLLevelTag}->{11} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 12 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]
->{ $Self->{XMLLevelTag}->{10} }
->[ $Self->{XMLLevelCount}->{10}->{ $Self->{XMLLevelTag}->{10} } ]
->{ $Self->{XMLLevelTag}->{11} }
->[ $Self->{XMLLevelCount}->{11}->{ $Self->{XMLLevelTag}->{11} } ]
->{ $Self->{XMLLevelTag}->{12} }
->[ $Self->{XMLLevelCount}->{12}->{ $Self->{XMLLevelTag}->{12} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 13 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]
->{ $Self->{XMLLevelTag}->{10} }
->[ $Self->{XMLLevelCount}->{10}->{ $Self->{XMLLevelTag}->{10} } ]
->{ $Self->{XMLLevelTag}->{11} }
->[ $Self->{XMLLevelCount}->{11}->{ $Self->{XMLLevelTag}->{11} } ]
->{ $Self->{XMLLevelTag}->{12} }
->[ $Self->{XMLLevelCount}->{12}->{ $Self->{XMLLevelTag}->{12} } ]
->{ $Self->{XMLLevelTag}->{13} }
->[ $Self->{XMLLevelCount}->{13}->{ $Self->{XMLLevelTag}->{13} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 14 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]
->{ $Self->{XMLLevelTag}->{10} }
->[ $Self->{XMLLevelCount}->{10}->{ $Self->{XMLLevelTag}->{10} } ]
->{ $Self->{XMLLevelTag}->{11} }
->[ $Self->{XMLLevelCount}->{11}->{ $Self->{XMLLevelTag}->{11} } ]
->{ $Self->{XMLLevelTag}->{12} }
->[ $Self->{XMLLevelCount}->{12}->{ $Self->{XMLLevelTag}->{12} } ]
->{ $Self->{XMLLevelTag}->{13} }
->[ $Self->{XMLLevelCount}->{13}->{ $Self->{XMLLevelTag}->{13} } ]
->{ $Self->{XMLLevelTag}->{14} }
->[ $Self->{XMLLevelCount}->{14}->{ $Self->{XMLLevelTag}->{14} } ]->{$_} = $Param{Item}->{$_};
}
}
}
elsif ( $Param{Item}->{TagLevel} == 15 ) {
for ( sort keys %{ $Param{Item} } ) {
if ( !defined $Param{Item}->{$_} ) {
$Param{Item}->{$_} = '';
}
if ( $_ !~ /^Tag/ ) {
$Self->{XMLHash2}->{ $Self->{XMLLevelTag}->{1} }
->[ $Self->{XMLLevelCount}->{1}->{ $Self->{XMLLevelTag}->{1} } ]
->{ $Self->{XMLLevelTag}->{2} }
->[ $Self->{XMLLevelCount}->{2}->{ $Self->{XMLLevelTag}->{2} } ]
->{ $Self->{XMLLevelTag}->{3} }
->[ $Self->{XMLLevelCount}->{3}->{ $Self->{XMLLevelTag}->{3} } ]
->{ $Self->{XMLLevelTag}->{4} }
->[ $Self->{XMLLevelCount}->{4}->{ $Self->{XMLLevelTag}->{4} } ]
->{ $Self->{XMLLevelTag}->{5} }
->[ $Self->{XMLLevelCount}->{5}->{ $Self->{XMLLevelTag}->{5} } ]
->{ $Self->{XMLLevelTag}->{6} }
->[ $Self->{XMLLevelCount}->{6}->{ $Self->{XMLLevelTag}->{6} } ]
->{ $Self->{XMLLevelTag}->{7} }
->[ $Self->{XMLLevelCount}->{7}->{ $Self->{XMLLevelTag}->{7} } ]
->{ $Self->{XMLLevelTag}->{8} }
->[ $Self->{XMLLevelCount}->{8}->{ $Self->{XMLLevelTag}->{8} } ]
->{ $Self->{XMLLevelTag}->{9} }
->[ $Self->{XMLLevelCount}->{9}->{ $Self->{XMLLevelTag}->{9} } ]
->{ $Self->{XMLLevelTag}->{10} }
->[ $Self->{XMLLevelCount}->{10}->{ $Self->{XMLLevelTag}->{10} } ]
->{ $Self->{XMLLevelTag}->{11} }
->[ $Self->{XMLLevelCount}->{11}->{ $Self->{XMLLevelTag}->{11} } ]
->{ $Self->{XMLLevelTag}->{12} }
->[ $Self->{XMLLevelCount}->{12}->{ $Self->{XMLLevelTag}->{12} } ]
->{ $Self->{XMLLevelTag}->{13} }
->[ $Self->{XMLLevelCount}->{13}->{ $Self->{XMLLevelTag}->{13} } ]
->{ $Self->{XMLLevelTag}->{14} }
->[ $Self->{XMLLevelCount}->{14}->{ $Self->{XMLLevelTag}->{14} } ]
->{ $Self->{XMLLevelTag}->{15} }
->[ $Self->{XMLLevelCount}->{15}->{ $Self->{XMLLevelTag}->{15} } ]->{$_} = $Param{Item}->{$_};
}
}
}
}
return 1;
}
sub _Decode {
my ( $Self, $A ) = @_;
# get encode object
my $EncodeObject = $Kernel::OM->Get('Kernel::System::Encode');
for ( sort keys %{$A} ) {
if ( ref $A->{$_} eq 'ARRAY' ) {
for my $B ( @{ $A->{$_} } ) {
$Self->_Decode($B);
}
}
# decode
elsif ( defined $A->{$_} ) {
# check if decode is already done by parser
if ( $Self->{XMLQuote} ) {
my %Map = (
'amp' => '&',
'lt' => '<',
'gt' => '>',
'quot' => '"',
);
$A->{$_} =~ s/&(amp|lt|gt|quot);/$Map{$1}/g;
}
# convert into default charset
$A->{$_} = $EncodeObject->Convert(
Text => $A->{$_},
From => 'utf-8',
To => 'utf-8',
Force => 1,
);
}
}
return 1;
}
sub _HS {
my ( $Self, $Expat, $Element, %Attr ) = @_;
if ( $Self->{LastTag} ) {
push @{ $Self->{XMLARRAY} }, { %{ $Self->{LastTag} }, Content => $Self->{C} };
}
undef $Self->{LastTag};
undef $Self->{C};
$Self->{XMLLevel}++;
$Self->{XMLTagCount}++;
$Self->{XMLLevelTag}->{ $Self->{XMLLevel} } = $Element;
if ( $Self->{Tll} && $Self->{Tll} > $Self->{XMLLevel} ) {
for ( ( $Self->{XMLLevel} + 1 ) .. 30 ) {
undef $Self->{XMLLevelCount}->{$_};
}
}
$Self->{XMLLevelCount}->{ $Self->{XMLLevel} }->{$Element}++;
# remember old level
$Self->{Tll} = $Self->{XMLLevel};
my $Key = '';
for ( 1 .. ( $Self->{XMLLevel} ) ) {
$Key .= "{'$Self->{XMLLevelTag}->{$_}'}";
$Key .= "[" . $Self->{XMLLevelCount}->{$_}->{ $Self->{XMLLevelTag}->{$_} } . "]";
}
$Self->{LastTag} = {
%Attr,
TagType => 'Start',
Tag => $Element,
TagLevel => $Self->{XMLLevel},
TagCount => $Self->{XMLTagCount},
TagLastLevel => $Self->{XMLLevelTag}->{ ( $Self->{XMLLevel} - 1 ) },
};
return 1;
}
sub _CS {
my ( $Self, $Expat, $Element, $I, $II ) = @_;
if ( $Self->{LastTag} ) {
$Self->{C} .= $Element;
}
return 1;
}
sub _ES {
my ( $Self, $Expat, $Element ) = @_;
$Self->{XMLTagCount}++;
if ( $Self->{LastTag} ) {
push @{ $Self->{XMLARRAY} }, { %{ $Self->{LastTag} }, Content => $Self->{C} };
}
undef $Self->{LastTag};
undef $Self->{C};
push(
@{ $Self->{XMLARRAY} },
{
TagType => 'End',
TagLevel => $Self->{XMLLevel},
TagCount => $Self->{XMLTagCount},
Tag => $Element
},
);
$Self->{XMLLevel} = $Self->{XMLLevel} - 1;
return 1;
}
1;
=end Internal:
=head1 TERMS AND CONDITIONS
This software is part of the OTRS project (L).
This software comes with ABSOLUTELY NO WARRANTY. For details, see
the enclosed file COPYING for license information (GPL). If you
did not receive this file, see L.
=cut