http://www.perlmonks.org?node_id=1004816

techie411 has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to add elements to XML using XML::LibXML. I know how to add elements, but I'm having a hard time trying to go to lower levels of the elements. For instance:

---- ORIGINAL FILE ----
<dict> <key>TEST1</key> <key>TEST2</key> <string>en</string> <key>TEST3</key> </dict>
---- RESULTS I WANT ----
<dict> <key>ADDKEY</key> <array> <dict> <key>SAMPLEKEY</key> <array> <string>STRING</string> </array> </dict> </array> <key>TEST1</key> <string>en</string> <key>TEST2</key> </dict>
I'd also like to add it before the TEST1 key. The results I get from below is that it appends it to the end of the 'dict' element.

---- WHAT I HAVE SO FAR ----
use strict; use warnings; use XML::LibXML; # load open my $fh, '<', 'test.xml'; binmode $fh; # drop all PerlIO layers possibly created by a use open + pragma my $doc = XML::LibXML->load_xml(IO => $fh); my $root=$doc->getDocumentElement(); # Grabs the 'dict' element my $rootElement = pop(@{$root>getElementsByTagName('dict')}); my $keyElement= $doc->createElement("key"); $keyElement->appendText('Test'); $rootElement->appendChild($keyElement); # save open my $out, '>', 'out.xml'; binmode $out; $doc->toFH($out);

Replies are listed 'Best First'.
Re: Adding Elements to XML
by Anonymous Monk on Nov 20, 2012 at 23:37 UTC

    SO FAR

    Well, naturally, appendChild adds one to the end, perhaps you want  $root->insertBefore( $newNode, $root->firstChild );

    RESULTS I WANT

    You may not have a choice, but if you do, you should think about WANTing a different xml structure :) for example, one that isn't so recursive -- one where the definitions are children (not siblings) of keys -- its a dictionary :)

Re: Adding Elements to XML
by choroba (Cardinal) on Nov 21, 2012 at 11:01 UTC
    Using XML::XSH2, a wrapper around XML::LibXML:
    open 1.xml ; cd /dict ; insert element key prepend . ; set key[1] 'ADDKEY' ; my $array := insert chunk '<array><dict/></array>' after key[1] ; my $key := insert element key into $array/dict ; insert text 'SAMPLEKEY' into $key ; my $array2 := insert element array after $key ; set $array2/string 'STRING' ; delete key[last()] ; xmove :r string[last()] before preceding-sibling::key[1] ; save :b ;
    I tried to demonstrate several ways of creating new nodes: via insert and set (more than one node can be created by both, see insert chunk and setting of string).
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Adding Elements to XML
by Anonymous Monk on Nov 21, 2012 at 12:27 UTC
    Also, generally speaking, use XPath expressions to navigate an XML structure, not hard code. The day will come when you have a structure to deal with that is not-quite what your code was hard-coded to expect. Therefore, as a general approach to this problem, use XPath to find the node(s) you want, then modify them.

      have a structure to deal with that is not-quite what your code was hard-coded to expect.

      hardcode an xpath or hardcode something else -- if it changes, your code will change, duh