【问题标题】:To compare tags with the same name in xml file with other tag in other xml file将 xml 文件中的同名标签与其他 xml 文件中的其他标签进行比较
【发布时间】:2017-03-17 13:15:05
【问题描述】:

我有两个 XML 文件。在第一个中,我有一些设备已经在数据库中(标签 ipAddress 很重要)。 第二个 XML 文件包含设备/设备,如果它们不在数据库中,则应添加它们(发布请求)。

如果两个 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'));

但它不起作用。

【问题讨论】:

  • 您列表中的这些条目是否真的相关?它们没有相同的名称或 IP?
  • 另外 - 第一个“文件”似乎是两个单独的 XML 文档。这是故意的吗?
  • 不,它不应该是两个独立的 XML 文档,是一个错误
  • 是的,它们没有相同的名称或 IP,这只是示例......但此时它只是 IP,因为我的“file2”只包含 IP 而没有名称

标签: xml perl xml-parsing


【解决方案1】:

好的,这里的事情是get_xpath 定位符合特定条件的节点。

如果你确实有相同顺序的东西,你可以得到两个 get_xpath 响应列表并迭代它们。

但我不认为这是 XML 中的安全假设 - 可能缺少设备。

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

尽管您的输入存在一些问题 - FILE1.xml 您已经到达那里,实际上是两个单独的 XML 文档。两者之间没有root 标签,并且有两次&lt;?xml 声明。

因此,您需要稍微对其进行转换以使其成为单个文档(或分别解析两者)。与FILE2.xml 类似 - 最后有两个&lt;/devices&gt; 标签(一个应该是&lt;/device&gt;)。检查您使用的是有效的 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::Twigxpath 的功能有限制,因此值得检查 quick reference guide(这是 XML::LibXML` 发挥作用的地方 - 它的功能更全面)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    相关资源
    最近更新 更多