Once upon a time I was asked by one of our javadevelopers if i can send a csv in proper xml to one of his webservices. Of course I can. As usual i decided to use perl and Text::CSV to read in the CSV as well as LWP::UserAgent to send the xml to the (soap-)webservice.
After having a second look on the code, where I put in several nodes at the fourth level of the xml-tree, managing all the intents just via print, I found myself doing something like this:
foreach my $key(keys %hasharr) {
my ($foo,$bar,$value1,$value2,$value3,$value4) = @{$hasharr{$key}};
print XML "\t\t\t\t<base>\n\t\t\t\t\t<key>\n\t\t\t\t\t\t".
$key."\n\t\t\t\t\t</key>\n\t\t\t\t\t<foo>\n\t\t\t\t\t\t".
$foo."\n\t\t\t\t\t</foo>\n\t\t\t\t\t<timestamp>\n\t\t\t\t\t\t".
$value1."\n\t\t\t\t\t</timestamp>\n\t\t\t\t\t<originator>\n\t\t\t\t\t\t".
$value2."\n\t\t\t\t\t</originator>\n\t\t\t\t\t<remote-server>\n\t\t\t\t\t\t".
$value3."\n\t\t\t\t\t</remote-server>\n\t\t\t\t\t<category>\n\t\t\t\t\t\t".
$value4."\n\t\t\t\t\t</category>\n\t\t\t\t\t<diagnostic-string>\n\t\t\t\t\t\t<![CDATA[".$bar."]]>\n\t\t\t\t\t</diagnostic-string>\n\t\t\t\t</base>\n";
}
So not only this looks very ugly it is also very hard to edit
afterwards. I was playing around a bit with “XML::Smart” which was a
hint by one of my friends. Unfortunately I again found why I always
hated products which call themselves “Smart” like “S.M.A.R.T” or
“Smarty”, it is because they all label their Product as smart, while in
some cases it maybe is, in this it wasn’t. I don’t like tools to be
smart. I like people beeing smart or solutions beeing smart. Tools
should just work.
So I found “XML::LibXML” which is a perl-Interface to the most commonly
used library in C. It was not only much faster than XML::Smart, it also
worked in my rather curious circumstances. But as well as for many other
XML-Modules, while there were plenty of examples for parsing, dumping
data and validating xml, I can’t find a simple example on how to
generate xml.
So here’s mine:
#!/usr/bin/perl
use XML::LibXML;
#the XML doc itself:
my $xml = XML::LibXML::Document->new( '1.0', 'UTF-8');
#the root node:
my $root=$xml->createElement( 'foo' );
#append a node with textcontent:
$root->appendTextChild('bar','fubafubafubalalalala');
#append a node with CDATA Content, kind of tricky:
my $content = ' fuubaaa cdata ';
my $newnode = XML::LibXML::Element->new('fubacdata');
my $cdata = XML::LibXML::CDATASection->new($content);
$newnode->appendChild($cdata);
$root->appendChild( $newnode );
#put all back in the document:
$xml->setDocumentElement($root);
#print it pretty:
print $xml->toString(2);
This is the output you will get from that:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>
fubafubafubalalalala
</bar>
<fubacdata>
<![CDATA[<some> fuubaaa cdata </some>]]>
</fubacdata>
</foo>
If you have any questions, rants, suggestions for me, just ping me via one of the contact methods listed.
Cheers, J