2017-03-17 106 views
0

我有两个XML文件。在第一个我有一些设备已经在数据库(标签ipAddress是重要的)。 第二个XML文件包含那些应该添加的设备/设备,如果它们不在数据库(发布请求)。要比较xml文件中具有相同名称的标签与其他xml文件中的其他标签

我已经有了比较两个XML文件的代码,如果他们只有一个设备(一个标签与ipAddress)。

FILE1(包含30个设备,例如我只添加了2个)。

<?xml version="1.0" ?> 
<queryResponse last="34" first="0" count="35" type="Devices" responseType="listEntityInstances" requestUrl="https://hostname/webacs/api/v1/data/Devices?.full=true" rootUrl="https://hostname/webacs/api/v1/data"> 
    <entity dtoType="devicesDTO" type="Devices" url="https://hostname/webacs/api/v1/data/Devices/200"> 
    <devicesDTO displayName="201200" id="200"> 
     <deviceName>NEW</deviceName> 
     <deviceType>Cisco Switch</deviceType> 
     <ipAddress>10.66.12.128</ipAddress> 
    </devicesDTO> 
    </entity> 
    <entity dtoType="devicesDTO" type="Devices" url="https://hostname/webacs/api/v1/data/Devices/201"> 
    <devicesDTO displayName="201201" id="201"> 
     <deviceName>NEW-SWW</deviceName> 
     <deviceType>Cisco Switch</deviceType> 
     <ipAddress>10.66.12.127</ipAddress> 
    </devicesDTO> 
    </entity> 
</queryResponse> 

FILE2(可以是一个或多个设备)

<?xml version="1.0"?> 
    <devicesImport> 
    <devices> 
     <device> 
     <ipAddress>10.66.0.8</ipAddress> 
     <networkMask>24</networkMask> 
     <snmpWriteCommunity>labor</snmpWriteCommunity> 
     <udfs> 
     <udf> 
      <name>LaborTest</name> 
     </udf> 
     </udfs> 
    </device> 
    </devices> 
    </devicesImport> 
    <devicesImport> 
    <devices> 
     <device> 
     <ipAddress>10.66.0.9</ipAddress> 
     <networkMask>24</networkMask> 
     <snmpWriteCommunity>labor</snmpWriteCommunity> 
     <udfs> 
     <udf> 
      <name>LaborTest</name> 
     </udf> 
     </udfs> 
    </devices> 
    </devices> 
</devicesImport> 

我的代码:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use XML::Twig; 


my $xml1 = XML::Twig->new->parsefile('FILE1.xml'); 
my $xml2 = XML::Twig->new->parsefile('FILE2.xml'); 

#$xml2->findnodes('./ipAddress/*'); # I tried to cover all ipAddress from FILE1 

    #Next Try to do it other way 
    #foreach $xml1->get_xpath('//ipAddress', 0)->text { 
    #foreach $xml2->get_xpath('//ipAddress', 0)->text { 


    # I compare here just one tag from both files (it works if my file contains just one device) 
    if ($xml1->get_xpath('//ipAddress', 0)->text 
    eq $xml2->get_xpath('//ipAddress', 0)->text) 

    { 
    print "IP matches\n"; 
    } 

我也试过

if (($xml1->get_xpath('//ipAddress', 0)->text 
    eq $xml2->get_xpath('//ipAddress', 0)->text) 
    for $xml2->findnodes ('//ipAddress')); 

,但它不工作。

+0

不要在你的列表中的那些条目实际上相关?他们没有相同的名字或IP? – Sobrique

+0

另外 - 第一个'文件'似乎是两个单独的XML文档。这是故意的吗? – Sobrique

+0

不,它不应该是两个单独的XML文档,是一个错误 – StayCalm

回答

2

好的,所以这里的东西是get_xpath定位符合特定标准的节点。

如果您确定按照相同的顺序收到东西,您可以获得两个get_xpath响应列表并对它们进行迭代。

但我不认为这是一个安全的假设,在XML - 一个设备可能会丢失。

因此,您需要编写一个search - get_xpath也可以这样做。

您的输入存在一些问题,虽然 - FILE1.xml您已经到了,实际上是两个单独的XML文档。两者之间没有root标记,并且有两次<?xml声明。

因此,您需要稍微转换它以使其成为单个文档(或单独解析)。与FILE2.xml一样 - 最后有两个</devices>标签(其中一个应该是</device>)。请你用有效的XML,因为各种东西,如果你不打破:

但是为了说明,我假设他们是一个单一的文件:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use XML::Twig; 

my $xml1 = XML::Twig->new->parsefile('FILE1.xml'); 
my $xml2 = XML::Twig->new->parsefile('FILE2.xml'); 

foreach my $device ($xml2->get_xpath('//device')) { 
    my $ip_addr = $device->first_child_text('ipAddress'); 
    print "Looking for $ip_addr\n"; 
    if (my $search = $xml1->get_xpath("//ipAddress[string()=\"$ip_addr\"]")) 
    { 
     print "Found: ", $search->parent->first_child_text('deviceName'), "\n"; 
    } 
    else { 
     print "Didn't find match for: ", 
     $device->get_xpath('.//name', 0)->text, "\n"; 
    } 
} 

现在,有在这里没有找到,因为你的IP在你的两个文件中不匹配。

XML::Twig有什么可以与xpath所以它的价值检查做的局限性quick reference guide(这是XML :: LibXML`进入它自己 - 它的功能更全面)