Apr 13

[原]再谈XML::Twig模块 晴

linuxing , 17:49 , 编程 » Perl , 评论(0) , 引用(0) , 阅读(20184) , Via 本站原创 | |
    上周讲解过perl的XML::Twig模块,描述了如何读取XML文件后,使用TwigHandlers方法来对指定的标签进行过滤和修改处理,最后输出整个或部分的XML内容。其实,TwigHandlers仅是处理节点的其中一种方法,如果你希望从XML中提取数据后,可以自定义输出格式;或输出一个新的XML格式内容,XML::Twig模块也能很好的帮助您。

一、示例一
这是官方说明中的其中一个示例,能很少的说明用法:

#!/bin/perl -w
use XML::Twig;

my $t= XML::Twig->new();
  $t->parse( '<d><title>title</title><para>p 1</para><para>p 2</para></d>');
  my $root= $t->root;
  $root->set_tag( 'html');              # change doc to html
  $title= $root->first_child( 'title'); # get the title
  $title->set_tag( 'h1');               # turn it into h1
  my @para= $root->children( 'para');   # get the para children
  foreach my $para (@para)
    { $para->set_tag( 'p'); }           # turn them into p
  $t->print;                            # output the document

输出结果:
引用
$ perl printCustom.pl
<html><h1>title</h1><p>p 1</p><p>p 2</p></html>

从这个示例中,我们可以发现几点:
引用
1、创建一个新的XML::Twig实例后,可以通过parse给其粘贴进HTML或XML内容;
2、通过->root方法,可以指向目录树的根;
3、通过$title= $root->first_child( 'title'); 得到的$title是一个原目录节点的映射变量,也就是说,对$title的修改,会直接影响原目录树的内容(修改tag为h1);
同样的,children方法类似,而children_copy方法、copy方法则可以返回一个拷贝。
4、children方法返回包含某个节点下的所有子节点的数组,对其遍历即可对每个节点进行修改。

二、说明
在给出第二个示例前,我想先XML::Twig和XML::Twig::Elt模块进行一些必要的说明:
引用
1、对于XML::Twig,按树结构对XML文档进行解析,使用XPath架构来描述某个节点的位置;
2、XML::Twig::Elt模块用于创建新的元素节点,然后即可在该元素节点上添加属性节点和文本节点,最后通过paste方法粘贴到某个元素节点的位置上,输出父节点即会同时输出该新节点的内容;如果新创建的元素节点没有粘贴到某个位置,其仅是“浮动”节点而已;
3、对于不同的树架构,不能直接把其中一棵树上分支节点粘贴(映射)到另一个树的分支上,但可以拷贝。

三、示例二
代码:

#!/bin/perl -w
use XML::Twig;
use encoding "utf-8";

my $file = "./feed.xml";
my $twig = XML::Twig->new();
$twig->parsefile($file);
# 定义一个树目录的根变量
my $root = $twig->root;

# 使用XPath架构来描述某个节点的位置,item节点在channel节点下面
# 通过循环来遍历item下面的所有子节点
foreach my $item ($root->first_child('channel')->children('item')) {
  print $item->first_child_text('title');
  print "(".$item->first_child_text('link').")\n";
  print $item->first_child_text('author')."\n";
  print $item->first_child_text('pubDate')."\n";
#  print $item->first_child_text('description')."\n";
}
print "=========================================\n";

print qq|<?xml version="1.0" encoding="UTF-8" ?>|;
print "\n";
my $myitem = XML::Twig::Elt->new('html');
my $mybody = XML::Twig::Elt->new('body');
# 把两个节点连接起来
$mybody->paste($myitem);

foreach my $item ($root->first_child('channel')->children('item')) {
  # 创建一个新节点后,把从另一个树节点的内容通过新的节点插入目录树中
  my $mytitle = XML::Twig::Elt->new('title');
  # 创建文本节点
  $mytitle->set_text($item->first_child_text('title'));
  $mytitle->paste($myitem);
  my $mylink = XML::Twig::Elt->new('a');
  # 创建属性节点
  $mylink->set_att('href',$item->first_child_text('link'));
  $mylink->paste('first_child',$mytitle);
}
# 使用更容易查看的方式输出XML内容
$myitem->print('indented');

