忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT HPC论坛 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
12下一页
最近访问板块 发新帖
查看: 6827 | 回复: 18

优化有酬劳,如何读取XML同名标签个数不确定里的内容? [复制链接]

论坛徽章:
0
发表于 2013-09-27 21:09 |显示全部楼层
我是一个初学者,还有很多不懂的地方,请赐教。
现在,我读取的方法是先判断同名标签的个数,判断后分为两种情况:一个或多个,多个的再给循环顺序分别读取内容,如果有二级标签,又要判断标签的个数,判断后再分为两种情况:一个或多个,如此往复。如果有两级标签,就要写四次代码,如果三级标签,就要有写八次代码,也就是2的n次方,太冗余了,请高手指教,想话费酬劳!例子如下:
这个XML里有同级同名标签<device>出现两次,而在一个<device>里<host>出现三次,我就要判断<device>的个数,以及<host>的个数,要写四次代码,请优化!
<?xml version="1.0" encoding="GBK"?>
<function funcname="gray_list" mode="predefined" no="no">
  <task_name>20130506113902_989513309</task_name>
  <device>
    <device_name>202.197.12.199</device_name>
    <interface_name>gei-0/2</interface_name>
    <commited_information_rate>5000</commited_information_rate>
    <host>
      <ip>192.168.1.1</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.45.115</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.54.112</ip>
      <mask>255.255.255.0</mask>
    </host>
  </device>
  <device>
    <device_name>202.197.12.200</device_name>
    <interface_name>gei-0/1</interface_name>
    <commited_information_rate>10000</commited_information_rate>
    <host>
      <ip>172.168.2.1</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>172.168.2.15</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>172.168.5.12</ip>
      <mask>255.255.255.0</mask>
    </host>
  </device>  
</function>

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
发表于 2013-09-27 23:17 |显示全部楼层
本帖最后由 104359176 于 2013-09-27 23:21 编辑
  1. #!perl

  2. use 5.010;
  3. use XML::Simple qw(XMLin XMLout);
  4. use YAML qw(Dump);

  5. my @lines = <DATA>;
  6. my $text = join '', @lines;
  7. my $xml_data = XMLin($text);

  8. show_keys($xml_data);

  9. sub show_keys {
  10.         my ($data, $meta) = @_;
  11.         if (defined $meta) {
  12.                 $meta = "$meta -> ";
  13.         }
  14.         else {
  15.                 $meta = '';
  16.         }
  17.         # return if (ref($data) ne ref([]));
  18.         foreach my $key (keys $data) {
  19.                 my $value = $data->{$key};
  20.                 if (ref($value) eq ref([])) {
  21.                         my $values_amount = scalar @$value;
  22.                         say "Tag:<$meta $key> occur $values_amount times";
  23.                         foreach my $n (@$value) {
  24.                                 show_keys($n, $key);
  25.                         }
  26.                 }
  27.         }
  28. }

  29. __DATA__
  30. <function funcname="gray_list" mode="predefined" no="no">
  31.   <task_name>20130506113902_989513309</task_name>
  32.   <device>
  33.     <device_name>202.197.12.199</device_name>
  34.     <interface_name>gei-0/2</interface_name>
  35.     <commited_information_rate>5000</commited_information_rate>
  36.     <host>
  37.       <ip>192.168.1.1</ip>
  38.       <mask>255.255.255.0</mask>
  39.     </host>
  40.     <host>
  41.       <ip>192.168.45.115</ip>
  42.       <mask>255.255.255.0</mask>
  43.     </host>
  44.     <host>
  45.       <ip>192.168.54.112</ip>
  46.       <mask>255.255.255.0</mask>
  47.     </host>
  48.   </device>
  49.   <device>
  50.     <device_name>202.197.12.200</device_name>
  51.     <interface_name>gei-0/1</interface_name>
  52.     <commited_information_rate>10000</commited_information_rate>
  53.     <host>
  54.       <ip>172.168.2.1</ip>
  55.       <mask>255.255.255.0</mask>
  56.     </host>
  57.     <host>
  58.       <ip>172.168.2.15</ip>
  59.       <mask>255.255.255.0</mask>
  60.     </host>
  61.     <host>
  62.       <ip>172.168.5.12</ip>
  63.       <mask>255.255.255.0</mask>
  64.     </host>
  65.   </device>  
  66. </function>
