xmlperlxml-libxml

Need help to create XML file using perl XML::LibXML


refering to this solution, in this question, < How can I include nested elements within root element to create XML from scratch using perl XML::LibXML >

I tried to use this approach and I have arrived at this point.

#!/tool/pandora64/bin/perl5.18.1
use strict;
use warnings;
use XML::LibXML;
my $doc = XML::LibXML::Document->new('1.0', 'utf-8');my $tag; my  $childtag;
my $root = $doc->createElement('RootInfo');
$root->setAttribute('name1'=> 'value1');
$root->setAttribute('name2'=>'value2');
my %tags = (
    element1 => 'sometext',
    element2 => 'somevalue',
    element3 => 'somevalue',
    element4 => '',
);
for my $name (keys %tags) {
    $tag = $doc->createElement($name);
    my $value = $tags{$name};
    $tag->appendTextNode($value);
    $root->appendChild($tag);    
}
my %childtags = (
    Name => "INFO",
    Model => "mname",
    Revision => 'rev',
    );
for my $childname(keys %childtags){
    $childtag = $doc->createElement($childname);
    my $childvalue = $childtags{$childname} ;
    $childtag->appendTextNode($childvalue);
    $tag->appendChild($childtag);}
$doc->setDocumentElement($root);
print $doc->toString(1);

This is the output I get,

<?xml version="1.0" encoding="utf-8"?>
<RootInfo name1="value1" name2="value2">
  <element2>somevalue<element3/>
  <element4/>
  <element1>sometext</element1>
  <element3>somevalue<Name>INFO</Name><Revision>rev</Revision><Model>mname</Model></element3>
</RootInfo>

I want it to be as following. I am somehow unable to fig out where should I modify exactly. Being new to perl, I seek help.

<?xml version="1.0" encoding="utf-8"?>
<RootInfo name1="value1" name2="value2">
  <element2>somevalue<element2/>
  <element1>sometext</element1>
  <element3>somevalue</element3>
  <element4>
    <Name>INFO</Name>
    <Revision>rev</Revision>
    <Model>mname</Model>
  <element4/>
</RootInfo>

Solution

  • The problem here is you're not fixing the order of your node creation.

    Since Perl 5.18, keys returns the keys in a randomised order, for security reasons. Here, your first for loop goes over %tags and assigns $tag to each one in turn. So which one is last (used for appending in the second for loop) is non-deterministic.

    You can get predictable behaviour either by changing keys to sort keys, or better specifying which element you want attached to which in the two loops (possibly with a hash of hashes).