-1

Perl / XML::Simpleを使用してXML応答のネストされたデータにアクセスする際に問題が発生しました。印刷されたXML応答の抜粋は次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:SelectCmDeviceResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://schemas.cisco.com/ast/soap/">
<SelectCmDeviceResult xsi:type="ns1:SelectCmDeviceResult">
<TotalDevicesFound xsi:type="xsd:unsignedInt">3</TotalDevicesFound>
<CmNodes soapenc:arrayType="ns1:CmNode[3]" xsi:type="soapenc:Array" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<item xsi:type="ns1:CmNode">
<ReturnCode xsi:type="ns1:RisReturnCode">NotFound</ReturnCode>
<Name xsi:type="xsd:string">10.186.78.4</Name>
<NoChange xsi:type="xsd:boolean">false</NoChange>
<CmDevices soapenc:arrayType="ns1:CmDevice[0]" xsi:type="soapenc:Array"/>
</item>
<item xsi:type="ns1:CmNode">
<ReturnCode xsi:type="ns1:RisReturnCode">Ok</ReturnCode>
<Name xsi:type="xsd:string">10.186.78.68</Name>
<NoChange xsi:type="xsd:boolean">false</NoChange>
<CmDevices soapenc:arrayType="ns1:CmDevice[2]" xsi:type="soapenc:Array">
<item xsi:type="ns1:CmDevice">
<Name xsi:type="xsd:string">SEPD0574CF73FC0</Name>
<IpAddress xsi:type="xsd:string">10.186.79.41</IpAddress>
<DirNumber xsi:type="xsd:string">51251001-Registered,51251004-Registered,51251002-Registered</DirNumber>
<Class xsi:type="ns1:DeviceClass">Phone</Class>
<Model xsi:type="xsd:unsignedInt">404</Model>
<Product xsi:type="xsd:unsignedInt">303</Product>
<BoxProduct xsi:type="xsd:unsignedInt">0</BoxProduct>

応答を解析し、返されたデバイスのIpAddress値を返すコードは次のとおりです。

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use XML::Simple;
use LWP;
use SOAP::Lite;

my $cucmip = "10.1.10.1";
my $axl_port = "8443";
my $user = "admin";
my $password = "password";
my $axltoolkit = "http://schemas.cisco.com/ast/soap/action/#RisPort#SelectCmDevice";

sub getDevIp {
    my $message = "<?xml POST message>

    my $url="https://$cucmip:$axl_port/realtimeservice/services/RisPort?wsdl";
    my $ua = LWP::UserAgent->new;
    my $header = new HTTP::Headers (
    'Content-Type' => 'application/xml; charset=utf-8',
    'SOAPAction' => 'http://schemas.cisco.com/ast/soap/action/#RisPort#SelectCmDevice',
    );
    my $req = HTTP::Request->new(POST => $url, $header, $message);
    $req->authorization_basic($user,$password);
    my $response = $ua->request($req);
    my $xs = new XML::Simple(KeyAttr=>[]);
    my $data = $xs->XMLin($response->content);
    print $data->{'soapenv:Body'}->{'ns1:SelectCmDeviceResponse'}->{'SelectCmDeviceResult'}->{'CmNodes'}->{'item'}->[0]->{'CmDevices'}->{'item'}->[0]->{'IpAddress'}->{'content'};
}

getDevIp();
4

2 に答える 2

3

これは基本的にあなたが持っているものです。

$VAR1 = {
    'soapenv:Body' => {
        'ns1:SelectCmDeviceResponse' => {
            'SelectCmDeviceResult' => {
                'CmNodes' => {
                    'item' => [
                        {
                            'xsi:type'  => 'ns1:CmNode',
                            'CmDevices' => {
                                'soapenc:arrayType' => 'ns1:CmDevice[0]',
                                'xsi:type'          => 'soapenc:Array'
                            },
                        },
                    ],
                    # plus some more items with DIFFERENT structure
                },
            },
        },
    },
};

でアクセスしようとしています

$data->{'soapenv:Body'}
    ->{'ns1:SelectCmDeviceResponse'}
        ->{'SelectCmDeviceResult'}
            ->{'CmNodes'}
                ->{'item'}->[0]                # you probably want ->[1] here! (wild guess)
                    ->{'CmDevices'}
                        ->{'item'}->[0]        # this data does not exist
                            ->{'IpAddress'}    # and this does not exist
                                ->{'content'}; # and this

存在しない値は、最初のアクセス時にperlによって作成され(これは自動生存と呼ばれます)、初期化されますundef

それがあなたの警告の理由です。

于 2012-05-07T16:46:18.077 に答える
1

SOAP::Deserializerを試すことができます。解析しているXMLドキュメントにアクセスできないため、試すことができません。SOAP::SOMオブジェクトを返します。

valueof(node)

    $res = $som->valueof('[1]');

オブジェクトがmatchメソッドを使用して内部的にパスと一致した場合SOAP::SOM、このメソッドを使用すると、一致したノード内のデータを取得できます。データは、クラスインスタンスではなく、ネイティブPerlデータとして返されます(dataofを参照)。スカラーコンテキストでは、このメソッドは一致したノードセットから最初の要素のみを返します。で配列リストコンテキストでは、すべての要素が返されます。以前の呼び出しが一致する以前の呼び出しの後に発生すると仮定すると、これはメソッド応答タグの最初の子要素であるため、$somに含まれるメソッド応答から結果エンティティを取得します。

于 2012-05-02T16:40:26.840 に答える