使用 Perl 脚本仅在 XML 中的节点值中更改几个字符
Change few characters only in a node value in XML using Perl script
原文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);
错误信息:
Can't locate object method "replaceNode" via package "XML::LibXML::NodeList"
我是 Perl 脚本的初学者和新手。我想使用 Perl 和 XML::LibXML 模块修改 XML 文件。我也访问了 CPAN,但是通过很少的相关示例很难掌握这个概念。如果你能给我一些提示,这对我的知识增长会很有帮助。
很高兴得到任何类型的反馈并且愿意学习 :)
来自 XML::LibXML::Node 的文档:
findnodes evaluates the xpath expression (XPath 1.0) on the current node and returns the resulting node set as an array. In scalar context, returns an XML::LibXML::NodeList object.
由于 $variable = $doc->findnodes(...)
,您的调用处于标量上下文中。
您有三个选择:
- 使用
my $el = $doc->find(...)
到return单个节点。
- 或者,使用语法
my ($el) = $doc->findnodes(...)
。这导致调用 list context 并将 returned 列表的第一个元素分配给 $el
.
如果您的 XPath 表达式可以有更多节点,您可以使用 for
表达式来遍历 ->findnodes(...)
的结果,如下所示:
for my $el ($doc->findnodes(...) {
print $el->tostring()
}
以下代码最终对我有用,但是,如果您发现我可以改进的地方,请发表评论。
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>
原文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);
错误信息:
Can't locate object method "replaceNode" via package "XML::LibXML::NodeList"
我是 Perl 脚本的初学者和新手。我想使用 Perl 和 XML::LibXML 模块修改 XML 文件。我也访问了 CPAN,但是通过很少的相关示例很难掌握这个概念。如果你能给我一些提示,这对我的知识增长会很有帮助。
很高兴得到任何类型的反馈并且愿意学习 :)
来自 XML::LibXML::Node 的文档:
findnodes evaluates the xpath expression (XPath 1.0) on the current node and returns the resulting node set as an array. In scalar context, returns an XML::LibXML::NodeList object.
由于 $variable = $doc->findnodes(...)
,您的调用处于标量上下文中。
您有三个选择:
- 使用
my $el = $doc->find(...)
到return单个节点。 - 或者,使用语法
my ($el) = $doc->findnodes(...)
。这导致调用 list context 并将 returned 列表的第一个元素分配给$el
. 如果您的 XPath 表达式可以有更多节点,您可以使用
for
表达式来遍历->findnodes(...)
的结果,如下所示:for my $el ($doc->findnodes(...) { print $el->tostring() }
以下代码最终对我有用,但是,如果您发现我可以改进的地方,请发表评论。
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>