2010-09-06 39 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