我正在编写一个perl脚本来调用第三方的Web服务并解析响应XML,以便将数据写入数据库。我被建议使用SOAP :: Lite(目前在草莓Perl 5.22.0.1中使用1.14 for Windows 64-bit)。
响应可能如下所示:
<soap:Envelope>
<soap:Body>
<getEventsResponse>
<GetEventsResponse>
<events>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
.
.
.
</events>
</GetEventsResponse>
</getEventsResponse>
</soap:Body>
</soap:Envelope>
其中valueofattr1
可以是该Event对象的唯一标识符,并且Events的数量是可变的。每个活动都有相同的吸引力。
要检索和评估事件,请使用以下软件包和代码:
package EventServices;
use SOAP::Lite;
sub new {
my ($class) = shift;
my ($url) = shift;
my ($soapuser) = shift;
my ($soappasswordhash) = shift;
my $self = {
"url" => $url,
"soapuser" => $soapuser,
"soappasswordhash" => $soappasswordhash,
"client" => undef
};
bless $self, 'EventServices';
return $self;
}
sub connect {
my $self = shift;
$self->{client} =
SOAP::Lite->uri('http://3rdparty.co.uk')
->proxy( $self->{url} . '/hosted/services/EventServicesWS' );
$self->{client}->autotype(0);
# This stops SOAP::DATA automatically adding type definitions within every
# XML element, which is often wrong and fails the XSD validation.
}
sub getBatch {
my $self = shift;
my $startDate = shift;
my $endDate = shift;
my $result =
$self->{client}->getEvents(
SOAP::Data->prefix('ns2')->uri('http://3rdparty.co.uk')->name("userContext" =>
\SOAP::Data->value(
SOAP::Data->prefix('ns1')
.
.
.
)
)
);
return $result;
}
1;
my $fs = new EventServices( "https://3rdparty.co.uk", "<username>", "<hashedpassed>" );
$fs->connect();
$result = $fs->getBatch($startDate, $endDate);
for my $event ( $result->valueof('//getEventsResponse/GetEventsResponse/events/Event'))
{
my $e_eventAttr1 = $event->{e_eventAttr1};
my $e_eventAttr2 = $event->{e_eventAttr2};
my $e_eventAttr3 = $event->{e_eventAttr3};
.
.
.
}
这一切都运行正常,代码愉快地遍历每个事件。我一如既往地相信有不止一种方法可以实现这一目标,但这很简单。
循环遍历一系列事件,我现在需要探索如何遍历每个事件中的子数组。 XML现在看起来像这样:
<soap:Envelope>
<soap:Body>
<getEventsResponse>
<GetEventsResponse>
<events>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventMessages>
<EventMessageDetail>
<MessageType>type1</MessageType>
<MessageText>textOfTheMessageForType1</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type2</MessageType>
<MessageText>textOfTheMessageForType2</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type3</MessageType>
<MessageText>textOfTheMessageForType3</MessageText>
<\EventMessageDetail>
.
.
.
</EventMessages>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventMessages>
<EventMessageDetail>
<MessageType>type1</MessageType>
<MessageText>textOfTheMessageForType1</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type2</MessageType>
<MessageText>textOfTheMessageForType2</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type3</MessageType>
<MessageText>textOfTheMessageForType3</MessageText>
<\EventMessageDetail>
.
.
.
</EventMessages>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventMessages>
<EventMessageDetail>
<MessageType>type1</MessageType>
<MessageText>textOfTheMessageForType1</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type2</MessageType>
<MessageText>textOfTheMessageForType2</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type3</MessageType>
<MessageText>textOfTheMessageForType3</MessageText>
<\EventMessageDetail>
.
.
.
</EventMessages>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
<Event>
<EventAttr1>valueofattr1</EventAttr1>
<EventAttr2>valueofattr2</EventAttr2>
<EventMessages>
<EventMessageDetail>
<MessageType>type1</MessageType>
<MessageText>textOfTheMessageForType1</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type2</MessageType>
<MessageText>textOfTheMessageForType2</MessageText>
<\EventMessageDetail>
<EventMessageDetail>
<MessageType>type3</MessageType>
<MessageText>textOfTheMessageForType3</MessageText>
<\EventMessageDetail>
.
.
.
</EventMessages>
<EventAttr3>valueofattr3</EventAttr3>
</Event>
.
.
.
</events>
</GetEventsResponse>
</getEventsResponse>
</soap:Body>
</soap:Envelope>
我应该严格地假设事件具有相同数量的EventMessages,如果 任何
我希望在事件的外部for
循环中有一个for
循环,但我发现如果我尝试$result->valueof('//getEventsResponse/GetEventsResponse/events/Event/EventMessages/EventMessageDetail')
,那么内部for
循环就会通过对于所有事件,所有EventMessageDetails,而不仅仅是外部for循环捕获的Event的EventMessageDetails。
我尝试使用[n]从for
中的外部$result->match( )
循环引用当前事件,但无法确定它应该如何工作。
有谁能告诉我如何解决这个问题?
一个解决方案:
在看了一下DATA :: Dumper的提示后,我终于发现在主for
循环中添加以下代码是一种享受。
use Data::Dumper
my $a = Dumper($Event->{'EventMessages'}->{'EventMessageDetail'});
eval $a;
for my $MessageDetail (@{$VAR1}) {
print "MessageType: $MessageDetail->{MessageType}; \n";
print "MessageText = $MessageDetail->{MessageText}; \n";
}
解答:
这是一个更简洁,更快速的执行编码方法,根本不需要Data :: Dumper模块:
for my $MessageDetail ( @{ $Event->{'EventMessages'}->{'EventMessageDetail'} } ) {
print "MessageType: $MessageDetail->{MessageType}; \n";
print "MessageText = $MessageDetail->{MessageText}; \n";
}
答案 0 :(得分:0)
所以简单的答案是for my $MessageDetail ( @{ $Event->{'EventMessages'}->{'EventMessageDetail'} } ) {...}
。
谢谢simbabque。