我正在使用SOAP :: Lite连接到外部服务。经过多次试验和错误以及与其他公司的沟通,我发现了这个问题。
我的代码如下所示:
$soap = new SOAP::Lite
->service($wsdl_link)
->uri($url_link)
->proxy($proxy_link)
->on_action(sub { sprintf '"%s%s"', shift, shift });
my $resp = $soap->call('CreateAssignment',SOAP::Data->type('xml'=>$xml),
SOAP::Header->type('xml'=>$headXML));
这会生成以下xml:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" >
<soap:Header>
...
</soap:Header>
<soap:Body>
<CreateAssignment xmlns="url_link">
...
</CreateAssignment></soap:Body></soap:Envelope>
(其中url_link
是有效的网址)
我需要定义其他名称空间。我通过在代码中添加->ns(namespace, prefix)
来完成此操作。但是,这会将其他名称空间添加到“envelope
”标记中。我被公司告知,名称空间需要位于“CreateAssignment
”标签上。实际上,当我进行适当的更改并使用SOAP UI运行它时,它可以很好地工作。
我尝试将“CreateAssignment
”标记添加到我的xml并在没有方法的情况下运行call()
函数。 SOAP :: Lite将xml包装在通用标记中。
我已经阅读了SOAP :: Lite文档,我已经问了搜索引擎,我问了同事,没有人有答案。
有没有办法强制SOAP :: Lite将命名空间声明放在我需要的位置?
如果没有,什么是更好的模块?
答案 0 :(得分:0)
我最后和另一位同事坐下来阅读SOAP :: Lite的源代码 - 我们发现方法标签是在sub envelope
中构建的。有一个if语句,模块将使用整个对象,而不是字符串对象,SOAP :: Data对象作为方法传入:
elsif (UNIVERSAL::isa($method => 'SOAP::Data')) {
$body = $method;
}
我改变了这个:
$soap = new SOAP::Lite
->service($wsdl_link)
->uri($url_link)
->proxy($proxy_link)
->on_action(sub { sprintf '"%s%s"', shift, shift });
my $resp = $soap->call('CreateAssignment',SOAP::Data->type('xml'=>$xml),
SOAP::Header->type('xml'=>$headXML));
对此:
$method = SOAP::Data->new(name=>'ns4:CreateAssignment');
$method->attr({'xmlns'=> $namespaceOne,
'xmlns:ns2'=> $namespaceTwo,
'xmlns:ns3'=> $namespaceThree,
'xmlns:ns4'=> $namespaceFour,
'xmlns:ns5'=> $namespaceFive});
$soap = new SOAP::Lite
->service($wsdl_link)
->uri($url_link)
->proxy($proxy_link)
->on_action(sub { sprintf '"%s%s"', shift, shift });
my $resp = $soap->call($method,SOAP::Data->type('xml'=>$xml),
SOAP::Header->type('xml'=>$headXML));
这创建了我的方法标记,完全符合公司要求:
<ns4:CreateAssignment xmlns="namespaceOne" xmlns:ns2="namespaceTwo" xmlns:ns3="namespaceThree" xmlns:ns4="namespaceFour" xmlns:ns5="namespaceFive">
...
</ns4:CreateAssignment>