linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘网络学院网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > 开发语言 > perl >
栏目导栏
  php
  JSP
  ASP
  asp.net
  JAVA
  c/c++/c#
  perl
  JavaScript
  Basic
  Delphi
资料搜索
热门文章
·perl入门学习指南
·perl入门教程:Perl 的变量
·perl入门教程:Perl的语法与C语
·Perl文件及目录操作
·perl入门教程:Perl概述
·perl入门教程:正则表达式
·perl 学习笔记
·Perl常用系统函数
·perl中传递和存储文件句柄
·Perl连接Oracle数据库的方法
·curl+perl的自动MAIL报警程序
·使用 perldoc 找文档
·perl入门教程:Perl 程序的属性
·Perl新手的误区和新手必读
·Perl命令行应用介绍
最新文章
·perl 学习笔记
·Perl 特殊变量
·perl Base64码的获取
·perl 父子进程的数据库连接继承
·工作中的实用 perl 脚本
·perl中传递和存储文件句柄
·curl+perl的自动MAIL报警程序
·Perl类包的动态调用
·使用open创建的管道进行父子进
·perl 执行一个系统命令(svn in
·windows平台下根据可执行文件名
·关联数组(hash)
·Perl语言在风险评估的系统基础
·在Perl/CGI中使用模板
·PERL CGI 常见问题
Google
 
入门教程:Perl XML:接口篇
[ 作者:  加入时间:2007-10-11 17:23:09  来自:Linux联盟收集整理 ]

入门简介zJnLinux联盟
最近在Perl-XML邮件组经常问起的问题是如何给不熟悉的用户一个对大量 Perl XML 模块的快速指引性概述文档。在接下来的几个月里我将单独对此问题写几篇专栏文章。 zJnLinux联盟
CPAN上的XML模块可以分成三大类:对 XML 数据提供独特的接口(通常有关在XML实例和Perl数据之间的转换),实现某一标准XML API的模块,和对一些特定的XML相关任务进行简化的特殊用途模块。这个月我们先关注第一个,XML Perl专用接口。

zJnLinux联盟
use Disclaimer qw(:standard);zJnLinux联盟
此文档不是为了对模块性能进行基准测试,我的目的也不是暗示某一模块比另一个模块更有用。为你的项目选择正确的 XML 模块更多依赖于项目本身和你积累的经验。不同的接口适应于不同的任务和不同的人。我的唯一目的是通过定义两个简单的任务,然后提供不同借口的可运行例子来显示如何获得同样的最终结果。 zJnLinux联盟
任务zJnLinux联盟
虽然XML的用途非常多,但大部分XML相关任务可分成两组:一是从已有的XML文档提取数据,另一个是使用其他资源的数据创建一个新的XML文档。既然如此,我们所用来介绍不同模块的例子将由“从一个XML文件中提取某一特定数据集”和“将一Perl数据结构转为某一特定XML格式”组成。 zJnLinux联盟
任务一:提取数据zJnLinux联盟
首先,假设有如下XML片断:

<?xml version="1.0"?>zJnLinux联盟
<camelids>zJnLinux联盟
  <species name="Camelus dromedarius">zJnLinux联盟
    <common-name>Dromedary, or Arabian Camel</common-name>zJnLinux联盟
    <physical-characteristics>zJnLinux联盟
      <mass>300 to 690 kg.</mass>zJnLinux联盟
      <appearance>zJnLinux联盟
        The dromedary camel is characterized by a long-curved zJnLinux联盟
        neck, deep-narrow chest, and a single hump.zJnLinux联盟
        ...zJnLinux联盟
      </appearance>zJnLinux联盟
    </physical-characteristics>zJnLinux联盟
    <natural-history>zJnLinux联盟
       <food-habits>zJnLinux联盟
         The dromedary camel is an herbivore.zJnLinux联盟
         ...zJnLinux联盟
       </food-habits>zJnLinux联盟
       <reproduction>zJnLinux联盟
         The dromedary camel has a lifespan of about 40-50 yearszJnLinux联盟
         ...zJnLinux联盟
       </reproduction>zJnLinux联盟
       <behavior>zJnLinux联盟
         With the exception of rutting males, dromedaries showzJnLinux联盟
         very little aggressive behavior.zJnLinux联盟
         ...zJnLinux联盟
       </behavior>zJnLinux联盟
       <habitat>zJnLinux联盟
         The camels prefer desert conditions characterized by azJnLinux联盟
         long dry season and a short rainy season.zJnLinux联盟
         ...zJnLinux联盟
       </habitat>zJnLinux联盟
    </natural-history>zJnLinux联盟
    <conservation status="no special status">zJnLinux联盟
      <detail>zJnLinux联盟
        Since the dromedary camel is domesticated, the camel haszJnLinux联盟
        no special status in conservation.zJnLinux联盟
      </detail>zJnLinux联盟
    </conservation>zJnLinux联盟
  </species>zJnLinux联盟
  ...zJnLinux联盟
</camelids>

现在我们假设此完整文档(可从本月例子代码中获取)包含骆驼家族所有成员的全部信息,而不仅仅是上面的单峰骆驼信息。为了举例说明每一模块是如何从此文件中提取某一数据子集,我们将写一个很简短的脚本来处理camelids.xml文档和在STDOUT上输出我们找到的每一种类的普通名(common-name),拉丁名(用括号包起来),和当前保存状况。因此,处理完整个文档,每一个脚本的输出应该为如下结果: zJnLinux联盟
Bactrian Camel (Camelus bactrianus) endangered zJnLinux联盟
Dromedary, or Arabian Camel (Camelus dromedarius) no special status zJnLinux联盟
Llama (Lama glama) no special status zJnLinux联盟
Guanaco (Lama guanicoe) special concernzJnLinux联盟
Vicuna (Vicugna vicugna) endangered

任务二:创建一个XML文档zJnLinux联盟
为了示范每一模块是如何从其他数据源中创建新的XML文档,我们将写一个小脚本将一个简单的Perl hash转换为一个简单的XHTML文档。hash里包含一些指向很cool的特定相关骆驼的网页的URLs。 zJnLinux联盟
Hash 如下:

my %camelid_links = (zJnLinux联盟
    one   => { url         => 'zJnLinux联盟
    http://www.online.discovery.com/news/picture/may99/photo20.html',zJnLinux联盟
               description => 'Bactrian Camel in front of Great ' .zJnLinux联盟
                              'Pyramids in Giza, Egypt.'},zJnLinux联盟
    two   => { url         => 'http://www.fotos-online.de/english/m/09/9532.htm',zJnLinux联盟
               description => 'Dromedary Camel illustrates the ' . zJnLinux联盟
                              'importance of accessorizing.'},zJnLinux联盟
    three => { url         => 'http://www.eskimo.com/~wallama/funny.htm',zJnLinux联盟
               description => 'Charlie - biography of a narcissistic llama.'},zJnLinux联盟
    four  => { url         => 'http://arrow.colorado.edu/travels/other/turkey.html',zJnLinux联盟
               description => 'A visual metaphor for the perl5-porters ' .zJnLinux联盟
                              'list?'},zJnLinux联盟
    five  => { url         => 'http://www.galaonline.org/pics.htm',zJnLinux联盟
               description => 'Many cool alpacas.'},zJnLinux联盟
    six   => { url         => 'http://www.thpf.de/suedamerikareise/galerie/vicunas.htm',zJnLinux联盟
               description => 'Wild Vicunas in a scenic landscape.'}zJnLinux联盟
);

而我们所期望从hash中创建的文档例子为:

<?xml version="1.0">zJnLinux联盟
<html>zJnLinux联盟
  <body>zJnLinux联盟
    <a href="Charlie">http://www.eskimo.com/~wallama/funny.htm">Charlie - zJnLinux联盟
      biography of a narcissistic llama.</a>zJnLinux联盟
    <a href="Bactrian">http://www.online.discovery.com/news/picture/may99/photo20.html">BactrianzJnLinux联盟
      Camel in front of Great Pyramids in Giza, Egypt.</a>zJnLinux联盟
    <a href="Dromedary">http://www.fotos-online.de/english/m/09/9532.htm">DromedaryzJnLinux联盟
      Camel illustrates the importance of accessorizing.</a>zJnLinux联盟
    <a href="Many">http://www.galaonline.org/pics.htm">Many cool alpacas.</a>zJnLinux联盟
    <a href="A">http://arrow.colorado.edu/travels/other/turkey.html">A visual zJnLinux联盟
      metaphor for the perl5-porters list?</a>zJnLinux联盟
    <a href="Wild">http://www.thpf.de/suedamerikareise/galerie/vicunas.htm">WildzJnLinux联盟
      Vicunas in a scenic landscape.</a>zJnLinux联盟
  </body>zJnLinux联盟
</html>

良好缩进的XML结果文件(如上面所显示的)对于阅读很重要,但这种良好的空格处理不是我们案例所要求的。我们所关心的是结果文档是结构良好的/well-formed和它正确地表现了hash里的数据。 zJnLinux联盟
任务定义完毕,接下来该是代码例子的时候了。

zJnLinux联盟
XML Perl专用接口例子zJnLinux联盟
XML::SimplezJnLinux联盟
最初创建用来简化读写XML格式配置文件的XML::Simple, 在转换XML文档和Perl数据结构之间没有另外的抽象接口。所有的元素和属性都可以通过嵌套的引用直接读取。

ReadingzJnLinux联盟
use XML::Simple;

my $file = 'files/camelids.xml';zJnLinux联盟
my $xs1 = XML::Simple->new();

my $doc = $xs1->XMLin($file);

foreach my $key (keys (%{$doc->{species}})){zJnLinux联盟
   print $doc->{species}->{$key}->{'common-name'} . ' (' . $key . ') ';zJnLinux联盟
   print $doc->{species}->{$key}->{conservation}->final . "\n";zJnLinux联盟
}

WritingzJnLinux联盟
use XML::Simple;

require "files/camelid_links.pl";zJnLinux联盟
my %camelid_links = get_camelid_data();

my $xsimple = XML::Simple->new();

print $xsimple->XMLout(\%camelid_links,zJnLinux联盟
                       noattr => 1,zJnLinux联盟
                       xmldecl => '');

这数据到文档的任务的条件要求暴露了XML::Simple的一个弱点:它没有允许我们决定hash里的哪个key应该作为元素返回和哪个key该作为属性返回。上面例子的输出虽然接近我们的输出要求但还远远不够。对于那些更喜欢将XML文档内容直接作为Perl数据结构操作,而且需要在输出方面做更细微控制的案例,XML::Simple和XML::Writer配合得很好。 zJnLinux联盟
如下例子说明了如何使用XML::Write来符合我们的输出要求。

use XML::Writer;

require "files/camelid_links.pl";zJnLinux联盟
my %camelid_links = get_camelid_data();

my $writer = XML::Writer->new();

$writer->xmlDecl();zJnLinux联盟
$writer->startTag('html');zJnLinux联盟
$writer->startTag('body');

foreach my $item ( keys (%camelid_links) ) {zJnLinux联盟
    $writer->startTag('a', 'href' => $camelid_links{$item}->{url});zJnLinux联盟
    $writer->characters($camelid_links{$item}->{description});zJnLinux联盟
    $writer->endTag('a');zJnLinux联盟
}

$writer->endTag('body');zJnLinux联盟
$writer->endTag('html');

$writer->end();

XML::SimpleObjectzJnLinux联盟
XML::SimpleObject 对XML数据使用回想文档对象模型(Document Object Model)的存取器/accessor来提供一个面对对象接口。 zJnLinux联盟
ReadingzJnLinux联盟
use XML::Parser;zJnLinux联盟
use XML::SimpleObject;

my $file = 'files/camelids.xml';

my $parser = XML::Parser->new(ErrorContext => 2, Style => "Tree");zJnLinux联盟
my $xso = XML::SimpleObject->new( $parser->parsefile($file) );

foreach my $species ($xso->child('camelids')->children('species')) {zJnLinux联盟
    print $species->child('common-name')->{VALUE};zJnLinux联盟
    print ' (' . $species->attribute('name') . ') ';zJnLinux联盟
    print $species->child('conservation')->attribute('status');zJnLinux联盟
    print "\n";zJnLinux联盟
}

WritingzJnLinux联盟
XML::SimpleObject 没有通过抓取来创建XML文档的功能。但是与上面的XML::Simple例子一样,可以通过与XML::Writer配合简单的完成任务。 zJnLinux联盟
XML::TreeBuilderzJnLinux联盟
XML::TreeBuilder 包由两模块组成:XML::Element用来创建和获得XML元素点的内容和XML::TreeBuilder作为一个工厂包从已有XML文件中简化文档树的创建。对于那些已有值得尊敬的 HTML::Element 和 HTML::Tree 模块使用经验的人来说,使用 XML::TreeBuilder 是非常容易的,因为除了XML特有的方法外其他都是一样的。 zJnLinux联盟
ReadingzJnLinux联盟
use XML::TreeBuilder;

my $file = 'files/camelids.xml';zJnLinux联盟
my $tree = XML::TreeBuilder->new();

$tree->parse_file($file);

foreach my $species ($tree->find_by_tag_name('species')){zJnLinux联盟
    print $species->find_by_tag_name('common-name')->as_text;zJnLinux联盟
    print ' (' . $species->attr_get_i('name') . ') ';zJnLinux联盟
    print $species->find_by_tag_name('conservation')->attr_get_i('status');zJnLinux联盟
    print "\n";zJnLinux联盟
}

WritingzJnLinux联盟
use XML::Element;

require "files/camelid_links.pl";zJnLinux联盟
my %camelid_links = get_camelid_data();

zJnLinux联盟
my $root = XML::Element->new('html');zJnLinux联盟
my $body = XML::Element->new('body');zJnLinux联盟
my $xml_pi = XML::Element->new('~pi', text => 'xml version="1.0"');zJnLinux联盟
$root->push_content($body);

foreach my $item ( keys (%camelid_links) ) {zJnLinux联盟
    my $link = XML::Element->new('a', 'href' => $camelid_links{$item}->{url});zJnLinux联盟
    $link->push_content($camelid_links{$item}->{description});zJnLinux联盟
    $body->push_content($link);zJnLinux联盟
}

print $xml_pi->as_XML;zJnLinux联盟
print $root->as_XML();

XML::TwigzJnLinux联盟
XML::Twig 与其他只有Perl的XML接口不同,它是一个除了标准的XML APIs外还有其它富有创造性特点的Perlish接口。需要更多更详细的介绍请查看XML.com 文章 zJnLinux联盟
ReadingzJnLinux联盟
use XML::Twig;

my $file = 'files/camelids.xml';zJnLinux联盟
my $twig = XML::Twig->new();

$twig->parsefile($file);

my $root = $twig->root;

foreach my $species ($root->children('species')){zJnLinux联盟
    print $species->first_child_text('common-name');zJnLinux联盟
    print ' (' . $species->att('name') . ') ';zJnLinux联盟
    print $species->first_child('conservation')->att('status');zJnLinux联盟
    print "\n";zJnLinux联盟
}

Writing

use XML::Twig;

require "files/camelid_links.pl";zJnLinux联盟
my %camelid_links = get_camelid_data();

my $root = XML::Twig::Elt->new('html');zJnLinux联盟
my $body = XML::Twig::Elt->new('body');zJnLinux联盟
$body->paste($root);

foreach my $item ( keys (%camelid_links) ) {zJnLinux联盟
    my $link = XML::Twig::Elt->new('a');zJnLinux联盟
    $link->set_att('href', $camelid_links{$item}->{url});zJnLinux联盟
    $link->set_text($camelid_links{$item}->{description});zJnLinux联盟
    $link->paste('last_child', $body);zJnLinux联盟
}

print qq|<?xml version="1.0"?>|;zJnLinux联盟
$root->print;

这些例子举例说明了这些普通XML Perl模块的基本使用方法。我的目标是提供足够多的例子让你感受怎么用每个模块写代码。下个月我们将关注“实现某一标准XML API的模块”,特别说明的,XML::DOM, XML::XPath 和其他大量的 SAX 和类SAX模块。

Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·Delphi下的接口编程学习笔记  (2007-10-30 15:11:56)
 ·Com接口入门细详(一)  (2007-10-30 15:09:42)
 ·Com接口入门细详(二)  (2007-10-30 15:09:04)
 ·Java数据库接口JDBC驱动设置  (2007-10-25 12:23:34)
 ·Linux网络接口卡安装配置介绍  (2007-10-25 10:13:53)
 ·Java中消除实现继承和面向接口编程  (2007-10-24 16:00:34)
 ·Java中用接口实现多继承和多态的方法  (2007-10-24 14:59:07)
 ·Linux操作系统中BSD套接口开发基础  (2007-10-15 11:10:55)
 ·ArrayAccess接口介绍  (2007-10-11 12:01:52)
 ·详细讲解如何用ODBC接口访问MySQL指南  (2007-05-31 12:00:48)