使用XML::LibXML替换XML节点

3

能有人帮我一下吗?我需要使用Perl和XML::LibXML模块替换一个XML节点。

这是XML文件的片段:

<utenti>
    <utente>
        <username>amministratore</username>
        <useremail>admin@email.com</useremail>
        <password>0000</password>
    </utente>
</utenti>

我需要替换密码的值。

具体来说,我需要在 XML 文件中查找具有特定用户名(由 cookie $userCookie 给出)的用户,并将其密码替换为变量 $newPSW

我尝试过以下方法:

    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);

但每次浏览器都会给我以下错误提示:
Can't locate object method "parentNode" via package "XML::LibXML::NodeList"

似乎我使用的任何方法都无法找到。
有人可以帮忙吗?
4个回答

3
你会得到一个XML::LibXML::NodeList对象作为结果。这个对象没有parentNode功能。你需要获取数组的第一个元素,然后在其上调用方法parentNode
第一个对象将是XML::LibXML::Node类的对象,它有一个parentNode函数。
更多详情请查看XML::LibXML::Node文档。
my $psw = $doc->findnodes("/utenti/utente[username=\"$userCookie\"]/password");
my $parent = $psw->[0]->parentNode;
$parent->removeChild($psw->[0]);

谢谢,它真的帮了我 ;) - ambdere

3
问题在于$psw是一个XML::LibXML::NodeList对象,而不仅仅是单个节点--尽管它应该是一个只包含一个节点的列表。
最简单的解决方案是使用列表赋值来获取列表中第一个(也希望是唯一的)元素。
如果有嵌入的双引号,更好的做法是改变字符串分隔符。
像这样:
my ($psw) = $doc->findnodes(qq</utenti/utente[username="$userCookie"]/password>);

3

XML::XSH2XML::LibXML的一个封装,可以让你的生活更加轻松:

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

2
更新:您无需操作父节点即可更改节点内容。
#!/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>

你甚至可以通过xpath请求父节点 :) 并且使用列表上下文的findnodes返回节点列表而不是...NodeList对象。
#!/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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接