使用 Perl 的 XML::Simple 解析 XML 文档

随着越来越多的 Web 站点开始使用 XML 作为他们的内容,Web 开发人员知道如何解析 XML 数据并将其转换成不同的格式突显重要起来。以前有两种方法实现这一点:设计一些回调处理函数,在一个特定的元素类型被识别时这些回调处理函数被调用(SAX),或者创建一个 XML 文档树,并使用树导航方法访问单独的内容片断(DOM)。

两种方法有一个共同的要点:实现起来不易,尤其是对于 XML 新手来说更是如此。Web 开发人员真正需要的是一些能够使解析 XML 数据像遍历数组或读取文件一样简单的东西。

这就是非常有用的 Perl 模块XML::Simple 出现的原因。它消除了解析XML 数据的痛苦,使得这一过程比你能想象的还要简单。在读完这篇文章之后,你就会知道从如何将 XML 数据转换成 Perl 可用的格式以及如何根据 Perl 哈希创建 XML 文件。

安装

XML::Simple 能够解析一个 XML 文件并在以一个 Perl 哈希引用返回数据。在这个哈希中,来自原始 XML 文件的元素作为键,而它们之间的 CDATA 作为值。一旦XML::Simple 处理完一个 XML 文件,XML 文件的内容就可以使用标准 Perl 数组表示法检索。

XML::Simple 完全用 Perl 写成,它是作为XML::Parser 模块之上的一个 API 层实现的,目前由Grant McLean 维护。它捆绑在最新的 Perl 发布中,但是如果你没有最新的 Perl 发布,获取该模块的最简单的方法是从 CPAN 下载。在下载的压缩文件中提供了详细的安装说明,但是目前为上最简单的安装方法是使用 CPAN shell:

shell> perl -MCPAN -e shell

cpan> install XML::Simple

如果使用 CPAN shell,依赖模块会被自动下载(除非你将 shell 配置为不下载依赖模块)。如果手工下载和安装这个模块,那么在安装XML::Simple 之前你可能需要先下载和安装XML::Parser 模块。这篇文章使用的XML::Simple 版本是2.12。

基本的XML解析

在安装了这个模块之后,创建下面的 XML 文件然后保存为“data.xml”。

<?xml version='1.0'?>

<employee>

<name>John Doe</name>

<age>43</age>

<sex>M</sex>

<department>Operations</department>

</employee>

然后敲入以下 Perl 脚本,这段脚本使用XML::Simple 模块解析了前面的 XML。

#!/usr/bin/perl

# use module

use XML::Simple;

use Data::Dumper;

# create object

$xml = new XML::Simple;

# read XML file

$data = $xml->XMLin("data.xml");

# print output

print Dumper($data);

使用XML::Simple 本身相当简单。XML::Simple 类的每个对象暴露两个方法:XMLin() 和 XMLout()。XMLin() 方法读取一个 XML 文件或字符串,然后将其转换成一个 Perl 表示;XMLout() 方法则正好相反,读取一个 Perl 结构并将其作为一个 XML 文档实例返回。上面的脚本使用XMLin() 方法读取前面创建的“data.xml”然后将处理结果存储在 $data 中。然后,$data 的内容使用Perl 的 Data::Dumper 显示出来。

在运行这个脚本时,会得到下面的输出:

$VAR1 = {

'department' => 'Operations',

'name' => 'John Doe',

'sex' => 'M',

'age' => '43'

};

从上面的结果可以看到,每个元素和与其相关的内容都被转换成一个键值对 Perl 关联数组。你现在可以把上面的脚本反向改为下面的脚本来访问 XML 数据:

#!/usr/bin/perl

# use module

use XML::Simple;

# create object

$xml = new XML::Simple;

# read XML file

$data = $xml->XMLin("data.xml");

# access XML data

print "$data-> is $data-> years old and works in the $data-> section ";

下面是输出:

John Doe is 43 years old and works in the Operations section [/output]

下面让我们看一下如何使用 XML::Simple 来处理更复杂的 XML 文档。

处理多级文档树

