2016-12-19 53 views
2

我創建一個XML傳遞給一個API和API返回這個(轉儲數據):在perl中我如何循環這個結構?

(
    "Data::Dump", 
    { 
     SiteDevices => { 
     "device" => { 
         1102 => { address => "1.2.3.4", riskfactor => "1.0", riskscore => "0.0" }, 
         1136 => { address => "1.2.3.5", riskfactor => "1.0", riskscore => "0.0" }, 
         20491 => { address => "1.2.3.6", riskfactor => "1.0", riskscore => "0.0" }, 
         129644 => { address => "1.2.3.7", riskfactor => "1.0", riskscore => "0.0" }, 
         129645 => { address => "1.2.3.8", riskfactor => "1.0", riskscore => "0.0" }, 
         130408 => { address => "1.2.3.9", riskfactor => "1.0", riskscore => "0.0" }, 
         135975 => { address => "1.2.3.10", riskfactor => "1.0", riskscore => "0.0" }, 
         137642 => { address => "1.2.3.11", riskfactor => "1.0", riskscore => "0.0" }, 
        }, 
     "site-id" => 27, 
     }, 
     success => 1, 
    }, 
) 

我通過要循環和打印他們和我有關的設備和IP爲我的生活不能拿出任何代碼來做到這一點。我錯過了什麼?!我試圖循環散列,哈希散列等。永遠不能得到它的工作。如果你們中的任何一個人有第二個,並且能夠提供答案,那麼我就可以搖頭,這真是太棒了。

我曾嘗試:

foreach my $key (keys %{ $output->{‘SiteDevices’}->{‘device’} }) { 
     print $key 
     print $key->{‘address’} 
} 

foreach my $key (keys %{ $output{‘SiteDevices’}{‘device’} }) { 
     print $key 
     print $key{‘address’} 
} 

但既不工程。

+0

輸出中有多少'SiteDevices'條目?只有一個? – stevieb

+0

這看起來像解析XML一樣可疑。有沒有機會?如果是這樣,我建議你最好在上游工作並使用更好的解析器。添加一個XML的例子,給你一個更好的例子會容易得多。 – Sobrique

回答

5

你提這個被解析XML。它看起來就像你用XML::Simplethat's just not a good idea.

分析它爲什麼不來代替:

#!/usr/bin/env perl 
use strict; 
use warnings; 

use XML::Twig; 

## get xml somehow here. parsefile if it's a file already. 
my $twig = XML::Twig -> new -> parse ($your_xml); 

foreach my $device ($twig -> get_xpath('//devices')) { 
    print $device -> att('name'), " => "; 
    print $device -> att('address'),"\n"; 
} 

這裏的有用的東西是xpath - 它不是一個正則表達式,但它有點類似 - 它適用於XML。在這種情況下,//device表示'在樹中的任意位置找到<device>節點。 (然後我們提取屬性)。

這可能是你的情況下工作,但你可以通過指定一個較長的路徑更具體:

  • ./device - 直接在當前節點下方。
  • .//device - 位於當前節點下的任何位置。
  • /root/SiteDevices/device - 與此「樹」特別匹配的節點。

您還可以使用xpath對屬性進行搜索:

  • .//device[@name="1136"]會找到合適的值和屬性的東西。

請參閱XML Twig有關如何執行此操作的一些指南的快速參考。

+1

我想感謝您的支持!試圖弄清楚這一點,我一直在桌子上敲着頭。而且你在幾秒鐘內完成了修復。我會更多地閱讀小枝是如何工作的,因爲我做了一個轉儲,它有一個瘋狂的信息。但循環打印所需的信息! – robamcclellan

+1

@robamcclellan:請注意,Sobrique使用了XPath'// devices',它可以找到文檔中任何位置的所有'devices'節點。我猜他選擇的是因爲我們沒有看到你的XML數據,所以不知道根元素的名字。通常最好使用'/ root/SiteDevices/device'來更具體地隔離節點,但我們不能說出'root'應該是什麼。 – Borodin

+1

@robamcclellan你可能不想轉儲XML :: Twig(或任何XML :: Twig :: Elt)對象。把它想象成一根香腸; - )你可以使用'_dump'方法來獲得樹的表示,但是真正漂亮的XML打印就像信息一樣。查看http://xmltwig.org/xmltwig/quick_ref.html獲取有用方法的第一個列表 – mirod

2

我相信下面的循環會做你正在努力完成的。它將從樹中的每個設備,然後提取出它的地址,並打印兩種:

for my $device (keys %{ $output->{SiteDevices}{device} }){ 
    print "$device: $output->{SiteDevices}{device}{$device}{address}\n"; 
} 

在你的測試,你要使用的鍵名作爲哈希/哈希引用,這是行不通的。您需要將提取的密鑰放回哈希中以執行進一步的提取。

輸出的基礎上,我抽出你的問題的一個記錄:

129644: 1.2.3.7 
129645: 1.2.3.8 
130408: 1.2.3.9 
137642: 1.2.3.11 
1136: 1.2.3.5 
135975: 1.2.3.10 
1102: 1.2.3.4 
20491: 1.2.3.6