XML-Simple
view release on metacpan or search on metacpan
lib/XML/Simple.pm view on Meta::CPAN
=head1 SYNOPSIS
PLEASE DO NOT USE THIS MODULE IN NEW CODE. If you ignore this
warning and use it anyway, the C<qw(:strict)> mode will save you a little pain.
use XML::Simple qw(:strict);
my $ref = XMLin([<xml file or string>] [, <options>]);
my $xml = XMLout($hashref [, <options>]);
Or the object oriented way:
require XML::Simple qw(:strict);
my $xs = XML::Simple->new([<options>]);
my $ref = $xs->XMLin([<xml file or string>] [, <options>]);
my $xml = $xs->XMLout($hashref [, <options>]);
(or see L<"SAX SUPPORT"> for 'the SAX way').
Note, in these examples, the square brackets are used to denote optional items
not to imply items should be supplied in arrayrefs.
=cut
# See after __END__ for more POD documentation
# Load essentials here, other modules loaded on demand later
use strict;
use warnings;
use warnings::register;
use Carp;
use Scalar::Util qw();
require Exporter;
##############################################################################
# Define some constants
#
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $PREFERRED_PARSER);
@ISA = qw(Exporter);
@EXPORT = qw(XMLin XMLout);
@EXPORT_OK = qw(xml_in xml_out);
my %StrictMode = ();
my @KnownOptIn = qw(keyattr keeproot forcecontent contentkey noattr
searchpath forcearray cache suppressempty parseropts
grouptags nsexpand datahandler varattr variables
normalisespace normalizespace valueattr strictmode);
my @KnownOptOut = qw(keyattr keeproot contentkey noattr
rootname xmldecl outputfile noescape suppressempty
grouptags nsexpand handler noindent attrindent nosort
valueattr numericescape strictmode);
my @DefKeyAttr = qw(name key id);
my $DefRootName = qq(opt);
my $DefContentKey = qq(content);
my $DefXmlDecl = qq(<?xml version='1.0' standalone='yes'?>);
my $xmlns_ns = 'http://www.w3.org/2000/xmlns/';
my $bad_def_ns_jcn = '{' . $xmlns_ns . '}'; # LibXML::SAX workaround
##############################################################################
# Globals for use by caching routines
#
my %MemShareCache = ();
my %MemCopyCache = ();
##############################################################################
# Wrapper for Exporter - handles ':strict'
#
sub import {
# Handle the :strict tag
my($calling_package) = caller();
_strict_mode_for_caller(1) if grep(/^:strict$/, @_);
# Pass everything else to Exporter.pm
@_ = grep(!/^:strict$/, @_);
goto &Exporter::import;
}
##############################################################################
# Constructor for optional object interface.
#
sub new {
my $class = shift;
if(@_ % 2) {
croak "Default options must be name=>value pairs (odd number supplied)";
}
my %known_opt;
@known_opt{@KnownOptIn, @KnownOptOut} = ();
my %raw_opt = @_;
$raw_opt{strictmode} = _strict_mode_for_caller()
unless exists $raw_opt{strictmode};
my %def_opt;
while(my($key, $val) = each %raw_opt) {
my $lkey = lc($key);
$lkey =~ s/_//g;
croak "Unrecognised option: $key" unless(exists($known_opt{$lkey}));
$def_opt{$lkey} = $val;
}
lib/XML/Simple.pm view on Meta::CPAN
# $prefix = $self->{nsup}->get_prefix($uri);
$prefix = $self->{ns_prefix}++;
$self->{nsup}->declare_prefix($prefix, $uri);
$nsdecls .= qq( xmlns:$prefix="$uri");
}
$ref->{"$prefix:$lname"} = $ref->{$qname};
delete($ref->{$qname});
}
}
}
}
my @nested = ();
my $text_content = undef;
if($named) {
push @result, $indent, '<', $name, $nsdecls;
}
if(keys %$ref) {
my $first_arg = 1;
foreach my $key ($self->sorted_keys($name, $ref)) {
my $value = $ref->{$key};
next if(substr($key, 0, 1) eq '-');
if(!defined($value)) {
next if $self->{opt}->{suppressempty};
unless(exists($self->{opt}->{suppressempty})
and !defined($self->{opt}->{suppressempty})
) {
carp 'Use of uninitialized value' if warnings::enabled();
}
if($key eq $self->{opt}->{contentkey}) {
$text_content = '';
}
else {
$value = exists($self->{opt}->{suppressempty}) ? {} : '';
}
}
if(!ref($value)
and $self->{opt}->{valueattr}
and $self->{opt}->{valueattr}->{$key}
) {
$value = $self->new_hashref(
$self->{opt}->{valueattr}->{$key} => $value
);
}
if(ref($value) or $self->{opt}->{noattr}) {
push @nested,
$self->value_to_xml($value, $key, "$indent ");
}
else {
if($key eq $self->{opt}->{contentkey}) {
$value = $self->escape_value($value) unless($self->{opt}->{noescape});
$text_content = $value;
}
else {
$value = $self->escape_attr($value) unless($self->{opt}->{noescape});
push @result, "\n$indent " . ' ' x length($name)
if($self->{opt}->{attrindent} and !$first_arg);
push @result, ' ', $key, '="', $value , '"';
$first_arg = 0;
}
}
}
}
else {
$text_content = '';
}
if(@nested or defined($text_content)) {
if($named) {
push @result, ">";
if(defined($text_content)) {
push @result, $text_content;
$nested[0] =~ s/^\s+// if(@nested);
}
else {
push @result, $nl;
}
if(@nested) {
push @result, @nested, $indent;
}
push @result, '</', $name, ">", $nl;
}
else {
push @result, @nested; # Special case if no root elements
}
}
else {
push @result, " />", $nl;
}
$self->{nsup}->pop_context() if($self->{nsup});
}
# Handle arrayrefs
elsif(UNIVERSAL::isa($ref, 'ARRAY')) {
foreach $value (@$ref) {
next if !defined($value) and $self->{opt}->{suppressempty};
if(!ref($value)) {
push @result,
$indent, '<', $name, '>',
($self->{opt}->{noescape} ? $value : $self->escape_value($value)),
'</', $name, ">$nl";
}
elsif(UNIVERSAL::isa($value, 'HASH')) {
push @result, $self->value_to_xml($value, $name, $indent);
}
else {
push @result,
$indent, '<', $name, ">$nl",
$self->value_to_xml($value, 'anon', "$indent "),
$indent, '</', $name, ">$nl";
}
}
}
else {
lib/XML/Simple.pm view on Meta::CPAN
=head1 OPTIONS
B<XML::Simple> supports a number of options (in fact as each release of
B<XML::Simple> adds more options, the module's claim to the name 'Simple'
becomes increasingly tenuous). If you find yourself repeatedly having to
specify the same options, you might like to investigate L<"OPTIONAL OO
INTERFACE"> below.
If you can't be bothered reading the documentation, refer to
L<"STRICT MODE"> to automatically catch common mistakes.
Because there are so many options, it's hard for new users to know which ones
are important, so here are the two you really need to know about:
=over 4
=item *
check out C<ForceArray> because you'll almost certainly want to turn it on
=item *
make sure you know what the C<KeyAttr> option does and what its default value is
because it may surprise you otherwise (note in particular that 'KeyAttr'
affects both C<XMLin> and C<XMLout>)
=back
The option name headings below have a trailing 'comment' - a hash followed by
two pieces of metadata:
=over 4
=item *
Options are marked with 'I<in>' if they are recognised by C<XMLin()> and
'I<out>' if they are recognised by C<XMLout()>.
=item *
Each option is also flagged to indicate whether it is:
'important' - don't use the module until you understand this one
'handy' - you can skip this on the first time through
'advanced' - you can skip this on the second time through
'SAX only' - don't worry about this unless you're using SAX (or
alternatively if you need this, you also need SAX)
'seldom used' - you'll probably never use this unless you were the
person that requested the feature
=back
The options are listed alphabetically:
Note: option names are no longer case sensitive so you can use the mixed case
versions shown here; all lower case as required by versions 2.03 and earlier;
or you can add underscores between the words (eg: key_attr).
=head2 AttrIndent => 1 I<# out - handy>
When you are using C<XMLout()>, enable this option to have attributes printed
one-per-line with sensible indentation rather than all on one line.
=head2 Cache => [ cache schemes ] I<# in - advanced>
Because loading the B<XML::Parser> module and parsing an XML file can consume a
significant number of CPU cycles, it is often desirable to cache the output of
C<XMLin()> for later reuse.
When parsing from a named file, B<XML::Simple> supports a number of caching
schemes. The 'Cache' option may be used to specify one or more schemes (using
an anonymous array). Each scheme will be tried in turn in the hope of finding
a cached pre-parsed representation of the XML file. If no cached copy is
found, the file will be parsed and the first cache scheme in the list will be
used to save a copy of the results. The following cache schemes have been
implemented:
=over 4
=item storable
Utilises B<Storable.pm> to read/write a cache file with the same name as the
XML file but with the extension .stor
=item memshare
When a file is first parsed, a copy of the resulting data structure is retained
in memory in the B<XML::Simple> module's namespace. Subsequent calls to parse
the same file will return a reference to this structure. This cached version
will persist only for the life of the Perl interpreter (which in the case of
mod_perl for example, may be some significant time).
Because each caller receives a reference to the same data structure, a change
made by one caller will be visible to all. For this reason, the reference
returned should be treated as read-only.
=item memcopy
This scheme works identically to 'memshare' (above) except that each caller
receives a reference to a new data structure which is a copy of the cached
version. Copying the data structure will add a little processing overhead,
therefore this scheme should only be used where the caller intends to modify
the data structure (or wishes to protect itself from others who might). This
scheme uses B<Storable.pm> to perform the copy.
=back
Warning! The memory-based caching schemes compare the timestamp on the file to
the time when it was last parsed. If the file is stored on an NFS filesystem
(or other network share) and the clock on the file server is not exactly
synchronised with the clock where your script is run, updates to the source XML
file may appear to be ignored.
=head2 ContentKey => 'keyname' I<# in+out - seldom used>
When text content is parsed to a hash value, this option lets you specify a
name for the hash key to override the default 'content'. So for example:
XMLin('<opt one="1">Text</opt>', ContentKey => 'text')
( run in 0.333 second using v1.01-cache-2.11-cpan-ec4f86ec37b )