复制代码
---------------------------------output------------------------------------
C:\WINDOWS\system32\cmd.exe /c perl Parse-xml.pl
Tag:< device> occur 2 times
Tag:<device ->  host> occur 3 times
Tag:<device ->  host> occur 3 times
Hit any key to close this window...

论坛徽章:
0
发表于 2013-09-28 00:27 |显示全部楼层
回复 2# 104359176


    首先感谢你的耐心指导,我可能还没有完全表达出我的意图,我想要的是取出键值,而不是统计出现几次,如:
情形一:
    <device>
    <device_name>202.197.12.199</device_name>
    <interface_name>gei-0/2</interface_name>
    <commited_information_rate>5000</commited_information_rate>
    <host>
      <ip>192.168.1.1</ip>
      <mask>255.255.255.0</mask>
    </host>   
  </device>
我想要的是202.197.12.199, gei-0/2, 5000, 192.168.1.1, 255.255.255.0

情形二:
<device>
    <device_name>202.197.12.199</device_name>
    <interface_name>gei-0/2</interface_name>
    <commited_information_rate>5000</commited_information_rate>
    <host>
      <ip>192.168.1.1</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.45.115</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.54.112</ip>
      <mask>255.255.255.0</mask>
    </host>
  </device>
我想要的是202.197.12.199, gei-0/2, 5000, 192.168.1.1, 255.255.255.0,192.168.45.115, 255.255.255.0,192.168.54.112, 255.255.255.0

情形三:
<device>
    <device_name>202.197.12.199</device_name>
    <interface_name>gei-0/2</interface_name>
    <commited_information_rate>5000</commited_information_rate>
    <host>
      <ip>192.168.1.1</ip>
      <mask>255.255.255.0</mask>
    </host>   
  </device><device>
    <device_name>202.197.12.200</device_name>
    <interface_name>gei-0/1</interface_name>
    <commited_information_rate>10000</commited_information_rate>
    <host>
      <ip>192.168.2.1</ip>
      <mask>255.255.255.0</mask>
    </host>  
  </device>
我想要的是202.197.12.199, gei-02, 5000, 192.168.1.1, 255.255.255.0,202.197.12.200, gei-0/1, 10000, 192.168.2.1, 255.255.255.0

情形四:
<device>
    <device_name>202.197.12.199</device_name>
    <interface_name>gei-0/2</interface_name>
    <commited_information_rate>5000</commited_information_rate>
    <host>
      <ip>192.168.1.1</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.45.115</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.54.112</ip>
      <mask>255.255.255.0</mask>
    </host>
  </device>
<device>
    <device_name>202.197.12.199</device_name>
    <interface_name>gei-0/1</interface_name>
    <commited_information_rate>10000</commited_information_rate>
    <host>
      <ip>192.168.2.1</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.25.115</ip>
      <mask>255.255.255.0</mask>
    </host>
    <host>
      <ip>192.168.24.112</ip>
      <mask>255.255.255.0</mask>
    </host>
  </device>
我想要的是202.197.12.199, gei-0/2, 5000, 192.168.1.1, 255.255.255.0,192.168.45.115, 255.255.255.0,192.168.54.112, 255.255.255.0
              202.197.12.199, gei-0/1, 10000, 192.168.2.1, 255.255.255.0,192.168.25.115, 255.255.255.0,192.168.24.112, 255.255.255.0


感谢再次指导,为盼!

论坛徽章:
0
发表于 2013-09-28 02:22 |显示全部楼层
这不就是读取XML文件内容么?话费how much?
楼上已经提供模块了,自己遍历读吧

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
发表于 2013-09-28 09:59 |显示全部楼层
本帖最后由 104359176 于 2013-09-28 10:02 编辑

回复 3# capfsxl

这个模块是将 XML 保存成数组的哈希,哈希的键值没有固定顺序,不能按照楼主的要求顺序输出结果。如果想按照文本出现的顺序来解析值,就要自己做一个解析器。

使用递归,和深度没有关系,就不用代码去按照深度写了。



   

论坛徽章:
0
发表于 2013-09-28 12:31 |显示全部楼层
把酬劳给二楼吧,修改一下就可用了!当然,给我也可以

论坛徽章:
0
发表于 2013-09-28 12:45 |显示全部楼层
回复 5# 104359176

理解与深度没关系,但我生成的XML文档中,不确定有几个同名标签,例如我再简化一下:

1.只有一个<device>标签时,从外部输入的值只能为1:
__DATA__
  <device>
    <device_name>192.168.1.1</device_name>
  </device>  

