3

Can someone help me please? I need to replace an XML node using Perl with the XML::LibXML module

This is the fragment of the XML file:

<utenti>
    <utente>
        <username>amministratore</username>
        <useremail>[email protected]</useremail>
        <password>0000</password>
    </utente>
</utenti>

And I need to replace the value of the password.

In particular I have to find in the XML file the user with a particular username (given by the cookie $userCookie) and replace his password with the variable $newPSW.

I've tried this:

    my $psw = $doc->findnodes("/utenti/utente[username=\"$userCookie\"]/password");
    my $parent = $psw->parentNode;
    $parent->removeChild($psw);


    my $password = XML::LibXML::Element->new('password');
    $password->appendText( $newPSW );
    $parent->appendChild($password);

but everytime the browser give me the following error:

Can't locate object method "parentNode" via package "XML::LibXML::NodeList"

It seems to no find any method I use.

Can someone help?

4 Answers 4

3

You get a XML::LibXML::NodeList as result. And this object has no function parentNode. You have to get the first element of the array and then call the method parentNode on it.

The first object will be an object of class XML::LibXML::Node and this has a funtion parentNode.

for more details see the documentation of XML::LibXML::Node

my $psw = $doc->findnodes("/utenti/utente[username=\"$userCookie\"]/password");
my $parent = $psw->[0]->parentNode;
$parent->removeChild($psw->[0]);
Sign up to request clarification or add additional context in comments.

Comments

3

XML::XSH2, a wrapper around XML::LibXML, can make your life easier:

set /utenti/utente[username="amministratore"]/password $newPSW ;

Comments

3

The problem is that $psw is an XML::LibXML::NodeList object, not just a single node -- although it should be a list of one node

The simplest solution here is to use a list assignment to grab just the first -- and hopefully only -- element in the list

It's also neater to change the string delimiter if you have embedded double quotes

Like this

my ($psw) = $doc->findnodes(qq</utenti/utente[username="$userCookie"]/password>);

Comments

2

update: you don't need to mess with the parent to change the contents of a node

#!/usr/bin/perl --
use strict;
use warnings;
use XML::LibXML 1.70; ## for load_html/load_xml/location
my $xml = q{<a><b><c>old password</c></b></a>};
my $dom = XML::LibXML->new(qw/ recover 2 /)->load_xml(
#~     location => $filepath_or_http,
    string => $xml,
);
my $password = $dom->findnodes('//c')->get_node(0);
$password->removeChildNodes;
$password->appendText('new password');
print "$dom";
__END__
<?xml version="1.0"?>
<a><b><c>new password</c></b></a>

You could even ask for parent via xpath :) and using list context findnodes returns a list of nodes instead of a ...NodeList object

#!/usr/bin/perl --
use strict;
use warnings;
use XML::LibXML 1.70; ## for load_html/load_xml/location
my $xml = q{<a><b><c></c></b></a>};
my $dom = XML::LibXML->new(qw/ recover 2 /)->load_xml(
#~     location => $filepath_or_http,
    string => $xml,
);
my( $parent ) = $dom->findnodes('//c/..');
print $parent->nodePath;
__END__
/a/b

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.