2011-08-12 77 views
4

我使用perl的XML :: LibXML模塊來解析來自設備的XML響應。 看來,我可以成功獲取數據的唯一方法是通過修改設備的XML響應。 下面是從設備我的XML響應:使用perl XML :: LibXML來解析

<chassis-inventory xmlns="http://xml.juniper.net/junos/10.3D0/junos-chassis"> 

<chassis junosstyle="inventory"> 

<name>Chassis</name> 

<serial-number>JN111863EAFF</serial-number> 

<description>VJX1000</description> 

<chassis-module> 

<name>Midplane</name> 

</chassis-module> 

<chassis-module> 

<name>System IO</name> 

</chassis-module> 

<chassis-module> 

<name>Routing Engine</name> 

<description>VJX1000</description> 

<chassis-re-disk-module> 

<name>ad0</name> 

<disk-size>1953</disk-size> 

<model>QEMU HARDDISK</model> 

<serial-number>QM00001</serial-number> 

<description>Hard Disk</description> 

</chassis-re-disk-module> 

</chassis-module> 

<chassis-module> 

<name>FPC 0</name> 

<chassis-sub-module> 

<name>PIC 0</name> 

</chassis-sub-module> 

</chassis-module> 

<chassis-module> 

<name>Power Supply 0</name> 

</chassis-module> 

</chassis> 

</chassis-inventory> 

這裏是我使用的解析,找到例如序列號的Perl代碼:

#!/bin/env perl 
use strict; 
use warnings; 
use XML::LibXML; 
my $f = ("/var/working/xmlstuff"); 
sub yeah { 
my $ff; 
my $f = shift; 
open(my $fff,$f); 
while(<$fff>) { 
$_ =~ s/^\s+$//; 
$_ =~ s/^(<\S+)\s.*?=.*?((?:\/)?>)/$1$2/g; 
$ff .= $_; 
} 
close($fff); 
return $ff 
} 
my $tparse = XML::LibXML->new(); 
my $ss = $tparse->load_xml(string => &yeah($f)); 
print map $_->to_literal,$ss->findnodes('/chassis-inventory/chassis/serial-number'); 

如果我不使用正則表達式替換沒有爲腳本加載解析。 我能理解換行符的剝離,但爲什麼我必須刪除從XML響應的屬性,所以它只能出現這些線條:

<chassis-inventory xmlns="http://xml.juniper.net/junos/10.3D0/junos-chassis"> 

<chassis junosstyle="inventory"> 

成爲這樣的:

<chassis-inventory> 
<chassis> 
  1. 這是XML響應還是XML :: LibXML模塊的問題?

  2. 有沒有辦法讓它忽略文件中沒有使用正則表達式替換的空行的事實?

感謝您的幫助。

+0

我相信這可能會失敗,因爲您的XML缺少正確的標頭和文檔類型。也就是說,這看起來很簡單,你可以嘗試使用XML :: Simple,即使XML不是100%正確的,也可以設置爲解析。 – Cfreak

回答

12

XPATH表達式失敗的原因是因爲命名空間;你需要在上下文中搜索。下面是來自XML::libXML documentation的解釋:

註記的命名空間和XPATH:

有關XPath的一個常見的錯誤是假設由元素名稱的 在默認 命名空間沒有前綴匹配元素節點測試。這個假設是錯誤的 - 通過XPath規範,例如 節點測試只能匹配名稱空間中沒有(即空) 的元素。

因此,例如,不能用$節點 - 一個XHTML 文件的根元素>找到(「/ HTML」),因爲「/ HTML」比賽將只有 根元素沒有命名空間匹配,但所有XHTML元素 都屬於命名空間http://www.w3.org/1999/xhtml。 (請注意, xmlns =「...」名稱空間聲明也可以在DTD中指定, 這會使情況更糟糕,因爲如果沒有默認名稱空間,XML文檔看起來爲 )。

要解決這個問題,請註冊命名空間,然後使用命名空間搜索您的文檔。下面是一個適用於您的示例:

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

my $xml = XML::LibXML->load_xml(location => '/var/working/xmlstuff'); 
my $xpc = XML::LibXML::XPathContext->new($xml); 
$xpc->registerNs('x', 'http://xml.juniper.net/junos/10.3D0/junos-chassis'); 

foreach my $node ($xpc->findnodes('/x:chassis-inventory/x:chassis/x:serial-number')) { 

    print $node->textContent() . "\n"; 
} 
+1

感謝您的解釋和解決方案。 – salparadise