使用XML :: Simple计算重复的XML属性值

时间:2016-01-19 13:38:44

标签: xml perl foreach

<Root>
  <Top Name=" ">
    <Tag name="ALU">
      <in name="PC"/>
      <iodirection name="AB"/>
    </Tag>
    <Tag name=" ">
      <in name="CCB"/>
      <ou name="PC"/>
      <bi name="AB"/>
    </Tag>
    <Tag name=" ">
      <in name="DB"/>
      <ou name="DI"/>
      <bi name="CCB"/>
    </Tag>
    <Tag name=" ">
      <in name="DI"/>
      <ou name="DB"/>
      <bi name="CCB"/>
    </Tag>
  </Top>
</Root>

我不是Perl专家,但是我很难弄清楚一些简单的事情,其中​​一个任务就是这样。上面的XML,您可以看到属性/元素,它们重复了几次,但适用于不同的<in><io><ou>标记。现在,我希望只返回重复的属性/元素,只打印一次。

Example : DI
          DB
          CCB
          AB

我的代码段就是这样的

use strict;

use XML::Simple;
use Data::Dumper;

$xml_1 = XMLin('./tmp.xml');

my $root_top = $xml_1->{Top};
my $mod_top  = $root_top1->{Tag};
my @mod      = keys %$mod_top;

foreach my $mods ( values %$mod_top ) {

    my $temp = shift(@mod);
    print XST_FILE "$temp u_$temp(\n";

    my $in_mo = $modules->{in};
    my @in_1  = keys %$in_mo;

    foreach my $name_1 ( values %$in_mo ) {

        my $inn = shift(@in_1);

        if ( $inn =~ /\bname\b/ ) {
            print " \.$name_1\($name_1\)\,\n";
        }
        else {
            print " \.$in\($in\)\,\n";
        }
    }

PS:如果只能在XML::Simple修改,我会很感激。虽然XML::Simple is discouraged,但他并不是正义的,但他是我目前用来完成这项任务的人

2 个答案:

答案 0 :(得分:4)

不要使用XML :: Simple。

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use XML::LibXML;
my $xml = 'XML::LibXML'->load_xml(location => shift);

my %names;
$names{ $_->value } = 1 for $xml->findnodes('//*[not(*)]/@name');  # Leaf nodes only.
say for keys %names;

答案 1 :(得分:2)

这是一个使用XML::LibXML来满足要求的程序。它使用单个XPath表达式来查找感兴趣的所有属性,并以散列%names计算它们。随后的for循环显示计数大于1的所有散列键

use strict;
use warnings 'all';

use XML::LibXML;

my $xml = XML::LibXML->load_xml(IO => \*DATA);

my %names;
++$names{ $_->getValue } for $xml->findnodes('//in/@name | //ou/@name | //bi/@name');

print "$_\n" for grep { $names{$_} > 1 } keys %names;

__DATA__
<Root>
  <Top Name=" ">
    <Tag name="ALU">
      <in name="PC"/>
      <iodirection name="AB"/>
    </Tag>
    <Tag name=" ">
      <in name="CCB"/>
      <ou name="PC"/>
      <bi name="AB"/>
    </Tag>
    <Tag name=" ">
      <in name="DB"/>
      <ou name="DI"/>
      <bi name="CCB"/>
    </Tag>
    <Tag name=" ">
      <in name="DI"/>
      <ou name="DB"/>
      <bi name="CCB"/>
    </Tag>
  </Top>
</Root>

输出

DB
PC
DI
CCB