Apr
13
上周讲解过perl的XML::Twig模块,描述了如何读取XML文件后,使用TwigHandlers方法来对指定的标签进行过滤和修改处理,最后输出整个或部分的XML内容。其实,TwigHandlers仅是处理节点的其中一种方法,如果你希望从XML中提取数据后,可以自定义输出格式;或输出一个新的XML格式内容,XML::Twig模块也能很好的帮助您。
一、示例一
这是官方说明中的其中一个示例,能很少的说明用法:
输出结果:
从这个示例中,我们可以发现几点:
二、说明
在给出第二个示例前,我想先XML::Twig和XML::Twig::Elt模块进行一些必要的说明:
三、示例二
代码:
输出结果:
这里使用了两种方式来输出XML的内容。
当然,获取数据的方式是多样的,你可以由数据库、网页等地方捕获数据后,格式化为XML格式输出。
※ 上面的例子输出的是XML::Twig::Elt,也可以用输出XML::Twig
※ 上面的例子仅输出了XML文档item节点下面一部分子节点,若希望全部输出,上面的代码明显是相当麻烦的。
我们可以使用copy来简化:
使用copy方法,先从另一棵树上拷贝一个分支,然后粘贴到新的树上,接着在这颗新树上对这个分支进行修改:
代码下载:
四、其他
XML::Twig可以理解为一个独立的接口来对XML文档进行解析的模块。除此以外,还有一些访问XML文档的API标准,例如:XML::DOM、XML::XPath和大量的SAX和类SAX模块。
下面是一些实际的例子,供参考:
一、示例一
这是官方说明中的其中一个示例,能很少的说明用法:
#!/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
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>
<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方法返回包含某个节点下的所有子节点的数组,对其遍历即可对每个节点进行修改。
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、对于不同的树架构,不能直接把其中一棵树上分支节点粘贴(映射)到另一个树的分支上,但可以拷贝。
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');
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>
[转]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;
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;
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模块。
下面是一些实际的例子,供参考:
下载文件