仅使用Perl脚本在XML中的节点值中更改少量字符

时间:2017-08-24 10:09:41

标签: xml perl xml-libxml

原始XML:

<library>
<email name="Peter P">Peter_Parker@library.com</email>
</library>

预期结果:

<library>
<email name="Peter Parker">Peter.Parker@library.com</email>
<address>London</address>
</library>

进一步的XML挑战:

<library>
<email name="Peter Parker">Peter.Parker@library.com</email>
<address> 
    <housenumber>1</housenumber>
    <street>Regent Street</street>
    <postcode>AB12YZ</postcode>
</address>
</library>

代码:

use strict;
use XML::LibXML;
use XML::LibXML::NodeList;

my $parser = XML::LibXML->new;
my $doc = $parser->parse_file("StackTest.xml");
my $root = $doc->getDocumentElement();

#to modify email address
my $email = $doc->findnodes("/library/email");
my $text = XML::LibXML::Text->new('Peter.Parker@library.com');
$email->replaceNode($text);

#to modify email name attribute
my $email_attribute = $doc->findnodes("/library/email");
my $email_name_att->setAttribute(q|name|,"Peter Parker");
$email_attribute->getAttribute(q|name|);

#to add <address tag> with value
my $address = $doc->createElement('address');
$address->appendText('London');
$root->appendChild($address);

print($doc->toString);

错误讯息:

  

无法通过包“XML :: LibXML :: NodeList”找到对象方法“replaceNode”

我是初学者,也是Perl脚本的新手。我想使用Perl和XML :: LibXML模块修改XML文件。我也访问了CPAN,但很难用很少的相关例子来理解这个概念。如果你能为我提供一些提高我知识的提示。

很高兴获得任何反馈并愿意学习:)

2 个答案:

答案 0 :(得分:3)

来自XML::LibXML::Node的文档:

  

findnodes计算当前节点上的xpath表达式(XPath 1.0),并将结果节点集作为数组返回。在标量上下文中,返回XML :: LibXML :: NodeList对象。

由于$variable = $doc->findnodes(...),您的通话处于标量上下文中。 您有三种选择:

  1. 使用my $el = $doc->find(...)返回单个节点。
  2. 或者,使用语法my ($el) = $doc->findnodes(...)。这会导致在列表上下文中调用,并将返回列表的第一个元素分配给$el
  3. 如果您的XPath表达式可以有更多节点,您可以使用for表达式循环遍历->findnodes(...)的结果,如下所示:

    for my $el ($doc->findnodes(...) {
        print $el->tostring()
    }
    

答案 1 :(得分:0)

以下代码最终适用于我,但如果您发现任何我可以改进的内容,请发表评论。

use strict;
use XML::LibXML;
use XML::LibXML::NodeList;
use XML::LibXML::PrettyPrint;

my $parser = XML::LibXML->new;
my $doc = $parser->parse_file("StackTest.xml");
my $root = $doc->getDocumentElement();

#to modify email address
for my $email ($doc->findnodes('//library/email/text()')) {
    my $text = $email->getValue;
    $text =~ s{_}(\.);   
    $email->setData($text);
}

#to modify email name attribute
for my $email_attribute ($doc->findnodes('//library/email/@name')) {
    my $email_name_att = $email_attribute->getValue;
    $email_name_att =~ s{\sP}( Parker);
    $email_attribute->setValue($email_name_att);
}

#to add <address tag> with value
for my $addresstag ($doc->findnodes('//library')) {
    my $address = $doc->createElement('address');
    my $street = $doc->createElement('street');
    my $city = $doc->createElement('city');
    $addresstag->addChild($address);
    $address -> addChild($street);
    $address -> addChild($city);
    $street -> appendText('Forest Hills');
    $city -> appendText('New York');
}

#print($doc->toString);
print XML::LibXML::PrettyPrint
    -> new ( element => { compact => [qw/street/]})
    -> pretty_print($doc)
    -> toString;

输入XML文件:

<library>
  <email name="Peter P">Peter_Parker@library.com</email>
</library>

输出XML文件(此处手动格式化文本以明确说明):

<?xml version="1.0"?>
<library>
  <email name="Peter Parker">Peter.Parker@library.com</email>
  <address>
     <street> Forest Hills </street>
     <city> New York </city>
   </address>
</library>