使用Perl的SOAP :: Lite和WSDL文件进行SOAP调用

使用Perl的SOAP :: Lite和WSDL文件进行SOAP调用

问题描述:

我想对本地Web服务进行SOAP调用。 Web服务是通过WSDL文件定义的(请参见下文)。我想使用Perl和SOAP :: Lite。我试过了:使用Perl的SOAP :: Lite和WSDL文件进行SOAP调用

use strict ; 
use warnings ; 

use SOAP::Lite ; 

my $endpoint = qq{http://example.com:2222/orawsv/PS_API/ACCOUNT_WS} ; 
my $tns = 'http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS' ; 

my $method_urn = $tns ; 
my $soapaction = $tns ; 
my $method = 'GET_BY_ACCOUNT_NUMBER' ; 

my $sObj = SOAP::Lite->new(uri => $soapaction, proxy => $endpoint) ; 

my $response = $sObj->call(SOAP::Data->name($method)->attr({ 'xmlns' => $method_urn}) 
      => SOAP::Data->name('ACCOUNT_NUMBER-VARCHAR2-IN' => '274724')) ; 

print $response->faultstring() . "\n"; 

但是,这会导致XML parsing failed错误消息。什么是正确的SOAP :: Lite代码来调用此方法?

通过上述生成的HTTP请求是

Accept: text/xml 
Accept: multipart/* 
Accept: application/soap 
Content-Length: 553 
Content-Type: text/xml; charset=utf-8 
SOAPAction: "http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS#GET_BY_ACCOUNT_NUMBER" 

<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
    <GET_BY_ACCOUNT_NUMBER xmlns="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS"> 
     <ACCOUNT_NUMBER-VARCHAR2-IN xsi:type="xsd:int">274724</ACCOUNT_NUMBER-VARCHAR2-IN> 
    </GET_BY_ACCOUNT_NUMBER> 
    </soap:Body> 
</soap:Envelope> 

这里是WSDL文件中定义的Web服务:

<definitions name="ACCOUNT_WS" 
targetNamespace="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS" 
xmlns="http://schemas.xmlsoap.org/wsdl/" 
xmlns:tns="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> 
    <types> 
     <xsd:schema targetNamespace="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS" elementFormDefault="qualified">  
      <xsd:element name="CACCOUNT_A-GET_BY_ACCOUNT_NUMBERInput"> 
       <xsd:complexType> 
        <xsd:sequence> 
         <xsd:element name="ACCOUNT_NUMBER-VARCHAR2-IN" type="xsd:string"/> 
        </xsd:sequence> 
       </xsd:complexType> 
      </xsd:element> 
      <xsd:element name="GET_BY_ACCOUNT_NUMBEROutput"> 
       <xsd:complexType> 
        <xsd:sequence> 
         <xsd:element name="RETURN" type="xsd:string"/> 
        </xsd:sequence> 
       </xsd:complexType> 
      </xsd:element>    
     </xsd:schema> 
    </types> 
    <message name="GET_BY_ACCOUNT_NUMBERInputMessage"> 
     <part name="parameters" element="tns:CACCOUNT_A-GET_BY_ACCOUNT_NUMBERInput"/> 
    </message> 
    <message name="GET_BY_ACCOUNT_NUMBEROutputMessage"> 
     <part name="parameters" element="tns:GET_BY_ACCOUNT_NUMBEROutput"/> 
    </message> 
    <portType name="ACCOUNT_WSPortType"> 
     <operation name="GET_BY_ACCOUNT_NUMBER"> 
      <input message="tns:GET_BY_ACCOUNT_NUMBERInputMessage"/> 
      <output message="tns:GET_BY_ACCOUNT_NUMBEROutputMessage"/> 
     </operation> 
    </portType> 
    <binding name="ACCOUNT_WSBinding" type="tns:ACCOUNT_WSPortType"> 
     <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
     <operation name="GET_BY_ACCOUNT_NUMBER"> 
      <soap:operation soapAction="GET_BY_ACCOUNT_NUMBER"/> 
      <input> 
       <soap:body parts="parameters" use="literal"/> 
      </input> 
      <output> 
       <soap:body parts="parameters" use="literal"/> 
      </output> 
     </operation> 
    </binding> 
    <service name="ACCOUNT_WSService"> 
     <documentation>Oracle Web Service</documentation> 
     <port name="ACCOUNT_WSPort" binding="tns:ACCOUNT_WSBinding"> 
      <soap:address location="http://example.com:2222/orawsv/PS_API/ACCOUNT_WS"/> 
     </port> 
    </service> 
</definitions> 

看起来这是一岁左右,所以这可能不是不再相关。总之,基于CPAN肥皂::精简版文档,它看起来像你想这样做:

my $response = $sObj->call(SOAP::Data->name($method)->attr({ 'xmlns' => $method_urn}), 
    SOAP::Data->name('parameters')->value(SOAP::Data->value([ 
     SOAP::Data->name('ACCOUNT_NUMBER-VARCHAR2-IN' => '274724'), 
    ])) 
); 

die $response->fault->{ faultstring } if ($response->fault); 
print $response->result, "\n"; 

既然你有WSDL,你不应该来构建SOAP ::数据对象都没有。只需将WSDL加载到客户端对象并直接调用该方法:

my $client = SOAP::WSDL->new(wsdl => $url_of_wsdl); 
my $result = $client->$method(@arguments); 

是的,就这么简单!