Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Perl在XML数据中移动节点_Perl_Xml Libxml - Fatal编程技术网

如何使用Perl在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

我尝试了几种不同的方法来解析XML文档。我需要在文档中找到一个具有
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>