输出结果:
引用
$ perl printAndWrite.pl
[转]heartbeat CRM管理程序功能示例(http://www.linuxfly.org/post/365/)
linuxing <emos#linuxfly.org>
Thu, 09 Apr 2009 03:54:50 +0000
[原]heartbeat 2.x简单配置[2](http://www.linuxfly.org/post/364/)
linuxing <emos#linuxfly.org>
Wed, 08 Apr 2009 02:27:50 +0000
[原]heartbeat 2.x简单配置[1](http://www.linuxfly.org/post/363/)
linuxing <emos#linuxfly.org>
Tue, 07 Apr 2009 08:00:52 +0000
[原]heartbeat 2.x基础概念(http://www.linuxfly.org/post/362/)
linuxing <emos#linuxfly.org>
Mon, 06 Apr 2009 06:45:56 +0000
[转]关于脑中风急救--放血救命法(http://www.linuxfly.org/post/361/)
linuxing <emos#linuxfly.org>
Sun, 05 Apr 2009 02:51:05 +0000
清明节的起源和习俗(http://www.linuxfly.org/post/360/)
linuxing <emos#linuxfly.org>
Sat, 04 Apr 2009 01:41:55 +0000
[原]关闭Apache的目录浏览功能(http://www.linuxfly.org/post/354/)
linuxing <emos#linuxfly.org>
Mon, 30 Mar 2009 05:05:35 +0000
[转]用好sudo(http://www.linuxfly.org/post/353/)
linuxing <emos#linuxfly.org>
Sun, 29 Mar 2009 02:36:03 +0000
[原]发布ExtMail 1.0.8/ Extman 1.0.0安装及升级rpm (http://www.linuxfly.org/post/352/)
linuxing <emos#linuxfly.org>
Sat, 28 Mar 2009 08:12:55 +0000
[原]流量监控脚本 v1.3(http://www.linuxfly.org/post/347/)
linuxing <emos#linuxfly.org>
Mon, 23 Mar 2009 07:54:24 +0000
=========================================
<?xml version="1.0" encoding="UTF-8" ?>
<html>
  <title><a href="http://www.linuxfly.org/post/347/"/>[原]流量监控脚本 v1.3</title>
  <title><a href="http://www.linuxfly.org/post/352/"/>[原]发布ExtMail 1.0.8/ Extman 1.0.0安装及升级rpm </title>
  <title><a href="http://www.linuxfly.org/post/353/"/>[转]用好sudo</title>
  <title><a href="http://www.linuxfly.org/post/354/"/>[原]关闭Apache的目录浏览功能</title>
  <title><a href="http://www.linuxfly.org/post/360/"/>清明节的起源和习俗</title>
  <title><a href="http://www.linuxfly.org/post/361/"/>[转]关于脑中风急救--放血救命法</title>
  <title><a href="http://www.linuxfly.org/post/362/"/>[原]heartbeat 2.x基础概念</title>
  <title><a href="http://www.linuxfly.org/post/363/"/>[原]heartbeat 2.x简单配置[1]</title>
  <title><a href="http://www.linuxfly.org/post/364/"/>[原]heartbeat 2.x简单配置[2]</title>
  <title><a href="http://www.linuxfly.org/post/365/"/>[转]heartbeat CRM管理程序功能示例</title>
  <body/>
</html>

这里使用了两种方式来输出XML的内容。
当然,获取数据的方式是多样的,你可以由数据库、网页等地方捕获数据后,格式化为XML格式输出。

※ 上面的例子输出的是XML::Twig::Elt,也可以用输出XML::Twig

# 使用XML:Twig来输出
my $mytwig = XML::Twig->new(pretty_print => 'indented');
#  使用sprint方法输出到一个变量
$html=$myitem->sprint;
$mytwig->parse($html);
$mytwig->print;

※ 上面的例子仅输出了XML文档item节点下面一部分子节点,若希望全部输出,上面的代码明显是相当麻烦的。
我们可以使用copy来简化:
使用copy方法,先从另一棵树上拷贝一个分支,然后粘贴到新的树上,接着在这颗新树上对这个分支进行修改:

# 从另一棵树上拷贝分支,然后粘贴到新树上
foreach my $item ($root->first_child('channel')->children('item')) {
  my $copyitem = $item->copy;
  $copyitem->paste($mybody);
}

# 在新树上对分支进行修改
foreach my $item ($mybody->children('item')) {
  my $mytitle = $item->first_child('title');
  my $mylink = XML::Twig::Elt->new('a');
  $mylink->set_att('href',$item->first_child_text('link'));
  $mylink->paste('first_child',$mytitle);
}

# 使用XML:Twig来输出
my $mytwig = XML::Twig->new(pretty_print => 'indented',remove_cdata => 'true');
$html=$myitem->sprint;
$mytwig->parse($html);
$mytwig->print;


代码下载:
四、其他
XML::Twig可以理解为一个独立的接口来对XML文档进行解析的模块。除此以外,还有一些访问XML文档的API标准,例如:XML::DOM、XML::XPath和大量的SAX和类SAX模块。
下面是一些实际的例子,供参考:
Tags: ,
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]