Search code examples
perlxml-libxml

Libxml - replace xml value if particular conditions are met


I have an incomplete Perl script with the following content:

use XML::LibXML;
use XML::LibXSLT;

my $xml_mess = "
<activity>
<ref1></ref1>
<ref2>id_119604</ref2>
<ref3>id_342432</ref3>
</activity>";

my $parser = XML::LibXML->new();
my $xml_mess_obj = $parser -> parse_string($xml_mess);
my $ref1 = $xml_mess_obj -> getDocumentElement -> findNodes("/activity/ref1") -> [0] -> to_literal(); 
my $ref2 = $xml_mess_obj -> getDocumentElement -> findNodes("/activity/ref2") -> [0] -> to_literal();
my $ref3 = $xml_mess_obj -> getDocumentElement -> findNodes("/activity/ref3") -> [0] -> to_literal();

I would like to parse the $xml_mess and make the following changes:

  1. When ref3 has a value, then I want ref1 to have the same value.
  2. When ref3 does not have a value, then I want ref1 to have the same value as ref2.

I have been searching for examples on how to do this with LibXML, but can't figure out how to conditionally update nodes.


Solution

  • This seems to do what you want. See the embedded comments for more detail.

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    use XML::LibXML;
    
    my $xml_mess = '
    <activity>
    <ref1></ref1>
    <ref2>id_119604</ref2>
    <ref3>id_342432</ref3>
    </activity>';
    
    # Load the XML into a Document object
    my $xml_mess_obj = XML::LibXML->load_xml(string => $xml_mess);
    
    # Get an Element object for the <ref1> node.
    my $ref1 = $xml_mess_obj->findnodes('//ref1')->[0];
    
    # Get the text of the <ref2> and <ref3> nodes.
    my $ref2_txt = $xml_mess_obj->findnodes('//ref2')->[0]->to_literal;
    my $ref3_txt = $xml_mess_obj->findnodes('//ref3')->[0]->to_literal;
    
    # Use appendText() to add text to the <ref1> node.
    # Note: // is the 'defined-or' operator. It returns $ref3_txt if that
    # is defined, otherwise it returns $ref2_txt.
    $ref1->appendText($ref3_txt // $ref2_txt);
    
    # Display the result.
    say $xml_mess_obj->toString;