perlxml-libxml

How to add Child and Grandchild XML tags by XML::LibXML?


I'm trying to make a simple XML file and add Child and Grandchild XML tags by XML::LibXML.

I made country and location tags as below, but I want to add child and grandchild tags under country and location tags such as <dev>value</dev>. How do I add Child and Grandchild XML tags by XML::LibXML?

use strict;
use warnings;
use XML::LibXML;

my $doc = XML::LibXML::Document->new('1.0', 'utf-8');
#my $record = $doc->documentElement;
my $root = $doc->createElement('my-root-element');
$root->setAttribute('some-attr'=> 'some-value');


my $country = $doc->createElement('country');
$country-> appendText('Jamaica');
$root->appendChild($country);

    
my $dev = $doc->createElement('dev');
$dev-> appendText('value');
$country->appendChild($dev);


my $location = $doc->createElement('location');
$location-> appendText('21.241.21.2');
$root->appendChild($location);

$doc->setDocumentElement($root);
print $doc->toString(1);

The result I got is below:

<?xml version="1.0" encoding="utf-8"?>
<my-root-element some-attr="some-value">
  <country>Jamaica<dev>value</dev></country>
  <location>21.241.21.2</location>
</my-root-element>

Actually, I expected the output as below

<?xml version="1.0" encoding="utf-8"?>
<my-root-element some-attr="some-value">
  <country>
        <dev>
             <Name>Jameica</Name>
             <field>value</field>
             <range>value1</range>
        </dev>
  </country>
  <country>
        <dev>
             <Name>USA</Name>
             <field>value</field>
             <range>value1</range>
        </dev>
   </country>
</my-root-element>

Solution

  • Since <country> only has elements, not text, you should not use $country->appendText('Jamaica');. Similarly, you should not use appendText for <dev>.

    You also need to create 3 child elements under <dev>: Name, field and range. For those, you need to call $dev->appendChild, etc.

    This code sets you on a path to get the type of output you desire:

    use strict;
    use warnings;
    use XML::LibXML;
    
    my $doc = XML::LibXML::Document->new('1.0', 'utf-8');
    my $root = $doc->createElement('my-root-element');
    $root->setAttribute('some-attr'=> 'some-value');
    
    my $country = $doc->createElement('country');
    $root->appendChild($country);
        
    my $dev = $doc->createElement('dev');
    $country->appendChild($dev);
    
    my $name = $doc->createElement('Name');
    $name->appendText('Jamaica');
    $dev->appendChild($name);
    
    my $field = $doc->createElement('field');
    $field->appendText('value');
    $dev->appendChild($field);
    
    my $range = $doc->createElement('range');
    $range->appendText('value1');
    $dev->appendChild($range);
    
    $doc->setDocumentElement($root);
    print $doc->toString(1);
    

    Prints:

    <?xml version="1.0" encoding="utf-8"?>
    <my-root-element some-attr="some-value">
      <country>
        <dev>
          <Name>Jamaica</Name>
          <field>value</field>
          <range>value1</range>
        </dev>
      </country>
    </my-root-element>