.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
. if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{\
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "XML::Hash::XS 3pm"
.TH XML::Hash::XS 3pm "2021-02-18" "perl v5.32.1" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
XML::Hash::XS \- Simple and fast hash to XML and XML to hash conversion written in C
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 1
\& use XML::Hash::XS;
\&
\& my $xmlstr = hash2xml \e%hash;
\& hash2xml \e%hash, output => $fh;
\&
\& my $hash = xml2hash $xmlstr;
\& my $hash = xml2hash \e$xmlstr;
\& my $hash = xml2hash \*(Aqtest.xml\*(Aq, encoding => \*(Aqcp1251\*(Aq;
\& my $hash = xml2hash $fh;
\& my $hash = xml2hash *STDIN;
.Ve
.PP
Or \s-1OOP\s0 way:
.PP
.Vb 1
\& use XML::Hash::XS qw();
\&
\& my $conv = XML::Hash::XS\->new(utf8 => 0, encoding => \*(Aqutf\-8\*(Aq)
\& my $xmlstr = $conv\->hash2xml(\e%hash, utf8 => 1);
\& my $hash = $conv\->xml2hash($xmlstr, encoding => \*(Aqcp1251\*(Aq);
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This module implements simple hash to \s-1XML\s0 and \s-1XML\s0 to hash conversion written in C.
.PP
During conversion uses minimum of memory, \s-1XML\s0 or hash is written directly without building \s-1DOM.\s0
.PP
Some features are optional and are available with appropriate libraries:
.IP "\(bu" 2
XML::LibXML library is required in order to build \s-1DOM\s0
.IP "\(bu" 2
\&\s-1ICU\s0 or iconv library is required in order to perform charset conversions
.SH "FUNCTIONS"
.IX Header "FUNCTIONS"
.ie n .SS "hash2xml $hash, [ %options ]"
.el .SS "hash2xml \f(CW$hash\fP, [ \f(CW%options\fP ]"
.IX Subsection "hash2xml $hash, [ %options ]"
\&\f(CW$hash\fR is reference to hash
.PP
.Vb 11
\& hash2xml
\& {
\& node1 => \*(Aqvalue1\*(Aq,
\& node2 => [ \*(Aqvalue21\*(Aq, { node22 => \*(Aqvalue22\*(Aq } ],
\& node3 => \e\*(Aqvalue3\*(Aq,
\& node4 => sub { return \*(Aqvalue4\*(Aq },
\& node5 => sub { return { node51 => \*(Aqvalue51\*(Aq } },
\& },
\& canonical => 1,
\& indent => 2,
\& ;
.Ve
.PP
will convert to:
.PP
.Vb 10
\&
\&
\& value1
\& value21
\&
\& value22
\&
\& value3
\& value4
\&
\& value51
\&
\&
.Ve
.PP
and (use_attr=1):
.PP
.Vb 12
\& hash2xml
\& {
\& node1 => \*(Aqvalue1\*(Aq,
\& node2 => [ \*(Aqvalue21\*(Aq, { node22 => \*(Aqvalue22\*(Aq } ],
\& node3 => \e\*(Aqvalue3\*(Aq,
\& node4 => sub { return \*(Aqvalue4\*(Aq },
\& node5 => sub { return { node51 => \*(Aqvalue51\*(Aq } },
\& },
\& use_attr => 1,
\& canonical => 1,
\& indent => 2,
\& ;
.Ve
.PP
will convert to:
.PP
.Vb 6
\&
\&
\& value21
\&
\&
\&
.Ve
.ie n .SS "xml2hash $xml, [ %options ]"
.el .SS "xml2hash \f(CW$xml\fP, [ \f(CW%options\fP ]"
.IX Subsection "xml2hash $xml, [ %options ]"
\&\f(CW$xml\fR may be string, reference to string, file handle or tied file handle:
.PP
.Vb 2
\& xml2hash \*(Aqtext\*(Aq;
\& # output: \*(Aqtext\*(Aq
\&
\& xml2hash \*(Aqtext\*(Aq;
\& # output: { a => \*(Aq1\*(Aq, b => \*(Aq2\*(Aq, content => \*(Aqtext\*(Aq }
\&
\& open(my $fh, \*(Aq<\*(Aq, \*(Aqtest.xml\*(Aq);
\& xml2hash $fh;
\&
\& xml2hash *STDIN;
.Ve
.SH "OPTIONS"
.IX Header "OPTIONS"
.IP "doc [ => 0 ] \fI# hash2xml\fR" 4
.IX Item "doc [ => 0 ] # hash2xml"
if doc is '1', then returned value is XML::LibXML::Document.
.IP "root [ = 'root' ] \fI# hash2xml\fR" 4
.IX Item "root [ = 'root' ] # hash2xml"
Root node name.
.IP "version [ = '1.0' ] \fI# hash2xml\fR" 4
.IX Item "version [ = '1.0' ] # hash2xml"
\&\s-1XML\s0 document version
.IP "encoding [ = 'utf\-8' ] \fI# hash2xml+xml2hash\fR" 4
.IX Item "encoding [ = 'utf-8' ] # hash2xml+xml2hash"
\&\s-1XML\s0 input/output encoding
.IP "indent [ = 0 ] \fI# hash2xml\fR" 4
.IX Item "indent [ = 0 ] # hash2xml"
if indent great than \*(L"0\*(R", \s-1XML\s0 output should be indented according to its hierarchic structure.
This value determines the number of spaces.
.Sp
if indent is \*(L"0\*(R", \s-1XML\s0 output will all be on one line.
.IP "output [ = undef ] \fI# hash2xml\fR" 4
.IX Item "output [ = undef ] # hash2xml"
\&\s-1XML\s0 output method
.Sp
if output is undefined, \s-1XML\s0 document dumped into string.
.Sp
if output is \s-1FH, XML\s0 document writes directly to a filehandle or a stream.
.IP "canonical [ = 0 ] \fI# hash2xml\fR" 4
.IX Item "canonical [ = 0 ] # hash2xml"
if canonical is \*(L"1\*(R", converter will be write hashes sorted by key.
.Sp
if canonical is \*(L"0\*(R", order of the element will be pseudo-randomly.
.IP "use_attr [ = 0 ] \fI# hash2xml\fR" 4
.IX Item "use_attr [ = 0 ] # hash2xml"
if use_attr is \*(L"1\*(R", converter will be use the attributes.
.Sp
if use_attr is \*(L"0\*(R", converter will be use tags only.
.IP "content [ = undef ] \fI# hash2xml+xml2hash\fR" 4
.IX Item "content [ = undef ] # hash2xml+xml2hash"
if defined that the key name for the text content(used only if use_attr=1).
.IP "force_array => [ = undef ] \fI# xml2hash\fR" 4
.IX Item "force_array => [ = undef ] # xml2hash"
This option is similar to \*(L"ForceArray\*(R" from XML::Simple module: .
.IP "force_content => [ = 0 ] \fI# xml2hash\fR" 4
.IX Item "force_content => [ = 0 ] # xml2hash"
This option is similar to \*(L"ForceContent\*(R" from XML::Simple module: .
.IP "merge_text [ = 0 ] \fI# xml2hash\fR" 4
.IX Item "merge_text [ = 0 ] # xml2hash"
Setting this option to \*(L"1\*(R" will cause merge adjacent text nodes.
.IP "xml_decl [ = 1 ] \fI# hash2xml\fR" 4
.IX Item "xml_decl [ = 1 ] # hash2xml"
if xml_decl is \*(L"1\*(R", output will start with the \s-1XML\s0 declaration ''.
.Sp
if xml_decl is \*(L"0\*(R", \s-1XML\s0 declaration will not be output.
.IP "trim [ = 0 ] \fI# hash2xml+xml2hash\fR" 4
.IX Item "trim [ = 0 ] # hash2xml+xml2hash"
Trim leading and trailing whitespace from text nodes.
.IP "suppress_empty => [ = 0 ] \fI# xml2hash\fR" 4
.IX Item "suppress_empty => [ = 0 ] # xml2hash"
This option is similar to \*(L"SuppressEmpty\*(R" from XMl::Simple module: .
.IP "utf8 [ = 1 ] \fI# hash2xml+xml2hash\fR" 4
.IX Item "utf8 [ = 1 ] # hash2xml+xml2hash"
Turn on utf8 flag for strings if enabled.
.IP "max_depth [ = 1024 ] \fI# xml2hash\fR" 4
.IX Item "max_depth [ = 1024 ] # xml2hash"
Maximum recursion depth.
.IP "buf_size [ = 4096 ] \fI# hash2xml+xml2hash\fR" 4
.IX Item "buf_size [ = 4096 ] # hash2xml+xml2hash"
Buffer size for reading end encoding data.
.IP "keep_root [ = 0 ] \fI# xml2hash\fR" 4
.IX Item "keep_root [ = 0 ] # xml2hash"
Keep root element.
.IP "filter [ = undef ] \fI# xml2hash\fR" 4
.IX Item "filter [ = undef ] # xml2hash"
Filter nodes matched by pattern and return reference to array of nodes.
.Sp
Sample:
.Sp
.Vb 7
\& my $xml = <<\*(AqXML\*(Aq;
\&
\& 111
\& 222
\& 333
\&
\& XML
\&
\& my $nodes = xml2hash($xml, filter => \*(Aq/root/item1\*(Aq);
\& # $nodes = [ 111 ]
\&
\& my $nodes = xml2hash($xml, filter => [\*(Aq/root/item1\*(Aq, \*(Aq/root/item2\*(Aq]);
\& # $nodes = [ 111, 222 ]
\&
\& my $nodes = xml2hash($xml, filter => qr[/root/item\ed$]);
\& # $nodes = [ 111, 222, 333 ]
.Ve
.Sp
It may be used to parse large \s-1XML\s0 because does not require a lot of memory.
.IP "cb [ = undef ] \fI# xml2hash\fR" 4
.IX Item "cb [ = undef ] # xml2hash"
This option is used in conjunction with \*(L"filter\*(R" option and defines callback
that will called for each matched node.
.Sp
Sample:
.Sp
.Vb 6
\& xml2hash($xml, filter => qr[/root/item\ed$], cb => sub {
\& print $_[0], "\en";
\& });
\& # 111
\& # 222
\& # 333
.Ve
.IP "method [ = '\s-1NATIVE\s0' ] \fI# hash2xml\fR" 4
.IX Item "method [ = 'NATIVE' ] # hash2xml"
experimental support the conversion methods other libraries
.Sp
if method is '\s-1LX\s0' then conversion result is the same as using XML::Hash::LX library
.Sp
Note: for '\s-1LX\s0' method following additional options are available:
attr
cdata
text
comm
.SH "OBJECT SERIALISATION(hash2xml)"
.IX Header "OBJECT SERIALISATION(hash2xml)"
.ie n .IP "1. When object has a ""toString"" method" 2
.el .IP "1. When object has a ``toString'' method" 2
.IX Item "1. When object has a toString method"
In this case, the method of object is invoked in scalar context.
It must return a single scalar that can be directly encoded into \s-1XML.\s0
.Sp
Example:
.Sp
.Vb 8
\& use XML::LibXML;
\& local $XML::LibXML::skipXMLDeclaration = 1;
\& my $doc = XML::LibXML\->new\->parse_string(\*(Aq\*(Aq);
\& print hash2xml({ doc => $doc }, indent => 2, xml_decl => 0);
\& =>
\&
\&
\&
.Ve
.IP "2. When object has overloaded stringification" 2
.IX Item "2. When object has overloaded stringification"
In this case, the stringification method of object is invoked and result is directly encoded into \s-1XML.\s0
.Sp
Example:
.Sp
.Vb 10
\& package Test {
\& use overload \*(Aq""\*(Aq => sub { shift\->stringify }, fallback => 1;
\& sub new {
\& my ($class, $str) = @_;
\& bless { str => $str }, $class;
\& }
\& sub stringify {
\& shift\->{str}
\& }
\& }
\& my $obj = Test\->new(\*(Aqtest string\*(Aq);
\& print hash2xml({ obj => $obj }, indent => 2, xml_decl => 0);
\& =>
\&
\& test string
\&
.Ve
.ie n .IP "3. When object has a ""iternext"" method (""\s-1NATIVE""\s0 method only)" 2
.el .IP "3. When object has a ``iternext'' method (``\s-1NATIVE''\s0 method only)" 2
.IX Item "3. When object has a iternext method (NATIVE method only)"
In this case, the method method will invoke a few times until the return value is not undefined.
.Sp
Example:
.Sp
.Vb 10
\& my $count = 0;
\& my $o = bless {}, \*(AqIterator\*(Aq;
\& *Iterator::iternext = sub { $count++ < 3 ? { count => $count } : undef };
\& print hash2xml({ item => $o }, use_attr => 1, indent => 2, xml_decl => 0);
\& =>
\&
\&
\&
\&
\&
.Ve
.Sp
This can be used to generate a large \s-1XML\s0 using minimum memory, example with \s-1DBI:\s0
.Sp
.Vb 12
\& my $sth = $dbh\->prepare(\*(AqSELECT * FROM foo WHERE bar=?\*(Aq);
\& $sth\->execute(...);
\& my $o = bless {}, \*(AqIterator\*(Aq;
\& *Iterator::iternext = sub { $sth\->fetchrow_hashref() };
\& open(my $fh, \*(Aq>\*(Aq, \*(Aqdata.xml\*(Aq);
\& hash2xml({ row => $o }, use_attr => 1, indent => 2, xml_decl => 0, output => $fh);
\& =>
\&
\&
\&
\& ...
\&
.Ve
.SH "BENCHMARK"
.IX Header "BENCHMARK"
Performance benchmark in comparison with some popular modules(hash2xml):
.PP
.Vb 5
\& Rate XML::Hash XML::Hash::LX XML::Simple XML::Hash::XS
\& XML::Hash 65.0/s \-\- \-6% \-37% \-99%
\& XML::Hash::LX 68.8/s 6% \-\- \-33% \-99%
\& XML::Simple 103/s 58% 49% \-\- \-98%
\& XML::Hash::XS 4879/s 7404% 6988% 4658% \-\-
.Ve
.PP
Benchmark was done on
.SH "AUTHOR"
.IX Header "AUTHOR"
Yuriy Ustushenko,
.SH "COPYRIGHT AND LICENSE"
.IX Header "COPYRIGHT AND LICENSE"
Copyright (C) 2012\-2021 Yuriy Ustushenko
.PP
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.