【发布时间】:2012-05-12 04:06:36
【问题描述】:
我在使用 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();
【问题讨论】:
-
你真的希望任何人水平来回滚动来理解这一点吗?如果你的数据结构太复杂,不要使用
XML::Simple。 -
我确实滚动了一下,发现您在示例中尝试访问的数据不存在。访问(不存在的)键时,自动激活将创建一个
undef值。你是use strict;和use warnings;吗? -
@SinanÜnür - 凌乱,我同意,但我认为这比错误地更改对想要帮助的人可能很重要的部分数据要好。
-
@mugenkenichi - 感谢您花时间查看。使用严格;只是告诉我,一旦我到达第二个项目数组,我正在使用一个未初始化的值,这就是我在这里发布的原因。我显然没有正确阅读回复。也许您可以提供解决方案或指出我可能误读的地方。对我来说,看起来我正在以与返回结构相同的方式向下钻取结构。
-
解决方案是发布实际的 XML,而不是坚持我们在这个数据结构中做出正面或反面。
标签: xml arrays perl hash xml-parsing