Reputation: 67
I'm trying to save a complex array/hash structure to xml. As I'm new to both perl and xml I don't know what is the easiest way to do this.
All the xml parser, writer, libxml, etc. modules don't give me what I want. E.g. DumpXML adds lots of tags. I have tried many different modules but none of them seem to do what I want or I don't know how to set them up so that they work as I want them to. Maybe I do have to write the xml part on a lower level? Or maybe it's best if I don't use the perl data structures but store it directly to xml?
The idea is to create a php webpage from the xml data. Unfortunately I'm a php noob as well and therefore was just hoping doing so won't be a big problem. :-) I just wanted to have a logical layout of the xml file like in the examples below.
Here's how I tried it with Data::Diver
and XML::Smart
.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Data::Diver qw( Dive DiveRef DiveVal DiveError );
use XML::Smart;
my $content = {};
# Usage: add_content_entry(name, group, descr)
sub add_content_entry {
my $name = shift;
my $group = shift;
my $descr1 = shift;
my $descr2 = shift;
my $data = {
DESCR1 => $descr1,
DESCR2 => $descr2,
};
my @pos = split('/', $group);
push @pos, $name;
DiveVal( $content, @pos ) = $data;
}
sub xml_read {
my $xml = XML::Smart->new('file.xml');
$content = $xml->data;
}
sub xml_write {
my $xml = XML::Smart->new(
q`
<?xml version="1.0" encoding="iso-8859-1" ?>
<content></content>
`);
$xml->{content} = $content;
$xml->('file.xml');
}
# Main
&xml_read; # file.xml is empty
&add_content_entry( 'content.1', 'group.A', 'Hello', 'World' );
&add_content_entry( 'content.2', 'group.B/group.x', 'Fred', 'Flintstone' );
&add_content_entry( 'content.3', 'group.B/group.y', 'bla', 'blah' );
&add_content_entry( 'content.4', 'group.B/group.y', '???', '!!!' );
&add_content_entry( 'content.5', 'group.C/group.z', '...', '...' );
&xml_write; # file.xml is written
$content = {};
&xml_read; # justify that file.xml can be read
print Dumper $content;
The output should be:
$VAR1 = {
'group.A' => {
'content.1' => {
'DESCR2' => 'World',
'DESCR1' => 'Hello'
}
},
'group.C' => {
'group.z' => {
'content.5' => {
'DESCR2' => '...',
'DESCR1' => '...'
}
}
},
'group.B' => {
'group.y' => {
'content.3' => {
'DESCR2' => 'blah',
'DESCR1' => 'bla'
},
'content.4' => {
'DESCR2' => '!!!',
'DESCR1' => '???'
}
},
'group.x' => {
'content.2' => {
'DESCR2' => 'Flintstone',
'DESCR1' => 'Fred'
}
}
}
};
My problem is that the number of levels is not the same for the different contents.
In the xml file there should be something like (I know the sorting is arbitrary. I kept the same as in the output of print Dumper
).
<?xml version="1.0" encoding="iso-8859-1" ?>
<content>
<group.A>
<content.1>
<DESCR2>World</DESCR>
<DESCR1>Hello</DESCR1>
</content.1>
</group.A>
<group.C>
<group.z>
<content.5>
<DESCR2>...</DESCR>
<DESCR1>...</DESCR1>
</content.5>
</group.z>
</group.C>
<group.B>
<group.y>
<content.3>
<DESCR2>blah</DESCR>
<DESCR1>bla</DESCR1>
</content.3>
<content.4>
<DESCR2>!!!</DESCR>
<DESCR1>???</DESCR1>
</content.4>
</group.y>
<group.x>
<content.2>
<DESCR2>Flintstone</DESCR>
<DESCR1>Fred</DESCR1>
</content.2>
</group.x>
</group.B>
</content>
or
<?xml version="1.0" encoding="iso-8859-1" ?>
<content>
<group.A>
<content DESCR2="World" DESCR1="Hello">content.1</content>
</group.A>
<group.C>
<group.z>
<content DESCR2="..." DESCR1="...">content.5</content>
</group.z>
</group.C>
<group.B>
<group.y>
<content DESCR2="blah" DESCR1="bla">content.3</content>
<content DESCR2="!!!" DESCR1="???">content.4</content>
</group.y>
<group.x>
<content DESCR2="Flintstone" DESCR1="Fred">content.2</content>
</group.x>
</group.B>
</content>
Upvotes: 3
Views: 744
Reputation: 6798
I'd like to suggest for you to consider using YAML as an alternative to XML. As you said, XML tends to get bloated with tags. YAML output is much cleaner, and is designed to be readable by people.
So your data output could look something like this:
group.A:
content.1:
- DESCR2: World
- DESCR1: Hello
group.C:
group.z:
content.5:
- DESCR2: ...
- DESCR1: ...
group.B:
- group.y:
- content.3:
- DESCR2: blah
- DESCR1: bla
- content.4:
- DESCR2: !!!
- DESCR1: ???
- group.x:
content.2:
- DESCR2: Flintstone
- DESCR1: Fred
In Perl, you can use the YAML::XS module. There are PHP modules that can recognise YAML also.
Upvotes: 1
Reputation: 27886
You should check out DBD::AnyData and see if it meets your needs. It supports using XML files the same way you would an SQL database.
Upvotes: 1