使用Perl XMLSimple解析XML文件

时间:2013-04-23 12:28:34

标签: xml perl hash xml-simple

我正在尝试使用以下结构解析 XML 类文件:

编辑: 我试图省略大部分巨大的xml文件,以简化c / p-ed错误的一切。这是实际存在此问题的完整文件(900kb!):https://docs.google.com/file/d/0B3ustNI1qZh1UURrYWZJQk0wVlU/edit?usp=sharing

<CIM CIMVERSION="2.0" DTDVERSION="2.0">

  <DECLARATION>
    <DECLGROUP>
      <LOCALNAMESPACEPATH>
        <NAMESPACE NAME="signalingsystem"/>
      </LOCALNAMESPACEPATH>

      <VALUE.OBJECT>
        <INSTANCE CLASSNAME="SharedGtTranslator">
          <PROPERTY NAME="Name" TYPE="string">
            <VALUE>AUC$4,1,6,4,26202*-->AUC RemoteSPC: 300 SSN: 10</VALUE>
          </PROPERTY>
          <PROPERTY NAME="NatureOfAddress" TYPE="sint32">
            <VALUE>4</VALUE>
          </PROPERTY>
        </INSTANCE>
      </VALUE.OBJECT>

      <VALUE.OBJECT>
        <INSTANCE CLASSNAME="SharedGtTranslator">
          <PROPERTY NAME="Name" TYPE="string">
            <VALUE>AUC$4,2,6,4,26202*-->AUC AUC LocalSPC: 410 SSN: 10</VALUE>
          </PROPERTY>
          <PROPERTY NAME="NatureOfAddress" TYPE="sint32">
            <VALUE>4</VALUE>
          </PROPERTY>
            <VALUE>2</VALUE>
          </PROPERTY>
        </INSTANCE>
      </VALUE.OBJECT>
    </DECLGROUP>

  </DECLARATION>
</CIM>

我正在使用XMLSimple来解析该结构。 如果NAME="Name",我需要获取PROPERTY CLASSNAME="SharedGtTranslator"的所有值。

这就是我要做的事情:

#!/usr/bin/perl
use strict;
use warnings;
# use module
use XML::Simple;
use Data::Dumper;

my $file1 = $ARGV[0];
# create object
my $xml = new XML::Simple;

# read XML file
my $data = $xml->XMLin($file1);
foreach my $object (@{$data->{DECLARATION}->{DECLGROUP}->{'VALUE.OBJECT'}}) {
        if ($object->{INSTANCE}->{CLASSNAME} eq 'SharedGtTranslator') {
                foreach my $property (@{$object->{INSTANCE}->{PROPERTY}}) {
                        if ($property->{NAME} eq 'Name') {
                                print $property->{VALUE} . "\n";
                        }
                }

        }
}

获取

  

“不推荐使用伪哈希”

没有任何反应。

非常感谢帮助!

2 个答案:

答案 0 :(得分:1)

您的代码可以正常使用。这是完整的计划吗?该代码中没有使用伪哈希值。

我能看到的唯一问题是你的XML数据格式不正确。有一个虚假的

  <VALUE>2</VALUE>
</PROPERTY>

在最后一个INSTANCE元素的末尾。修复后,程序运行正常。

XML::Simple似乎对你有用,所以坚持下去可能是合适的。但我一般不建议人们使用这个模块。它可能远非简单易用,它构建的结​​构并不能完全反映XML数据,所以类似于 XML::Twig 要么 XML::LibXML 往往好多了。


<强>更新

使用您的真实数据时,XML::Simple生成的结构看起来与为简短示例生成的结构完全不同。有些阵列与之前没有的哈希混合在一起。

这个程序似乎产生了你需要的东西。它产生170行输出。

use strict;
use warnings;

use XML::Simple;

my $file1 = 'active_7v19.om.cim';

my $xml  = new XML::Simple;
my $data = $xml->XMLin($file1);

for my $declgroup (@{ $data->{DECLARATION}{DECLGROUP} }) {

    foreach my $object (@{ $declgroup->{'VALUE.OBJECT'} }) {

        my $instance   = $object->{INSTANCE};
        my $classname  = $instance->{CLASSNAME};
        my $properties = $instance->{PROPERTY};

        next unless $classname eq 'SharedGtTranslator';

        for my $property (@$properties) {

            my $name  = $property->{NAME};
            my $value = $property->{VALUE};

            print $value, "\n" if $name eq 'Name';
        }
    }
}

但是,我现在更确定你会更好地使用“真正的”XML库。这段代码使用XML::LibXML来生成相同的输出。

use strict;
use warnings;

use XML::LibXML;

my $doc = XML::LibXML->load_xml(location => $file1, no_blanks => 1);

my @properties = $doc->findnodes('//INSTANCE[@CLASSNAME = "SharedGtTranslator"]/PROPERTY[@NAME = "Name"]');

for my $property (@properties) {
    print $property->textContent('VALUE'), "\n";
}

所有工作都由XPath表达式完成,该表达式选择PROPERTY属性为NAME的所有Name元素,这些元素是INSTANCE元素的子元素。 CLASSNAME属性为SharedGtTranslator的文档。随后的for循环打印每个VALUEPROPERTY元素的值。它显然更简洁,运行速度更快,如果需要提取不同的信息,则更灵活。

答案 1 :(得分:0)

您的XML格式不正确。我得到解析错误。你最后一个属性,你关闭,但不打开(或者因此而命名)。之后,在Perl 5.16中,它会打印:

AUC$4,1,6,4,26202*-->AUC RemoteSPC: 300 SSN: 10
AUC$4,2,6,4,26202*-->AUC AUC LocalSPC: 410 SSN: 10

当然这是使用XML :: Simple 2.20。