如何使用Perl在XML数据中移动节点
我尝试了几种不同的方法来解析XML文档。我需要在文档中找到一个具有如何使用Perl在XML数据中移动节点,perl,xml-libxml,Perl,Xml Libxml,我尝试了几种不同的方法来解析XML文档。我需要在文档中找到一个具有x属性的节点,然后将该节点及其子节点移动到另一个父节点 我已经成功地使用它来定位节点,并能够遍历它的子节点,但我一直在研究如何将它移动到另一个父节点 使用$node->cloneNode(1)看起来很有希望,但我找不到使用它的好例子 这是原始XML数据 <config logdir="/var/log/foo/" debugfile="/tmp/foo.debug"> <old> <ser
x
属性的节点,然后将该节点及其子节点移动到另一个父节点
我已经成功地使用它来定位节点,并能够遍历它的子节点,但我一直在研究如何将它移动到另一个父节点
使用$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>
私有的
私有的
私有的
私有的
私有的
使用:
使用严格;
使用警告;
使用XML::LibXML;
my$xml=xml::LibXML->load\uxml(IO=>\*数据);
my($new)=$xml->findnodes('//new');
对于我的$linux($xml->findnodes('//old/server[@osname=“linux”]')){
$linux->unbindNode();#从父级删除(在其他位置添加时自动完成,无需克隆)
$new->addChild($linux);
}
打印$xml;
__资料__
私有的
私有的
私有的
私有的
私有的
产出:
<?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>
私有的
私有的
私有的
私有的
私有的
您需要做的就是找到子节点和父节点,并通过调用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>
私有的
私有的
私有的
私家车
您所说的“具有“x”属性的节点”是什么意思?您是说要移动具有kalahari
属性name
的server
元素吗?请显示triedExcellent的Perl代码。这太完美了。谢谢你们两位!是的,如本例所示,匹配某些属性,如名称或ip。我没有移动的示例代码,因为我不知道从哪里开始:/I我肯定可以用这个运行。再次感谢!无需unbindNode
yes。我注意到,在定位之后,但我认为演示如何明确地从父对象中移除仍然是有帮助的。添加了要明确说明的注释问题:my()
在声明时的意义是什么:my($new)=$xml->findnodes('//new')
与仅my$new
相反,findnodes返回一个列表。为了获得列表的第一个元素,而不是匹配节点的计数,需要将左侧也放在列表上下文中,明白了吗。谢谢你,米勒<代码>无空格主要是一种黑客行为。要获得格式良好的输出,XML::LibXML::PrettyPrint
可能是最好的选择。@nwellnhof:我看过了,但我看不出有任何理由说明XML::LibXML
不能单独完成这项工作。我不喜欢有一个完整的其他模块实际上是一个工作环境。顺便说一下,链接是
<?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>