Use XML :: LibXML to replace XML node
Can anyone help me? I need to replace XML node with Perl using a moduleXML::LibXML
This is a snippet of the XML file:
<utenti>
<utente>
<username>amministratore</username>
<useremail>admin@email.com</useremail>
<password>0000</password>
</utente>
</utenti>
And I need to replace the password value.
Specifically, I have to search in the XML for the user with a specific username (given by the cookie $userCookie
) and replace his password with a 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 every time the browser gives me the following error:
Can't locate object method "parentNode" via package "XML::LibXML::NodeList"
I didn't seem to find any method that I am using.
Can anyone help?
source to share
The result is XML::LibXML::NodeList
. 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 a class object XML::LibXML::Node
and this has funtion parentNode
.
See XML documentation :: LibXML :: Node for details
my $psw = $doc->findnodes("/utenti/utente[username=\"$userCookie\"]/password");
my $parent = $psw->[0]->parentNode;
$parent->removeChild($psw->[0]);
source to share
The problem is that $psw
is is an object XML::LibXML::NodeList
, not just one node - although it should be a list of one node
The simplest solution here is to use a list assignment to grab only the first - and hopefully only - item in the list
It is also possible to change the line separator if you have embedded double quotes
Like this
my ($psw) = $doc->findnodes(qq</utenti/utente[username="$userCookie"]/password>);
source to share
XML :: XSH2 , a wrapper around XML :: LibXML , can make your life easier:
set /utenti/utente[username="amministratore"]/password $newPSW ;
source to share
update: you don't need to communicate 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 can even ask the parent via xpath :) and using the context context findnodes returns a list of nodes instead of ... 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
source to share