irishBatman has asked for the wisdom of the Perl Monks concerning the following question:
I have been looking for examples of converting hash's to XML and back again. Initially for overlaying setting's onto objects. I started using XML::Simple, but was discouraged as at some point I may wish to embed binary data in my XML processing functions. I thought it would be bettter to start using LibXML and build on that!
I have come up with 2 example scripts, one that show's coversion of a hash to XML, the other that reads this input and prepares it for overlay on a hash. If the scripts are executed in order the first one should provide the input to the second.
These are only a starting point and not my final functions that I need to create, however they provide all the basic function that I require. I was wondering what the Monks thought of these though and before I proceed any further if there was another approach that may work better?
use strict; use XML::LibXML; my %testHash; ## create a test hash $testHash{root}{testEl1}{currentValue} = 0; $testHash{root}{testEl1}{comment} = "System test element 1"; $testHash{root}{testEl1}{enable} = 1; $testHash{root}{testEl2}{currentValue} = 0; $testHash{root}{testEl2}{comment} = "System test element 2"; $testHash{root}{testEl2}{enable} = 1; $testHash{root}{testEl2}{newLevel}{enable1} = 1; $testHash{root}{testEl2}{newLevel}{enable2} = 1; $testHash{root}{testEl2}{newLevel}{enable3} = 1; $testHash{root}{testEl3}{newLevel}{enable} = 1; $testHash{root}{testEl2}{reference} = $testHash{root}{testEl1}; ## call the hash processor! my $string = myHash2Xml( \%testHash ); ## create the output XML open FILEOUT, ">myHash2Xml.xml"; print FILEOUT "$string\n"; close FILEOUT; ## end of script ## covert our hash to XML, this is a wrapper to create the ## document and pass it back as a string sub myHash2Xml { my ($hash) = @_; ## create a new xml document! my $xmlDoc = XML::LibXML::Document->new( '1.0', 'UTF-8' ); ## create the root element and a pointer to it! my $root = $xmlDoc->createElement("testDoc"); $xmlDoc->setDocumentElement($root); examineHash( $hash, \$xmlDoc, \$root ); # process the hash my $xmlString = $xmlDoc->toString(1); print "$xmlString\n"; return $xmlString; } ## wrapper for the recurser, sub examineHash { my ( $hash, $xmlDoc, $lastElement ) = @_; my %refsHash; # hash ref counter, use +d to prevent/detect circular refs examineHashRecurse( \%refsHash, $hash, $xmlDoc, $lastElement ); + # here we go } ## recurser! sub examineHashRecurse { my ( $refsHash, $hash, $xmlDoc, $lastElement ) = @_; foreach my $key ( sort { $a cmp $b } keys( %{$hash} ) ) { + # go through keys at current level if ( ( $$hash{$key} . "" ) =~ /HASH\(/ ) { + # is it another hash? ## its another hash, go deeper! if ( !exists $$refsHash{ $$hash{$key} } ) { + # check if its in the reference hash $$refsHash{ $$hash{$key} } = 1; # print "create element $key\n"; my $newElement = $$xmlDoc->createElement($key); + # create new element $$lastElement->appendChild($newElement); + # add element to our doc under the last element ## remember to pass the new element as a reference. examineHashRecurse( $refsHash, $$hash{$key}, $xmlDoc, +\$newElement ); } ## else, this has alread been examined! stops circula +r continuation else { # do something with a circular reference??? $$refsHash{ $$hash{$key} }++; } } else { # print "create attribute $key with value " . $ +$hash{$key} . "\n"; $$lastElement->setAttribute( "$key", $$hash{$key} ); # +add attribute to the last element! } } }
use strict; use XML::LibXML; my $file; $file = 'myHash2Xml.xml'; ## load the XML my $parser = XML::LibXML->new(); my $tree = $parser->parse_file($file); my $root = $tree->getDocumentElement; ## get all the elements that exist in a doc. Note the wildcard to sear +ch through everything. my @allDocElements = $root->getElementsByTagName('*'); ## some stats meters my $useableElements = 0; my $useableAtts = 0; my $count = @allDocElements; ## iterate over all the elements foreach my $el1 (@allDocElements) { ## if we have no child nodes we are at the bottom of the tree. Thi +s is what we ## will be looking for most of the time. if ( !$el1->hasChildNodes() ) { if ( $el1->hasAttributes() ) { ## iterate over all the attributes $useableElements++; foreach my $ttt ( $el1->attributes() ) { $useableAtts++; my $string = $el1->nodePath() . "/" . $ttt->localName +. " = " . $ttt->nodeValue; print "AT - $string\n"; } } else { ## haven't hit this yet $useableElements++; my $string = $el1->nodePath() . "/--" . $el1->localName . +" = " . $el1->nodeValue; print "EL - $string\n"; } } else { ## if we are not at the bottom of the tree, we could still hav +e attributes. Check here ## if we do and process as above if ( $el1->hasAttributes() ) { $useableElements++; foreach my $ttt ( $el1->attributes() ) { $useableAtts++; my $string = $el1->nodePath() . "/" . $ttt->localName +. " = " . $ttt->nodeValue; print "AT - $string\n"; } } else { ## keep an eye out for text added to elements if ( $el1->textContent() !~ /\n/ ) { $useableElements++; my $string = $el1->nodePath() . " = " . $el1->textCont +ent; print "TX - $string\n"; } } } } print "\nFrom $count we found $useableElements useable elements, with +$useableAtts attributes\n";
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: comments on xml 2 hash 2 xml using libXML
by space_monk (Chaplain) on Mar 18, 2013 at 14:29 UTC | |
by tobyink (Canon) on Mar 18, 2013 at 16:44 UTC | |
by space_monk (Chaplain) on Mar 18, 2013 at 17:26 UTC | |
by Anonymous Monk on Mar 18, 2013 at 15:32 UTC | |
by space_monk (Chaplain) on Mar 18, 2013 at 15:59 UTC | |
|
Re: comments on xml 2 hash 2 xml using libXML
by space_monk (Chaplain) on Mar 20, 2013 at 08:28 UTC |