NAME

XML::Hash::LX - Convert hash to xml and xml to hash using LibXML

SYNOPSIS

use XML::Hash::LX;

my $hash = xml2hash $xmlstring, attr => '.', text => '~';
my $hash = xml2hash $xmldoc;

my $xmlstr = hash2html $hash, attr => '+', text => '#text';
my $xmldoc = hash2html $hash, doc => 1, attr => '+';

# Usage with XML::LibXML

my $doc = XML::LibXML->new->parse_string($xml);
my $xp  = XML::LibXML::XPathContext->new($doc);
$xp->registerNs('rss', 'http://purl.org/rss/1.0/');

# then process xpath
for ($xp->findnodes('//rss:item')) {
    # and convert to hash concrete nodes
    my $item = xml2hash($_);
    print Dumper+$item
}

DESCRIPTION

This module is a companion for XML::LibXML. It operates with LibXML objects, could return or accept LibXML objects, and may be used for easy data transformations

It is faster in parsing then XML::Simple, XML::Hash, XML::Twig and of course much slower than XML::Bare ;)

It is faster in composing than XML::Hash, but slower than XML::Simple

Parse benchmark:

           Rate   Simple     Hash     Twig Hash::LX     Bare
Simple   11.3/s       --      -2%     -16%     -44%     -97%
Hash     11.6/s       2%       --     -14%     -43%     -97%
Twig     13.5/s      19%      16%       --     -34%     -96%
Hash::LX 20.3/s      79%      75%      51%       --     -95%
Bare      370/s    3162%    3088%    2650%    1721%       --

Compose benchmark:

           Rate     Hash Hash::LX   Simple
Hash     49.2/s       --     -18%     -40%
Hash::LX 60.1/s      22%       --     -26%
Simple   81.5/s      66%      36%       --

Benchmark was done on http://search.cpan.org/uploads.rdf

EXPORT

xml2hash and hash2xml are exported by default

:inject

Inject toHash method in the namespace of XML::LibXML::Node and allow to call it on any subclass of XML::LibXML::Node directly

By default is disabled

use XML::Hash::LX ':inject';

my $doc = XML::LibXML->new->parse_string($xml);
my $hash = $doc->toHash(%opts);

FUNCTIONS

xml2hash $xml, [ OPTIONS ]

XML could be XML::LibXML::Document, XML::LibXML::DocumentPart or string

hash2xml $hash, [ doc => 1, ] [ OPTIONS ]

Id doc option is true, then returned value is XML::LibXML::Document, not string

OPTIONS

Every option could be passed as arguments to function or set as global variable in XML::Hash::LX namespace

%XML::Hash::LX::X2H

Options respecting convertations from xml to hash

order [ = 0 ]

Strictly keep the output order. When enabled, structures become more complex, but xml could be completely reverted

attr [ = '-' ]

Attribute prefix

<node attr="test" />  =>  { node => { -attr => "test" } }
text [ = '#text' ]

Key name for storing text

<node>text<sub /></node>  =>  { node => { sub => '', '#text' => "test" } }
join [ = '' ]

Join separator for text nodes, splitted by subnodes

Ignored when order in effect

# default:
xml2hash( '<item>Test1<sub />Test2</item>' )
: { item => { sub => '', '~' => 'Test1Test2' } };

# global
$XML::Hash::LX::X2H{join} = '+';
xml2hash( '<item>Test1<sub />Test2</item>' )
: { item => { sub => '', '~' => 'Test1+Test2' } };

# argument
xml2hash( '<item>Test1<sub />Test2</item>', join => '+' )
: { item => { sub => '', '~' => 'Test1+Test2' } };
trim [ = 1 ]

Trim leading and trailing whitespace from text nodes

cdata [ = undef ]

When defined, CDATA sections will be stored under this key

# cdata = undef
<node><![CDATA[ test ]]></node>  =>  { node => 'test' }

# cdata = '#'
<node><![CDATA[ test ]]></node>  =>  { node => { '#' => 'test' } }
comm [ = undef ]

When defined, comments sections will be stored under this key

When undef, comments will be ignored

# comm = undef
<node><!-- comm --><sub/></node>  =>  { node => { sub => '' } }

# comm = '/'
<node><!-- comm --><sub/></node>  =>  { node => { sub => '', '/' => 'comm' } }
load_ext_dtd [ = 0 ]

Load the external DTD

# load_ext_dtd = 0
<!DOCTYPE foo [<!ENTITY % ent1 SYSTEM "rm -rf /">%ent1; ]><node> text</node>

# load_ext_dtd = 1
<!DOCTYPE foo [<!ENTITY % ent1 SYSTEM "rm -rf /">%ent1; ]><node> text</node>
oops!
expand_entities [ = 0 ]

Enable XInclude substitution. (See XML::LibXML::Parser)

expand_xinclude [ = 0 ]

Enable entities expansion. (See XML::LibXML::Parser). (Enabling also enables load_ext_dtd)

validation [ = 0 ]

Enable validating with the DTD. (See XML::LibXML::Parser)

no_network [ = 1 ]

Forbid network access; (See XML::LibXML::Parser)

If true, all attempts to fetch non-local resources (such as DTD or external entities) will fail

$XML::Hash::LX::X2A [ = 0 ]

Global array casing

Ignored when X2H{order} in effect

As option should be passed as

xml2hash $xml, array => 1;

Effect:

# $X2A = 0
<node><sub/></node>  =>  { node => { sub => '' } }

# $X2A = 1
<node><sub/></node>  =>  { node => [ { sub => [ '' ] } ] }

%XML::Hash::LX::X2A

By element array casing

Ignored when X2H{order} in effect

As option should be passed as

xml2hash $xml, array => [ nodes list ];

Effect:

# %X2A = ()
<node><sub/></node>  =>  { node => { sub => '' } }

# %X2A = ( sub => 1 )
<node><sub/></node>  =>  { node => { sub => [ '' ] } }

%XML::Hash::LX::H2X

Options respecting convertations from hash to xml

encoding [ = 'utf-8' ]

XML output encoding

attr [ = '-' ]

Attribute prefix

{ node => { -attr => "test", sub => 'test' } }
<node attr="test"><sub>test</sub></node>
text [ = '#text' ]

Key name for storing text

{ node => { sub => '', '#text' => "test" } }
<node>text<sub /></node>
# or 
<node><sub />text</node>
# order of keys is not predictable
trim [ = 1 ]

Trim leading and trailing whitespace from text nodes

# trim = 1
{ node => { sub => [ '    ', 'test' ], '#text' => "test" } }
<node>test<sub>test</sub></node>

# trim = 0
{ node => { sub => [ '    ', 'test' ], '#text' => "test" } }
<node>test<sub>    test</sub></node>
cdata [ = undef ]

When defined, such key elements will be saved as CDATA sections

# cdata = undef
{ node => { '#' => 'test' } } => <node><#>test</#></node> # it's bad ;)

# cdata = '#'
{ node => { '#' => 'test' } } => <node><![CDATA[test]]></node>
comm [ = undef ]

When defined, such key elements will be saved as comment sections

# comm = undef
{ node => { '/' => 'test' } } => <node></>test<//></node> # it's very bad! ;)

# comm = '/'
{ node => { '/' => 'test' } } => <node><!-- test --></node>

BUGS

None known

SEE ALSO

AUTHOR

Mons Anderson, <mons at cpan.org>

LICENSE

Copyright 2009-2020 Mons Anderson, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.