2017-08-24 75 views
0

原始XML:更改几个字符仅在XML节点值使用Perl脚本

<library> 
<email name="Peter P">[email protected]</email> 
</library> 

预期结果:

<library> 
<email name="Peter Parker">[email protected]</email> 
<address>London</address> 
</library> 

而且XML的挑战:

<library> 
<email name="Peter Parker">[email protected]</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('[email protected]'); 
$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 ::节点列表”,找到对象的方法 “replaceNode”

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

高兴得到任何形式的反馈,并愿意学习:)

+2

你尝试过什么?你有什么问题?请告诉我们你的代码。如果你没有任何代码,Stack Overflow是问这个问题的错误地方。 –

+0

你怎么知道彼得帕克住在伦敦? – simbabque

+0

显然,帕克先生是卧底摄影师,我很愚蠢的将这些信息提供出来。 – NewUser

回答

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表达式多个节点,您可以通过的->findnodes(...)像这样的结果用for表达循环:

    for my $el ($doc->findnodes(...) { 
        print $el->tostring() 
    } 
    
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">[email protected]</email> 
</library> 

输出XML文件(这里手动格式化文本,以明确):

<?xml version="1.0"?> 
<library> 
    <email name="Peter Parker">[email protected]</email> 
    <address> 
    <street> Forest Hills </street> 
    <city> New York </city> 
    </address> 
</library>