XML::Simple 的基本 XML 处理功能的易用性也可以扩展到具有多级的 XML 文档上。考虑列表A中的 XML 文件。如果使用 XMLin() 方法读取这个 XML 文件,你将会得到与列表B所示内容相似的结构。

XML::Simple 在一个匿名数组中将重复的元素表示为项。因而,XML 文件中的各个<employee> 元素被转换成一个 Perl 数组,每个数组元素表示一个 employee。所以,如果要访问值“John Doe”,只需要简单地使用下面这个语法:$data->->[0]->。

你还可以在一个 Perl 脚本中通过解引用$data-> 然后使用 foreach() 循环遍历数组来做到这一点。列表C中的代码是这样一个例子。下面是其输出:

John Doe

Age/Sex: 43/M

Department: Operations

Jane Doe

Age/Sex: 31/F

Department: Accounts

Be Goode

Age/Sex: 32/M

Department: Human Resources

处理属性(attribute

XML::Simple 处理属性的方式与它处理元素的方式基本相同——把它们放到一个哈希中。考虑列表D中的 XML 文件。

如果使用XML::Simple 解析列表D中的 XML 文件,输出将会类似于列表E。注意每个元素的内容被放在一个特殊的键“content”中,你可以使用前面讨论的标准表示法来访问这个键。

控制解析行为

用于控制XML::Simple 行为的两个有用的选项是ForceArray 和KeyAttr 选项,这两个选项一般都传递给对象构造器。ForceArray 选项是一个布尔标志,它告诉XML::Simple 将 XML 元素转换成常规的加了索引的数组,而不是转换成哈希。列表F中的代码片断举例说明了这一点。下面是列表F的输出:

$VAR1 = {

'department' => [

'Operations'

],

'name' => [

'John Doe'

],

'sex' => [

'M'

],

'age' => [

'43'

]

};

如果想要在 Perl 中创建 XML 文档的一致表示,那么这个输出是很有用的。简单地将所有元素和属性强迫转成一个数组形式,然后使用 Perl 的数组函数来处理它们。

另外一个重要的选项是KeyAttr,它告诉XML::Simple 在构建XML 文档的哈希表示时使用一个特定的元素作为一个唯一“键”。在指定这样一个键之后,对应元素的值(而不是其名字)被用作哈希引用中的一个键,它充当快速访问相关数据的一个索引。

理解这个选项的最好方式是看例子。考虑列表G中的 XML 文件。如果使用XML::Simple 解析这个文件,一般会得到列表H中的一个 Perl 结构。然而,如果告诉XML::Simple 使用 SKU 域作为每个项的一个唯一索引,将它作为KeyAttr 选项传递给构造器,如下所示:

$xml = new XML::Simple (KeyAttr=>'sku');

生成的 Perl 结构就会变为使用那个元素的值作为键,在列表I中可以看到其结果。这样就允许你直接使用 SKU 访问一个项——例如,$data->->->。

Perl结构写到XML

最后,你还可以使用XML::Simple 的 XMLout() 方法将一个 Perl 对象转换成一个 XML 文档。下面是一个例子:

#!/usr/bin/perl

# use module

use XML::Simple;

use Data::Dumper;

# create array

@arr = [

{'country'=>'england', 'capital'=>'london'},

{'country'=>'norway', 'capital'=>'oslo'},

{'country'=>'india', 'capital'=>'new delhi'} ];

# create object

$xml = new XML::Simple (NoAttr=>1, RootName=>'data');

# convert Perl array ref into XML document

$data = $xml->XMLout(@arr);

# access XML data

print Dumper($data);

下面是它的输出:

<data>

<anon>

<anon>

<country>england</country>

<capital>london</capital>

</anon>

<anon>

<country>norway</country>

<capital>oslo</capital>

</anon>

<anon>

<country>india</country>

<capital>new delhi</capital>

</anon>

</anon>

</data>

无须多说,这个同样的 XML 文档可以被XML::Simple 读取并重新创建原始的 Perl 结构。

这就是本篇文章的内容。希望你能够更好地理解XML::Simple 的名称的含义所在,下次能够使用 Perl 来解析 XML 文件。