我有两个XML文件。在第一个我有一些已经在DB中的设备(标签 ipAddress 很重要)。 第二个XML文件包含设备/设备,如果它们不在DB(Post请求),则应添加这些设备/设备。
如果两个XML文件只有一个设备(一个带有ipAddress的标签),我已经有了比较两个XML文件的代码。
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 :(得分:2)
好的,所以这里的事情是get_xpath
找到符合特定条件的节点。
如果您确实以相同的顺序获得了内容,则可以获得两个get_xpath
响应列表并对其进行迭代。
但我不认为XML
中的安全假设 - 设备可能会丢失。
相反,你需要写一个search
- get_xpath
也可以这样做。
您的输入存在一些问题 - FILE1.xml
您已经到达那里,实际上是两个单独的XML文档。两者之间没有root
标记,并且<?xml
声明两次。
所以你需要稍微改造它以使它成为一个单独的doc(或单独解析)。与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进入其中的地方&#39;自己 - 它的功能更全面)