2012-03-07 20 views
3

以下只是我工作的XML的一小部分。我想提取子列表下的所有屬性,標籤名稱和文本。如何擺脫由Perl的XML :: LibXML模塊中的findnodes返回的不需要的節點?

<?xml version='1.0' encoding='UTF-8'?> 
<Warehouse> 
<Equipment id="ABC001" model="TV" version="3_00"> 
<attributes> 
<Location>Chicago</Location> 
<Latitude>30.970</Latitude> 
<Longitude>-90.723</Longitude> 
</attributes> 
</Equipment></Warehouse> 

我已編碼的例子是這樣的:

#!/usr/bin/perl 
use XML::LibXML; 
use Data::Dumper; 

$parser = XML::LibXML->new(); 
$Chunk = $parser->parse_file("numone.xml"); 

@Equipment = $Chunk->findnodes('//Equipment'); 
foreach $at ($Equipment[0]->getAttributes()) { 
    ($na,$nv) = ($at -> getName(),$at -> getValue()); 
    print "$na => $nv\n"; 
} 

@Equipment = $Chunk->findnodes('//Equipment/attributes'); 
@Attr = $Equipment[0]->childNodes; 
print Dumper(@Attr); 

foreach $at (@Attr) { 
    ($na,$nv) = ($at->nodeName, $at->textContent); 
    print "$na => $nv\n"; 
} 

我得到的結果是這樣的:

id => ABC001 
model => TV 
version => 3_00 
$VAR1 = bless(do{\(my $o = 10579528)}, 'XML::LibXML::Text'); 
$VAR2 = bless(do{\(my $o = 13643928)}, 'XML::LibXML::Element'); 
$VAR3 = bless(do{\(my $o = 13657192)}, 'XML::LibXML::Text'); 
$VAR4 = bless(do{\(my $o = 13011432)}, 'XML::LibXML::Element'); 
$VAR5 = bless(do{\(my $o = 10579752)}, 'XML::LibXML::Text'); 
$VAR6 = bless(do{\(my $o = 10565696)}, 'XML::LibXML::Element'); 
$VAR7 = bless(do{\(my $o = 13046400)}, 'XML::LibXML::Text'); 
#text => 

Location => Chicago 
#text => 

Latitude => 30.970 
#text => 

Longitude => -90.723 
#text => 

提取屬性看起來OK,但提取標籤名稱和文字得到了額外的內容。 我的問題是:

  1. 那些人在那裏::Text元素是從哪裏來的?
  2. 我該如何擺脫那些額外的元素和#text的東西?

感謝,

回答

3

額外的節點是隻包含空白,例如文本節點,元素之間的換行符。跳過他們,如果你想:

@Equipment = $Chunk->findnodes('//Equipment/attributes'); 
@Attr = $Equipment[0]->childNodes; 
foreach $at (@Attr) { 
    ($na,$nv) = ($at->nodeName, $at->textContent); 

    next if $na eq "#text"; # skip text nodes between elements 

    print "$na => $nv\n"; 
} 

輸出:

id => ABC001 
model => TV 
version => 3_00 
Location => Chicago 
Latitude => 30.970 
Longitude => -90.723
+0

格雷格你的方法取得了訣竅。非常感謝! – mkt2012 2012-03-07 17:20:41

+0

@ mkt2012不客氣! – 2012-03-07 17:28:39

+1

這將忽略*所有*文本節點,不管它們是否包含有用的信息。最好編寫'next,如果$ na eq「#text」和$ nv!〜/ \ S /;' – Borodin 2012-03-07 19:26:02

3

首先,你真的應該use strictuse warnings在程序的開始,並在第一次使用的時候用my聲明所有變量。這會顯示出許多簡單的錯誤,在您要求幫助的程序中尤其重要。

正如您所知,XML::LibXML::Text條目是空白文本節點。如果你想讓XML::LibXML解析器忽略,然後在解析器對象上設置no_blanks選項。

此外,您會使用最近load_xml方法,而不是過時的parse_file如下

my $parser = XML::LibXML->new(no_blanks => 1); 
my $Chunk = $parser->load_xml(location => "numone.xml"); 

會更好,從這個變化版本的程序的輸出看起來像

id => ABC001 
model => TV 
version => 3_00 
$VAR1 = bless(do{\(my $o = 7008120)}, 'XML::LibXML::Element'); 
$VAR2 = bless(do{\(my $o = 7008504)}, 'XML::LibXML::Element'); 
$VAR3 = bless(do{\(my $o = 7008144)}, 'XML::LibXML::Element'); 
Location => Chicago 
Latitude => 30.970 
Longitude => -90.723 
相關問題