【问题标题】:converting xml to hash @ desired depth in perl在perl中将xml转换为哈希@期望的深度
【发布时间】:2016-04-21 22:54:40
【问题描述】:

在给定查询元素名称的情况下,我正在尝试获取所需节点的哈希 {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>

【问题讨论】:

    标签: xml perl xpath


    【解决方案1】:

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

    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);
    

    【讨论】:

    • 这两行编译。只有“哈希中的奇数个元素”警告。
    • @SlavenRezic 非常正确。我有点惊讶他们会跑,但那不是这里也不是那里。
    【解决方案2】:

    我会推荐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”的第一个(唯一)实例。你可以很容易地做多个,但你需要稍微改变你的数据结构,因为它们的键会发生冲突。

    【讨论】:

      猜你喜欢
      • 2021-07-13
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 2016-10-31
      • 2021-08-13
      相关资源
      最近更新 更多