免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: rexuekonglong
打印 上一主题 下一主题

求助:perl 处理xml内容 [复制链接]

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
11 [报告]
发表于 2014-02-19 13:01 |只看该作者
本帖最后由 pitonas 于 2014-02-19 06:05 编辑

rexuekonglon.xml 文件内容如下:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <list>
  3.    <entry>
  4.       <author>zhangsan</author>
  5.       <kind>add</kind>
  6.       <filename>[color=Yellow] log4j.java[/color]</filename>
  7.       <message>内容随意</message>
  8.       <path>[color=Yellow]C:\code\[/color]</path>
  9.    </entry>
  10.    <entry>
  11.       <author>zhangsan</author>
  12.       <kind>modified</kind>
  13.       <filename>[color=Orange]log.txt[/color]</filename>
  14.       <message>增加一个空格</message>
  15.       <path>[color=Yellow]C:\code\[/color]</path>
  16.    </entry>
  17.    <entry>
  18.       <author>zhangsan</author>
  19.       <kind>modified</kind>
  20.       <filename>[color=Yellow] log4j.java[/color]</filename>
  21.       <message>增加说明注释</message>
  22.       <path>[color=Yellow]C:\code\[/color]</path>
  23.    </entry>
  24. </list>
复制代码
  1. #!/usr/bin/perl
  2. open my $x, 'rexuekonglon.xml';
  3. my $xml = do { local $/; <$x> };
  4. my @xml = split /(?<=<\/entry>)/, $xml;
  5. my %first;
  6. for (@xml) {
  7.     print and next unless /entry>/;
  8.     my ( $filename, $path ) = /\]\s*(\S*?)\s*\[.*?\]\s*(\S*?)\s*\[/s;
  9.     print if !$first{ $path . $filename }++;
  10. }
复制代码
result 如下:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <list>
  3.    <entry>
  4.       <author>zhangsan</author>
  5.       <kind>add</kind>
  6.       <filename>[color=Yellow] log4j.java[/color]</filename>
  7.       <message>内容随意</message>
  8.       <path>[color=Yellow]C:\code\[/color]</path>
  9.    </entry>
  10.    <entry>
  11.       <author>zhangsan</author>
  12.       <kind>modified</kind>
  13.       <filename>[color=Orange]log.txt[/color]</filename>
  14.       <message>增加一个空格</message>
  15.       <path>[color=Yellow]C:\code\[/color]</path>
  16.    </entry>
  17. </list>
复制代码

论坛徽章:
0
12 [报告]
发表于 2014-02-19 16:05 |只看该作者
回复 11# pitonas

非常感谢,不过我尝试过上述代码后,xml文件被缩减只剩下第一段<entry>
见图:
  代码使用;

  结果展示;

真正的1.xml中有9段<entry> ,其中有7段是<filename><path>值是相同的;



多请教一步,最后
  1. print if !$first {$path . $filename}++;  
复制代码
结果是自动保存在了$x中吗?
如果我想把截取后的结果重新保存在2.xml中,然后用Dumper 解析输出,下面这样写行么?
  1. for (@xml){
  2.   .........
  3. if (!$first {$path . $filename}++)  
  4.    {
  5.       cat  $x > 2.xml;
  6.    }
  7. }
  8. my $y = new XML::Simple;
  9. my $data = $y->XMLin(2.xml);
  10. print Dumper($data);
复制代码

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
13 [报告]
发表于 2014-02-19 16:39 |只看该作者
非常感谢
如果你贴上你真实的文件内容{:2_172:}

论坛徽章:
0
14 [报告]
发表于 2014-02-19 16:55 |只看该作者
回复 13# pitonas
其实我真是xml文件内容,也就比我给的那个xml样例,少5个子节点而已。
12#的结果图片,就是第一段<entry>完整内容, 之所以选择<path><filename>这两个子节点作为匹配关键,就是因为,其他的都不足以确定显示的文件内容是否必要。

<path> </path> 的值中 中文、英文、斜线、都有, 如果是因为目前我的测试xml中<path>值存在乱码而导致<path>判断出错,那么我去换个全部都是纯英文的再试下。
<filename></filename>的值大多都是纯英文的
   

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
15 [报告]
发表于 2014-02-20 13:17 |只看该作者
{:2_172:}小伙伴们, 这个再试试
  1. #!/usr/bin/perl

  2. open my $x, 'rexuekonglon.xml';
  3. my $xml = do { local $/; <$x> };
  4. my @xml = split /(?<=<\/entry>)/, $xml;
  5. my %first;
  6. for (@xml) {
  7.     print and next unless /entry>/;
  8.     my %fh = /<(filename|path)>\s*(\S+)\s*</g;
  9.     print if !$first{ $fh{path} . $fh{filename} }++;
  10. }
复制代码

论坛徽章:
0
16 [报告]
发表于 2014-02-20 14:47 |只看该作者
回复 15# pitonas
尝试结果如下:
[error] Global symbol "%fh" requires explicit package name at  login.cgi line 44.
          Global symbol "$path" requires explicit package name at  login.cgi line 44
          Global symbol "$filename" requires explicit package name at  login.cgi line 44
   

论坛徽章:
0
17 [报告]
发表于 2014-02-20 15:11 |只看该作者
回复 15# pitonas
我又混合尝试了一下:
  1. for(@xml){
  2.     print ant next unless /entry>/;
  3.     my  ($filename,path) = /\s*/(S*+)\s*</g;
  4.     print if !$first{$path . $filename}++;
  5. }
复制代码
结果:
9个节点缩减到了2个,然后我重新确认了一下,原XML内<filename><path> 9个元素对的内容,
发现,<filename> 一共是4种,<path> 一共是7种,所以这样总结下来,结果xml内容应该显示7个<entry> 元素节点。
而我上面混杂模式得出了2个。


   

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
18 [报告]
发表于 2014-02-20 15:35 |只看该作者
{:2_172:} 小伙伴们, 贴上你的代码

rexuekonglong 发表于 2014-02-20 07:47
回复 15# pitonas
尝试结果如下:
[error] Global symbol "%fh" requires explicit package name at  lo ...

论坛徽章:
0
19 [报告]
发表于 2014-02-20 15:43 |只看该作者
回复 18# pitonas
  1. for(@xml){
  2.     print ant next unless /entry>/;
  3.     my  $fh =/<(filename|path)>\s*(\S*+)\s*<g ;
  4.     print if !$first{$fh{$path} . $fh{$filename}}++;
  5. }
复制代码
{:2_172:}  照抄的,经过验证,感觉好像
  1. my  $fh =/<(filename|path)>\s*(\S*+)\s*<g ;
复制代码
这句好像没有被系统接受。

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
20 [报告]
发表于 2014-02-20 15:44 |只看该作者
{:2_171:} %fh
  1.     my %fh = /<(filename|path)>\s*(\S+)\s*</g;
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP