Как использовать SOAP API для Perl?

1

Я пытаюсь адаптировать следующий PHP-код в Perl. Это API-интерфейс bioDBnet SOAP. Я попытался выполнить пример в модуле SOAP :: WSDL (под SYNOPSIS), но он не подключается. Я получаю сообщение об ошибке:

ПОПЫТКА 1

#!perl -w
use SOAP::WSDL;

my $client = SOAP::WSDL->new(
    wsdl => "http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl",
);

Сообщение об ошибке: cannot import document for namespace >http://schemas.xmlsoap.org/soap/encoding/< without location at/Library/Perl/5.16/SOAP/WSDL/Expat/WSDLParser.pm line 90.

ПОПЫТКА 2

Затем я попытался использовать модуль SOAP :: LITE. Я следовал примеру кода из ЗДЕСЬ (под 6.b. client).

#!perl -w
use SOAP::Lite;

my $client = SOAP::Lite -> 
    service('http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl');

my %db2dbParams;

$db2dbParams{'input'} = "Gene Symbol";
$db2dbParams{'outputs'} = "Gene ID, Ensembl Gene ID";
$db2dbParams{'inputValues'} = "MYC,A1BG";
$db2dbParams{'taxonId'} = "9606";

$db2dbRes = $client->db2db(%db2dbParams);
print $db2dbRes;

Вышеприведенный код ничего не печатает. Как получить API-интерфейс bioDBnet SOAP для Perl?

Теги:
soap
web-services
wsdl

2 ответа

1
Лучший ответ

Ваши второй скрипты работают, за исключением части db2db. Я предполагаю, что конверт XML SOAP, отправляемый на сервер, не в хорошей форме, при отправке с помощью SOAP :: LITE.

Я включил отладку во второй строке:

#!/usr/bin/perl -w
use SOAP::Lite +trace =>'debug';
#use SOAP::Lite;

my $client = SOAP::Lite->service('http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl');

$inputs = $client->getInputs();
print $inputs;

$input = "Gene Symbol";
$outputs = $client->getOutputsForInput($input);
print $outputs;

$dirOutputs = $client->getDirectOutputsForInput($input);
print $dirOutputs;

.. Из вашей попытки 2:

# doesn't work, the created XML envelope is not in a good shape
my %db2dbParams;
$db2dbParams{'input'} = "Gene Symbol";
$db2dbParams{'outputs'} = "Gene ID, Ensembl Gene ID";
$db2dbParams{'inputValues'} = "MYC,A1BG";
$db2dbParams{'taxonId'} = "9606";
$db2dbRes = $client->db2db(%db2dbParams);
print $db2dbRes;

.. Я также попытался переписать это с помощью SOAP: Data... но не удалось.

# doesn't work, the created XML envelope is not in a good shape    
$db2dbRes = $client->db2db(
    SOAP::Data->name("db2dbParams")->type("ns1:db2dbParams")->prefix("ns1:db2db")->uri("urn:bioDBnet") =>
        SOAP::Data->type("string")->name("input" => "Gene Symbol"),
        SOAP::Data->type("string")->name("inputValues" => "MYC,MTOR"),
        SOAP::Data->type("string")->name("outputs" => "Gene ID, Affy ID"),
        SOAP::Data->type("string")->name("taxonId" => "9606")
);
print $db2dbRes;

Переключился на PHP, чтобы увидеть рабочий запрос. Я включил отладку в скрипте PHP для печати заголовков запросов и получения рабочего XML-запроса, сделанного с PHP, и повторно использовать его как содержимое POST из PERL. В принципе, добавив параметр trace в SoapClient, а затем сбросив последние заголовки reqeust.

<?php

$wsdl = "http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl";

$client = new SoapClient($wsdl, ['trace' => 1]);

$inputs = $client->getInputs();
print $inputs;

$input = "Gene Symbol";
$outputs = $client->getOutputsForInput($input);
print $outputs;

$dirOutputs = $client->getDirectOutputsForInput($input);
print $dirOutputs;

$db2dbParams['input'] = "Gene Symbol";
$db2dbParams['outputs'] = "Gene ID, Ensembl Gene ID";
$db2dbParams['inputValues'] = "MYC,A1BG";
$db2dbParams['taxonId'] = "9606";

$db2dbRes = $client->db2db($db2dbParams);
print $db2dbRes;

echo "====== REQUEST HEADERS =====" . PHP_EOL;
var_dump($client->__getLastRequestHeaders());
echo "========= REQUEST ==========" . PHP_EOL;
var_dump($client->__getLastRequest());
echo "========= RESPONSE =========" . PHP_EOL;
var_dump($db2dbRes);

Это печатает заголовки вместе с XML, а ожидаемый результат:

Gene Symbol     Gene ID Ensembl Gene ID
MYC     4609    ENSG00000136997
A1BG    1       ENSG00000121410

Я включил "рабочие" данные XML-запроса в $ message и выполнил запрос POST.

#!/usr/bin/perl -w

use strict;

use LWP::UserAgent;
use HTTP::Request;

my $message = '<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:bioDBnet" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:db2db>
      <db2dbParams xsi:type="ns1:db2dbParams">
        <input xsi:type="xsd:string">Gene Symbol</input>
        <taxonId xsi:type="xsd:string">9606</taxonId>
        <inputValues xsi:type="xsd:string">MYC,A1BG</inputValues>
        <outputs xsi:type="xsd:string">Gene ID, Ensembl Gene ID</outputs>
      </db2dbParams>
    </ns1:db2db>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>';

my $userAgent = LWP::UserAgent->new();
my $request = HTTP::Request->new(POST => 'http://biodbnet.abcc.ncifcrf.gov/webServices/biodbnetSoapServer.php'); # ?debug=1
$request->content($message);
$request->content_type("text/xml; charset=utf-8");
my $response = $userAgent->request($request);

if($response->code == 200) {
    print $response->as_string;
}
else {
    print $response->error_as_HTML;
}

Наконец: рядом с заголовком мы наконец получили некоторые данные:

<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:db2dbResponse>
      <return xsi:type="xsd:string">Gene Symbol Gene ID Ensembl Gene ID
        MYC 4609 ENSG00000136997 A1BG 1 ENSG00000121410
      </return>
    </ns1:db2dbResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Теперь все, что вам нужно сделать, - извлечь return элемент внутри ns1:db2dbResponse из $response->as_string (возможно, используя LibXML).

Другими словами: это обходит SOAP :: Lite и использует LWP и простой запрос POST с XML, разбор XML-ответа. Вы теряете автоматическое извлечение и должны обрабатывать возвращаемые данные вручную.

  • 1
    Благодарю. Мне нравится это решение, потому что существует структура выводимых данных, которую я смог проанализировать с помощью Regex return элемента / тега. LibXML тоже хороший вариант.
3

Не используйте метод SOAP :: Lite, в основном это не работает. Постройте структуру мыла вручную. Я старался как можно больше следить за php xml, хотя большинство префиксов не требуется.

use strict;
use warnings;
use Data::Dumper;
use SOAP::Lite;
#use SOAP::Lite +trace=>'all';

$uri = 'urn:bioDBnet';
$proxy = 'http://biodbnet.abcc.ncifcrf.gov/webServices/biodbnetSoapServer.php';
$tns = 'urn:bioDBnet';
$soap = SOAP::Lite->new(uri => $uri,proxy => $proxy);
$soap->envprefix('SOAP-ENV');
$soap->encprefix('SOAP-ENC');
$soap->ns($tns,'tns1');
$soap->on_action(sub{$tns.'#db2db'});
@request = (SOAP::Data->name(db2dbParams => \SOAP::Data->value(
  SOAP::Data->name(input => 'Gene Symbol'),
  SOAP::Data->name(outputs => 'Gene ID, Ensembl Gene ID'),
  SOAP::Data->name(inputValues => 'MYC,A1BG'),
  SOAP::Data->name(taxonId => 9606),
   ))->type('ns1:db2dbParams'),
 );
 $db2db = $soap->db2db(@request);
 if ($match = $db2db->match('/Envelope/Body/db2dbResponse')) {
  print "match ok: $match\n";
  $result = $db2db->result;
  print Dumper($result);
} else {
 print "match nok: $match\n";
}

Это создает требуемый вывод с сервера.

  • 0
    добро пожаловать в ТАК. это хорошее решение. спасибо и +1
  • 1
    Ах, хитрость в том, чтобы избежать метода обслуживания и использовать прокси вместо этого. +1

Ещё вопросы

Сообщество Overcoder
Наверх
Меню