解:
#!/usr/bin/perl
use strict;
use XML::Simple qw(XMLin);
my $device_num = $ARGV[0];       #$device_num =1
my @lines = <DATA>;
my $text = join '', @lines;
my $xml_data = XMLin($text);
my $device_name = $xml_data->{device}->{device_name};

my $config = <<END;
system-view
ip router $device_name
undo shutdown
return
END

print $config;

输出结果为:
system-view
ip router 192.168.1.1
undo shutdown
return


2.有两个及以上<device>标签时,从外部会有一个输入值为第几个<device>,1或2或3或更多,但不能大于<device>标签个数:
__DATA__
  <device>
    <device_name>192.168.2.1</device_name>
  </device>  
  <device>
    <device_name>192.168.3.1</device_name>
  </device>  
  <device>
    <device_name>192.168.4.1</device_name>
  </device>

解:
#!/usr/bin/perl
use strict;
use XML::Simple qw(XMLin);
my $device_num = $ARGV[0];       #$device_num =1或2或3
my @lines = <DATA>;
my $text = join '', @lines;
my $xml_data = XMLin($text);
my $device_name = $xml_data->{device}[$device_num-1]->{device_name};

my $config = <<END;
system-view
ip router $device_name
undo shutdown
return
END

print $config;

当外部输入的$device_num =1时
输出结果为:
system-view
ip router 192.168.2.1
undo shutdown
return

当外部输入的$device_num =2时
输出结果为:
system-view
ip router 192.168.3.1
undo shutdown
return

当外部输入的$device_num =3时
输出结果为:
system-view
ip router 192.168.4.1
undo shutdown
return

3.当<device>标签不确定时,或一个,或多个,就是将1和2两种情况合并:
我目前做的就是要加一个判断语句。想优化此方案!!!

解:
#!/usr/bin/perl
use strict;
use XML::Simple qw(XMLin);
my $device_num = $ARGV[0];       #$device_num =1
my @lines = <DATA>;
my $text = join '', @lines;
my $xml_data = XMLin($text);
my $device_list  = $xml_data->{device};
my $device_times = ref ($device_list) eq ref ([]) ? scalar(@$device_list) : 1;
   if ($device_times == 1 ){

my $device_name = $device_list->{device_name};

my $config = <<END;
system-view
ip router $device_name
undo shutdown
return
END

print $config;

                                     }else
                                     {
my $device_name = $xml_data->{device}[$device_num-1]->{device_name};

my $config = <<END;
system-view
ip router $device_name
undo shutdown
return
END

print $config;
                                      }



我就想优化的是第三种情况,能不能不判断标签个数,上面第二种情况包括不了第一种情况,如果光用第二种表达式的话,且xml文档中只有一个标签时,会报错,说没有数组,如何解决???请高手赐教!!!









论坛徽章:
0
发表于 2013-09-28 13:01 |显示全部楼层
回复 6# iamlimeng

烦请高手看7楼的说明,盼解!
   

论坛徽章:
0
发表于 2013-09-28 13:01 |显示全部楼层
回复 4# onepublic


    烦请看7楼说明,盼解!

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
发表于 2013-09-28 13:07 |显示全部楼层
回复 9# capfsxl

标签一样部分的是以数组的形式保存在数据结构中的,不一样的是用普通的字符串保存。

如果遇到数组,就展开,如果不是数组,就按值来输出。做一个判断 ref()

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10张SACC2017门票等你来拿~

在数字化转型时代,云已成为万物智能的数字化大脑。而随着大数据应用、人工智能、移动互联网等技术的飞速发展,“智慧 +” 的概念正在深入到各行各业,提升企业效率,释放商业潜能,创造全新机遇。作为国内顶级技术盛会之一,2017 中国系统架构师大会(SACC2017)将于 10 月 19-21 日在北京新云南皇冠假日酒店震撼来袭。今年,大会以 “云智未来” 为主题,云集国内外顶级专家,围绕云计算、人工智能、大数据、移动互联网、产业应用等热点领域展开技术探讨与交流。本届大会共设置 2 大主会场,18 个技术专场;邀请来自互联网、金融、制造业、电商等多个领域,100 余位技术专家及行业领袖来分享他们的经验;并将吸引 4000 + 人次的系统运维、架构师及 IT 决策人士参会,为他们提供最具价值的交流平台。
----------------------------------------
优惠时间:2017年10月19日前

活动链接>>
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP