CPAN上的XML模块可以分成三大类:对 XML 数据提供独特的接口(通常有关在XML实例和Perl数据之间的转换),实现某一标准XML API的模块,和对一些特定的XML相关任务进行简化的特殊用途模块。这个月我们先关注第一个,XML Perl专用接口。
<?xml version="1.0"?>
<camelids>
<species name="Camelus dromedarius">
<common-name>Dromedary, or Arabian Camel</common-name>
<physical-characteristics>
<mass>300 to 690 kg.</mass>
<appearance>
The dromedary camel is characterized by a long-curved
neck, deep-narrow chest, and a single hump.
...
</appearance>
</physical-characteristics>
<natural-history>
<food-habits>
The dromedary camel is an herbivore.
...
</food-habits>
<reproduction>
The dromedary camel has a lifespan of about 40-50 years
...
</reproduction>
<behavior>
With the exception of rutting males, dromedaries show
very little aggressive behavior.
...
</behavior>
<habitat>
The camels prefer desert conditions characterized by a
long dry season and a short rainy season.
...
</habitat>
</natural-history>
<conservation status="no special status">
<detail>
Since the dromedary camel is domesticated, the camel has
no special status in conservation.
</detail>
</conservation>
</species>
...
</camelids>
现在我们假设此完整文档(可从本月例子代码中获取)包含骆驼家族所有成员的全部信息,而不仅仅是上面的单峰骆驼信息。为了举例说明每一模块是如何从此文件中提取某一数据子集,我们将写一个很简短的脚本来处理camelids.xml文档和在STDOUT上输出我们找到的每一种类的普通名(common-name),拉丁名(用括号包起来),和当前保存状况。因此,处理完整个文档,每一个脚本的输出应该为如下结果: Bactrian Camel (Camelus bactrianus) endangered Dromedary, or Arabian Camel (Camelus dromedarius) no special status Llama (Lama glama) no special status Guanaco (Lama guanicoe) special concern Vicuna (Vicugna vicugna) endangered
Hash 如下:
my %camelid_links = (
one => { url => '
http://www.online.discovery.com/news/picture/may99/photo20.html',
description => 'Bactrian Camel in front of Great ' .
'Pyramids in Giza, Egypt.'},
two => { url => 'http://www.fotos-online.de/english/m/09/9532.htm',
description => 'Dromedary Camel illustrates the ' .
'importance of accessorizing.'},
three => { url => 'http://www.eskimo.com/~wallama/funny.htm',
description => 'Charlie - biography of a narcissistic llama.'},
four => { url => 'http://arrow.colorado.edu/travels/other/turkey.html',
description => 'A visual metaphor for the perl5-porters ' .
'list?'},
five => { url => 'http://www.galaonline.org/pics.htm',
description => 'Many cool alpacas.'},
six => { url => 'http://www.thpf.de/suedamerikareise/galerie/vicunas.htm',
description => 'Wild Vicunas in a scenic landscape.'}
);
而我们所期望从hash中创建的文档例子为:
<?xml version="1.0">
<html>
<body>
<a href="http://www.eskimo.com/~wallama/funny.htm">Charlie -
biography of a narcissistic llama.</a>
<a href="http://www.online.discovery.com/news/picture/may99/photo20.html">Bactrian
Camel in front of Great Pyramids in Giza, Egypt.</a>
<a href="http://www.fotos-online.de/english/m/09/9532.htm">Dromedary
Camel illustrates the importance of accessorizing.</a>
<a href="http://www.galaonline.org/pics.htm">Many cool alpacas.</a>
<a href="http://arrow.colorado.edu/travels/other/turkey.html">A visual
metaphor for the perl5-porters list?</a>
<a href="http://www.thpf.de/suedamerikareise/galerie/vicunas.htm">Wild
Vicunas in a scenic landscape.</a>
</body>
</html>
良好缩进的XML结果文件(如上面所显示的)对于阅读很重要,但这种良好的空格处理不是我们案例所要求的。我们所关心的是结果文档是结构良好的/well-formed和它正确地表现了hash里的数据。
任务定义完毕,接下来该是代码例子的时候了。
use XML::Simple;
my $file = 'files/camelids.xml';
my $xs1 = XML::Simple->new();
my $doc = $xs1->XMLin($file);
foreach my $key (keys (%{$doc->{species}})){
print $doc->{species}->{$key}->{'common-name'} . ' (' . $key . ') ';
print $doc->{species}->{$key}->{conservation}->final . "\n";
}
use XML::Simple;
require "files/camelid_links.pl";
my %camelid_links = get_camelid_data();
my $xsimple = XML::Simple->new();
print $xsimple->XMLout(\%camelid_links,
noattr => 1,
xmldecl => '');
这数据到文档的任务的条件要求暴露了XML::Simple的一个弱点:它没有允许我们决定hash里的哪个key应该作为元素返回和哪个key该作为属性返回。上面例子的输出虽然接近我们的输出要求但还远远不够。对于那些更喜欢将XML文档内容直接作为Perl数据结构操作,而且需要在输出方面做更细微控制的案例,XML::Simple和XML::Writer配合得很好。
如下例子说明了如何使用XML::Write来符合我们的输出要求。
use XML::Writer;
require "files/camelid_links.pl";
my %camelid_links = get_camelid_data();
my $writer = XML::Writer->new();
$writer->xmlDecl();
$writer->startTag('html');
$writer->startTag('body');
foreach my $item ( keys (%camelid_links) ) {
$writer->startTag('a', 'href' => $camelid_links{$item}->{url});
$writer->characters($camelid_links{$item}->{description});
$writer->endTag('a');
}
$writer->endTag('body');
$writer->endTag('html');
$writer->end();
use XML::Parser;
use XML::SimpleObject;
my $file = 'files/camelids.xml';
my $parser = XML::Parser->new(ErrorContext => 2, Style => "Tree");
my $xso = XML::SimpleObject->new( $parser->parsefile($file) );
foreach my $species ($xso->child('camelids')->children('species')) {
print $species->child('common-name')->{VALUE};
print ' (' . $species->attribute('name') . ') ';
print $species->child('conservation')->attribute('status');
print "\n";
}
use XML::TreeBuilder;
my $file = 'files/camelids.xml';
my $tree = XML::TreeBuilder->new();
$tree->parse_file($file);
foreach my $species ($tree->find_by_tag_name('species')){
print $species->find_by_tag_name('common-name')->as_text;
print ' (' . $species->attr_get_i('name') . ') ';
print $species->find_by_tag_name('conservation')->attr_get_i('status');
print "\n";
}
use XML::Element;
require "files/camelid_links.pl";
my %camelid_links = get_camelid_data();
my $root = XML::Element->new('html');
my $body = XML::Element->new('body');
my $xml_pi = XML::Element->new('~pi', text => 'xml version="1.0"');
$root->push_content($body);
foreach my $item ( keys (%camelid_links) ) {
my $link = XML::Element->new('a', 'href' => $camelid_links{$item}->{url});
$link->push_content($camelid_links{$item}->{description});
$body->push_content($link);
}
print $xml_pi->as_XML;
print $root->as_XML();
use XML::Twig;
my $file = 'files/camelids.xml';
my $twig = XML::Twig->new();
$twig->parsefile($file);
my $root = $twig->root;
foreach my $species ($root->children('species')){
print $species->first_child_text('common-name');
print ' (' . $species->att('name') . ') ';
print $species->first_child('conservation')->att('status');
print "\n";
}
use XML::Twig;
require "files/camelid_links.pl";
my %camelid_links = get_camelid_data();
my $root = XML::Twig::Elt->new('html');
my $body = XML::Twig::Elt->new('body');
$body->paste($root);
foreach my $item ( keys (%camelid_links) ) {
my $link = XML::Twig::Elt->new('a');
$link->set_att('href', $camelid_links{$item}->{url});
$link->set_text($camelid_links{$item}->{description});
$link->paste('last_child', $body);
}
print qq|<?xml version="1.0"?>|;
$root->print;
这些例子举例说明了这些普通XML Perl模块的基本使用方法。我的目标是提供足够多的例子让你感受怎么用每个模块写代码。下个月我们将关注“实现某一标准XML API的模块”,特别说明的,XML::DOM, XML::XPath 和其他大量的 SAX 和类SAX模块。
|
|||
| · C++是垃圾语言?! · 邮件服务器专题 · Exchange Server专题 · 软件插件 · Serv-U基础应用专题 · 负载均衡技术基础专题 · CRM项目实施指导 · ERP系统应用实施指导 |
· Windows服务器全面加固 · Windows发展史 · Cisco IOS · Windows注册表应用指南 · FreeBSD使用教程 · Windows活动目录服务应.. · Windows系统使用技巧 · Zope应用开发指南 |
||
|
|||
| · Java基础教程 · VPN技术 · SQL Server 2005全解 · ARP攻击防范与解决方案 · SOA 面向服务架构 · SQL Server 2005全解 · Java编程开发手册 · 三层交换技术专题 |
· SQL Server入门到精通 · Windows Server 2003企.. · Windows远程桌面应用 · C#技术开发指南 · VPN技术 · Solaris 10 配置管理 · C#技术开发指南 · Windows操作系统安装 |
||
|
|||
| · VPN技术 · ARP攻击防范与解决方案 · SQL Server 2005全解 · Java基础教程 · SQL Server入门到精通 · SQL Server 2005全解 · SOA 面向服务架构 · Java编程开发手册 |
· C#技术开发指南 · 三层交换技术专题 · C#技术开发指南 · Windows远程桌面应用 · Windows Server 2003企.. · 邮件服务器专题 · wimax技术与趋势 · Windows操作系统安装 |
||
| ·DB2 Viper快速入门 ·DB2 9数据库的镜像分割与.. |
·将XML应用程序从DB2 8.x.. ·DB2 9中的pureXML:如何.. |
| ·服务器中的“傻瓜机”在.. ·盖茨也喜欢登录Youtube看.. |
· · |
| ·将职业教育职业化 - 各IT.. ·思科交换机上实现MAC地址.. |
·关于51CTO合作出书中的职.. ·OSPF动态路由协议入门简介 |
| ·9月第3周回顾:微软和英.. ·9月第2周回顾:四核之战.. |
·9月第1周回顾:微软国际.. ·什么样的文章更容易被编.. |
| · NGN:下一代网络 · 网络访问中断大排查 · FTTx光纤接入 |
· 平凡黑客讲述精彩人生(.. · 平凡黑客讲述精彩人生(.. · 平凡黑客讲述精彩人生(.. |
| · C++是垃圾语言?! · 2007年IT界七大抄袭事件 · Java实用开发全集 |
· 解析Ajax开发框架 走进A.. · 基于Google Maps与Ajax.. · 基于Google Maps与Ajax.. |
| · Ubuntu 中文开源频道 · Solaris基础知识入门 · 微软正式发布英文版Wind.. |
· 服务器基础知识入门 · Rambus第二?看全缓冲内.. · 服务器节能对比测试:AM.. |
| · 甲骨文Oracle 11g正式发.. · Oracle数据库开发之PL/S.. · Oracle数据库开发基础教.. |
· 存储2006,一个并购的大.. · IDC宣布浪潮蝉联存储市.. · 双机热备技术 |