要比较xml文件中具有相同名称的标签与其他xml文件中的其他标签
问题描述:
我有两个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'));
,但它不工作。
答
好的,所以这里的东西是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`进入它自己 - 它的功能更全面)
不要在你的列表中的那些条目实际上相关?他们没有相同的名字或IP? – Sobrique
另外 - 第一个'文件'似乎是两个单独的XML文档。这是故意的吗? – Sobrique
不,它不应该是两个单独的XML文档,是一个错误 – StayCalm