我尝试了几种不同的方法来解析XML文档。我需要在文档中找到一个带有x
属性的节点,然后将该节点及其子节点移动到另一个父节点。
我使用XML::LibXML
找到节点并能够遍历它的子节点时取得了一些成功,但我仍然坚持如何将它移动到另一个父节点。
使用$node->cloneNode(1)
看起来很有希望,但我找不到好用的例子。
这是原始的XML数据
<config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
<old>
<server name="sahara" osname="solaris" osversion="2.6">
<address ip="10.0.0.101">Private</address>
<address ip="10.0.1.101">Private</address>
</server>
<server name="gobi" osname="irix" osversion="6.5">
<address ip="10.0.0.102">Private</address>
</server>
<server name="kalahari" osname="linux" osversion="2.0.34">
<address ip="10.0.0.103">Private</address>
<address ip="10.0.1.103">Private</address>
</server>
</old>
<new>
</new>
</config>
这是我想要的结果
<config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
<old>
<server name="sahara" osname="solaris" osversion="2.6">
<address ip="10.0.0.101">Private</address>
<address ip="10.0.1.101">Private</address>
</server>
<server name="gobi" osname="irix" osversion="6.5">
<address ip="10.0.0.102">Private</address>
</server>
</old>
<new>
<server name="kalahari" osname="linux" osversion="2.0.34">
<address ip="10.0.0.103">Private</address>
<address ip="10.0.1.103">Private</address>
</server>
</new>
</config>
答案 0 :(得分:2)
使用XML::LibXML
:
use strict;
use warnings;
use XML::LibXML;
my $xml = XML::LibXML->load_xml( IO => \*DATA );
my ($new) = $xml->findnodes('//new');
for my $linux ( $xml->findnodes('//old/server[@osname="linux"]') ) {
$linux->unbindNode(); # Remove from Parent (done automatically when added elsewhere without cloning)
$new->addChild($linux);
}
print $xml;
__DATA__
<config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
<old>
<server name="sahara" osname="solaris" osversion="2.6">
<address ip="10.0.0.101">Private</address>
<address ip="10.0.1.101">Private</address>
</server>
<server name="gobi" osname="irix" osversion="6.5">
<address ip="10.0.0.102">Private</address>
</server>
<server name="kalahari" osname="linux" osversion="2.0.34">
<address ip="10.0.0.103">Private</address>
<address ip="10.0.1.103">Private</address>
</server>
</old>
<new>
</new>
</config>
输出:
<?xml version="1.0"?>
<config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
<old>
<server name="sahara" osname="solaris" osversion="2.6">
<address ip="10.0.0.101">Private</address>
<address ip="10.0.1.101">Private</address>
</server>
<server name="gobi" osname="irix" osversion="6.5">
<address ip="10.0.0.102">Private</address>
</server>
</old>
<new>
<server name="kalahari" osname="linux" osversion="2.0.34">
<address ip="10.0.0.103">Private</address>
<address ip="10.0.1.103">Private</address>
</server></new>
</config>
答案 1 :(得分:1)
您需要做的就是找到子节点和父节点,并通过调用appendChild
将子节点移动到新父节点。
假设您的原始XML数据位于名为config.xml
的文件中,代码将如下所示。
我不知道更好的方法来说服XML::LibXML
生成精美缩进的数据。我发现最好的是启用no_blanks
并使用非零参数toString
,但正如您所看到的那样,它远非理想。
use strict;
use warnings;
use XML::LibXML;
my $xml = XML::LibXML->load_xml(location => 'config.xml', no_blanks => 1);
my ($kalahari) = $xml->findnodes('/config/old/server[@name="kalahari"]');
my ($new) = $xml->findnodes('/config/new');
$new->appendChild($kalahari);
print $xml->toString(1);
<强>输出强>
<?xml version="1.0"?>
<config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
<old>
<server name="sahara" osname="solaris" osversion="2.6">
<address ip="10.0.0.101">Private</address>
<address ip="10.0.1.101">Private</address>
</server>
<server name="gobi" osname="irix" osversion="6.5">
<address ip="10.0.0.102">Private</address>
</server>
</old>
<new>
<server name="kalahari" osname="linux" osversion="2.0.34"><address ip="10.0.0.103">Private</address><address ip="10.0.1.103">Private</address></server></new>
</config>