我正在尝试使用以下结构解析 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";
}
}
}
}
获取
“不推荐使用伪哈希”
没有任何反应。
非常感谢帮助!
答案 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
循环打印每个VALUE
中PROPERTY
元素的值。它显然更简洁,运行速度更快,如果需要提取不同的信息,则更灵活。
答案 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。