如何使用 Perl LibXML 在缺少的地方添加一个 ChildNode?
How to use Perl LibXML to add a ChildNode where one is missing?
我正在使用 libXML 更新一批 XML 设置文件。这是我正在尝试更新的 xml 部分的示例:
<Setting SID="2091">
<Name>HME Cloud User Email</Name>
<Value/>
</Setting>
我可以使用以下代码正确更新该部分。
#!/usr/bin/perl
use File::Basename;
use XML::LibXML;
use XML::LibXML::XPathContext;
@files = glob('C:\Users25144\Documents\timer_test\*.xml');
foreach $file (@files)
{
my $dom = XML::LibXML->load_xml(location => $file);
my $xpc = XML::LibXML::XPathContext->new($dom);
$xpc->registerNs('xsd', 'http://hme.com/Settings.xsd');
#Add email
my($match9) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="2091"]/xsd:Value');
$match9->removeChildNodes();
$match9->appendText('email@email.com');
open (OUTFILE, ">$file");
print OUTFILE $dom;
}
print "XML Files Updated."
但问题是某些设置文件缺少此 SID 的值节点,请参见下面的示例:
<Setting SID="2091">
<Name>HME Cloud User Email</Name>
</Setting>
我一直在查看 addChild 以尝试将节点放入此 SID,但我似乎无法弄清楚语法。我断断续续地使用 perl,所以我希望有人能帮我弄清楚如何添加这个节点,或者如果 SID 有或没有 Value 节点,我是否可以使用替代解决方案。
感谢任何帮助 - 谢谢!
使用 if
,如果值不存在,则使用 addNewChild
创建它。
#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use XML::LibXML;
my @files = @ARGV;
my $uri = 'http://hme.com/Settings.xsd';
for my $file (@files) {
my $dom = 'XML::LibXML'->load_xml(location => $file);
my $xpc = 'XML::LibXML::XPathContext'->new($dom);
$xpc->registerNs('xsd', $uri);
if (my ($email) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="2091"]/xsd:Value')) {
$email->removeChildNodes;
$email->appendText('email@email.com');
} else {
my ($setting) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="2091"]');
$setting->addNewChild($uri, 'Value')->appendText('email@email.com');
}
$dom->toFile("$file.new");
}
say "XML Files Updated."
备注:
- 使用strict and warnings.
- 你不需要 use XML::LibXML::XPathContext. Using XML::LibXML 就够了。
- 使用
toFile
打印 XML。
删除节点就不用担心节点已经存在了:)
my ( $setting ) = $xpc->findnodes( '//xsd:Settings/xsd:Setting[@SID="2091"]' )
or die( "Setting not found\n" );
$_->unbindNode() for $xpc->findnodes( 'xsd:Value', $setting );
$setting->addNewChild( $uri, 'Value' )->appendText( 'email@email.com' );
我正在使用 libXML 更新一批 XML 设置文件。这是我正在尝试更新的 xml 部分的示例:
<Setting SID="2091">
<Name>HME Cloud User Email</Name>
<Value/>
</Setting>
我可以使用以下代码正确更新该部分。
#!/usr/bin/perl
use File::Basename;
use XML::LibXML;
use XML::LibXML::XPathContext;
@files = glob('C:\Users25144\Documents\timer_test\*.xml');
foreach $file (@files)
{
my $dom = XML::LibXML->load_xml(location => $file);
my $xpc = XML::LibXML::XPathContext->new($dom);
$xpc->registerNs('xsd', 'http://hme.com/Settings.xsd');
#Add email
my($match9) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="2091"]/xsd:Value');
$match9->removeChildNodes();
$match9->appendText('email@email.com');
open (OUTFILE, ">$file");
print OUTFILE $dom;
}
print "XML Files Updated."
但问题是某些设置文件缺少此 SID 的值节点,请参见下面的示例:
<Setting SID="2091">
<Name>HME Cloud User Email</Name>
</Setting>
我一直在查看 addChild 以尝试将节点放入此 SID,但我似乎无法弄清楚语法。我断断续续地使用 perl,所以我希望有人能帮我弄清楚如何添加这个节点,或者如果 SID 有或没有 Value 节点,我是否可以使用替代解决方案。
感谢任何帮助 - 谢谢!
使用 if
,如果值不存在,则使用 addNewChild
创建它。
#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use XML::LibXML;
my @files = @ARGV;
my $uri = 'http://hme.com/Settings.xsd';
for my $file (@files) {
my $dom = 'XML::LibXML'->load_xml(location => $file);
my $xpc = 'XML::LibXML::XPathContext'->new($dom);
$xpc->registerNs('xsd', $uri);
if (my ($email) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="2091"]/xsd:Value')) {
$email->removeChildNodes;
$email->appendText('email@email.com');
} else {
my ($setting) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="2091"]');
$setting->addNewChild($uri, 'Value')->appendText('email@email.com');
}
$dom->toFile("$file.new");
}
say "XML Files Updated."
备注:
- 使用strict and warnings.
- 你不需要 use XML::LibXML::XPathContext. Using XML::LibXML 就够了。
- 使用
toFile
打印 XML。
删除节点就不用担心节点已经存在了:)
my ( $setting ) = $xpc->findnodes( '//xsd:Settings/xsd:Setting[@SID="2091"]' )
or die( "Setting not found\n" );
$_->unbindNode() for $xpc->findnodes( 'xsd:Value', $setting );
$setting->addNewChild( $uri, 'Value' )->appendText( 'email@email.com' );