2010-09-06 198 views
2

的XML結構如下:解析XML文件 - 保留序列

<Entities> 
    <Entity> 
     <EntityName>.... </EntityName> 
     <EntityType>.... </EntityType> 
     <Tables> 
      <DataTables> 
       <DataTable>1</DataTable> 
       <DataTable>2</DataTable> 
       <DataTable>3</DataTable> 
       <DataTable>4</DataTable> 
      </DataTables> 
      <OtherTables> 
       <OtherTable>5</OtherTable> 
       <OtherTable>6</OtherTable> 
      </OtherTables> 
     </Tables> 
    </Entity> 
. 
. 
. 
</Entities> 

我需要解析基於選擇的實體名稱的文件,並專門檢索中提到的順序中的所有表。我如何在Perl中執行此操作以及應該使用哪個模塊?

+0

就這麼你知道,XML沒有這樣設置。如果你想要真正的元素排序,最好有一個名爲「order」的屬性填充順序值。 – vol7ron 2010-09-06 12:49:15

回答

8

我最喜歡的模塊在Perl解析XML是XML::Twigtutorial)。

代碼示例:

use XML::Twig; 

my $twig = XML::Twig->new(
    twig_handlers => { 
     #calls the get_tables method for each Entity element 
     Entity => sub {get_tables($_);}, 
    }, 
    pretty_print => 'indented',    # output will be nicely formatted 
    empty_tags => 'html',     # outputs <empty_tag /> 
    keep_encoding => 1, 
); 

$twig->parsefile(xml-file); 
$twig->flush; 

sub get_tables { 
    my $entity = shift; 

    #Retrieves the sub-elements of DataTables 
    my @data_tables = $entity->first_child("Tables")->children("DataTables"); 
    #Do stuff with the DataTables 

    #Retrieves the sub-elements of OtherTables 
    my @other_tables = $entity->first_child("Tables")->children("OtherTables"); 
    #Do stuff with the OtherTables 

    #Flushes the XML element from memory 
    $entity->purge; 
} 
+0

另外,任何元素的子元素列表將按照文檔順序即。與xml文件中的相同。 – 2010-09-07 04:32:01

-1

xml-simple

使用它之前,請記住,一些像點

XML ::簡單的是能夠提出一個簡單的API,因爲它使代表你的一些假設。這些措施包括:

  • 你不感興趣的文本內容 只包含空格的
  • 你不介意當事情變得 咕嚕咕嚕到一個哈希的訂單丟失
  • 你不要生成的XML的格式的細粒度控制
  • 你絕不會使用散列密鑰 不是一個合法的XML元素名稱
  • 你並不需要幫助轉換不同的編碼

對於基於事件的解析,使用SAX之間(不着手編寫XML任何新代碼::解析器的處理程序API - 這是已廢棄)。

對於基於樹的解析,您可以在XML :: Twig的「Perlish」方法和更多基於標準的DOM實現之間進行選擇 - 最好使用XPath支持。

:XML的簡單

有關Perl的XML更詳細,請參閱Perl-XML

+0

謝謝,但我曾嘗試XML簡單。引用表示「元素的順序不同,因爲哈希不保存它們包含的項目的順序」。所以我懷疑表格的順序是否會保留.. – Abhishek 2010-09-06 09:31:06

+0

@Abhi:這是真的,XML-Simple假定當事情變得混亂時,訂單就會丟失。 – 2010-09-06 09:35:46

+1

這個答案不好:使用XML :: Simple的建議。非常好:解釋爲什麼它不好。 – reinierpost 2010-09-15 15:28:22

2

文獻順序defined作爲

有一個排序,文檔順序,所有文檔中的對應於所述順序的節點上限定的其中每個節點的XML表示的第一個字符在擴展一般實體之後出現在文檔的XML表示中。因此,根節點將成爲第一個節點。元素節點出現在他們的子女面前因此,文檔順序命令元素節點按XML中的起始標籤的出現順序(在擴展實體之後)。

換句話說,事情發生在XML文檔中的順序。XML::XPath模塊按文件順序生成結果。例如:

#! /usr/bin/perl 

use warnings; 
use strict; 

use XML::XPath; 

my $entity_template = "/Entities" 
        . "/Entity" 
        . "[EntityName='!!NAME!!']" 
        ; 

my $tables_path = join "|" => 
        qw(./Tables/DataTables/DataTable 
         ./Tables/OtherTables/OtherTable); 

my $xp = XML::XPath->new(ioref => *DATA); 

foreach my $ename (qw/ foo bar /) { 
    print "$ename:\n"; 
    (my $path = $entity_template) =~ s/!!NAME!!/$ename/g; 
    foreach my $n ($xp->findnodes($path)) { 
    foreach my $t ($xp->findnodes($tables_path, $n)) { 
     print $t->toString, "\n"; 
    } 
    } 
} 

__DATA__ 

<Entity>元件,其中每個具有<ElementName>孩子其string-value是選擇的實體名稱的第一個表達式搜索。從那裏,我們尋找<DataTable><OtherTable>

鑑於

<Entities> 
    <Entity> 
     <EntityName>foo</EntityName> 
     <EntityType>type1</EntityType> 
     <Tables> 
      <DataTables> 
       <DataTable>1</DataTable> 
       <DataTable>2</DataTable> 
      </DataTables> 
      <OtherTables> 
       <OtherTable>3</OtherTable> 
       <OtherTable>4</OtherTable> 
      </OtherTables> 
     </Tables> 
    </Entity> 
    <Entity> 
     <EntityName>bar</EntityName> 
     <EntityType>type2</EntityType> 
     <Tables> 
      <DataTables> 
       <DataTable>5</DataTable> 
       <DataTable>6</DataTable> 
      </DataTables> 
      <OtherTables> 
       <OtherTable>7</OtherTable> 
       <OtherTable>8</OtherTable> 
      </OtherTables> 
     </Tables> 
    </Entity> 
</Entities> 

輸出輸入是

foo: 
<DataTable>1</DataTable> 
<DataTable>2</DataTable> 
<OtherTable>3</OtherTable> 
<OtherTable>4</OtherTable> 
bar: 
<DataTable>5</DataTable> 
<DataTable>6</DataTable> 
<OtherTable>7</OtherTable> 
<OtherTable>8</OtherTable> 

提取字符串值(下稱「內文」),改變$tables_path

my $tables_path = "./Tables/DataTables/DataTable/text() | 
        ./Tables/OtherTables/OtherTable/text()"; 

是,這是重複的 - 因爲XML :: XPath實現了XPath 1.0

輸出:

foo: 
1 
2 
3 
4 
bar: 
5 
6 
7 
8
+0

嗨..我怎麼才能得到使用XPath的值?例如:1 2 3 4 – Abhishek 2010-09-15 12:29:36

+1

@Abhi查看更新的答案。 – 2010-09-15 14:38:46