在perl中将xml转换为hash @ desired depth

时间:2013-09-12 21:23:12

标签: xml perl xpath

我试图在给定查询元素名称的情况下获得所需节点的哈希{key,value}对。

以下perl代码尝试获取可以按如下方式打印的输出:

p $error_hash->{'errorCode'}
0
p $error_hash->{'errorMsg'}
"get device list successfully"

感谢您帮助修复缺失的逻辑。

此处给出的代码仅打印“值”。即使我使用$xml_hash,我也必须在获得所需的哈希之前手动修剪前三个节点。

谢谢, 求那。

#!/usr/bin/env perl
use strict;
use warnings;
use XML::LibXML;
use XML::Hash;

my $xml = do {local $/;  < DATA > };
my $parser = XML::LibXML->new();
my $doc    = $parser->parse_string($xml);

my $xpath="//getDeviceResponse";

my $xml_converter = XML::Hash->new();
my $xml_hash = $xml_converter->fromXMLStringtoHash($xml);

my (%errmsg) = "";
my (%devinfo) = "";

sub get_value {
    my $elem = $_[0];

    my $query="$xpath";
    foreach my $errorMsg ($doc->findnodes($query)) {
        my ($title) = $errorMsg->findnodes($elem);
        print $title->to_literal;
    }
}

get_value "errorMsg";    
get_value "deviceInfo";

__DATA__
<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:ns1="http://jaxb.dev.java.net/array"
        xmlns:ns3="http://r200806.ws.abc.com/">
        <SOAP-ENV:Body>
                <getDeviceResponse>
                        <errorMsg>
                                <errorCode>0</errorCode>
                                <errorMsg>get device list successfully&#xA;</errorMsg>
                        </errorMsg>
                        <deviceInfo>
                                <devId>139</devId>
                                <firmware>abc</firmware>
                                <firmwareVersion>5.0</firmwareVersion>
                                <buildNum>208</buildNum>
                                <description></description>
                                <hostname>puppet</hostname>
                                <platform>puppetlabs</platform>
                                <sn>abc1234</sn>
                                <ip>172.168.210.2</ip>
                        </deviceInfo>
                </getDeviceResponse>
        </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

2 个答案:

答案 0 :(得分:0)

这些行在我的系统上产生警告:

my (%errmsg) = "";
my (%devinfo) = "";

你似乎比xpath更习惯于散列,所以我会举一个使用它们的例子:

my $getDeviceResponse_hash = $xml_hash->{'SOAP-ENV:Envelope'}{'SOAP-ENV:Body'}{'getDeviceResponse'};
my $errorMsg_hash = $getDeviceResponse_hash->{'errorMsg'};
print $errorMsg_hash->{'errorMsg'}{'text'};
print $errorMsg_hash->{'errorCode'}{'text'};

您可以随时检查这些哈希的结构:

use Data::Dumper;
...
print Dumper($errorMsg_hash);

答案 1 :(得分:0)

我建议XML::Twig

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

use XML::Twig;

my $twig = XML::Twig -> parse ( \*DATA ); 
my %hash = map { $_ -> tag => $_ -> trimmed_text } $twig -> findnodes ( '//getDeviceResponse/errorMsg', 0) -> children;
print Dumper \%hash;

__DATA__
<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:ns1="http://jaxb.dev.java.net/array"
        xmlns:ns3="http://r200806.ws.abc.com/">
        <SOAP-ENV:Body>
                <getDeviceResponse>
                        <errorMsg>
                                <errorCode>0</errorCode>
                                <errorMsg>get device list successfully&#xA;</errorMsg>
                        </errorMsg>
                        <deviceInfo>
                                <devId>139</devId>
                                <firmware>abc</firmware>
                                <firmwareVersion>5.0</firmwareVersion>
                                <buildNum>208</buildNum>
                                <description></description>
                                <hostname>puppet</hostname>
                                <platform>puppetlabs</platform>
                                <sn>abc1234</sn>
                                <ip>172.168.210.2</ip>
                        </deviceInfo>
                </getDeviceResponse>
        </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

输出:

$VAR1 = {
          'errorMsg' => 'get device list successfully',
          'errorCode' => '0'
        };

所以你可以:

print $hash{$errorMsg},"\n";

注意 - 这只会获取文件中第一个(唯一的)'errorMsg'实例。您可以轻松地执行多个操作,但是您需要稍微更改数据结构,因为它们的键会发生冲突。