7

I am working on a SOAP client in PHP, and the calls are going through to the service fine, with the exception of calls where there are elements that are identical to each other. It seems that when this happens, rather than creating two separate but identical elements, like this:

<ns1:someelement>
  <ns1:name>name1</ns1:name>
  <ns1:value>value1</ns1:value>
</ns1:someelement>
<ns1:someelement>
  <ns1:name>name1</ns1:name>
  <ns1:value>value1</ns1:value>
</ns1:someelement>

it is insisting on making only one copy of the element and assigning it an ID, and using href for any subsequent instances of that element (shown below), which is not supported by the webservice I am using (I don't know why this is, but it doesn't really matter because I cannot change it)

<ns1:someelement id="#ref1">
  <ns1:name>name1</ns1:name>
  <ns1:value>value1</ns1:value>
</ns1:someelement>
<ns1:someelement href="#ref1" />

So my question is how might I force the XML to come out with the duplicate elements included in full, rather than them using hrefs/ids. I checked the docs for PHP SoapClient for an option or something of the sort, but couldn't find anything. Any help or advice would be greatly appreciated. Thanks.

1
  • None of PHP's soap clients are that great. It's fairly trivial to hand-roll one, at least for a particular webservice. I'd honestly recommend going that route if the prepackaged ones don't work for you (I've been faced with this problem myself more than once, handrolling worked nicely). Commented Mar 16, 2012 at 21:08

4 Answers 4

3

SoapClient makes a reference only when you use the same object on multiple XML nodes. Make for each place a new object if you do not want the references.

Sign up to request clarification or add additional context in comments.

Comments

1

In your PHP code make a property with unique index so the resulting XML will look like:

<ns1:someelement>
  <ns1:name>name1</ns1:name>
  <ns1:value>value1</ns1:value>
  <ns1:index>0</ns1:value>
</ns1:someelement>
<ns1:someelement>
  <ns1:name>name1</ns1:name>
  <ns1:value>value1</ns1:value>
  <ns1:index>1</ns1:value>
</ns1:someelement>

Then PHP SoapClient will not make href references to the same copies of data and web service successfully ignored these unique fields in my case. No, I do not pass the same fields of someelement as reference in PHP code. They are cloned, however PHP SoapClient is smart enough to zip their multiple occurencies as references, unfortunately.

1 Comment

I lost hours of my life trying to solve this problem today with FedEx's SOAP API. Your solution here solved the problem. I expected FedEx's system to complain about the new element that didn't match the spec, but in fact the outgoing XML simply omitted it.
0
  • Make sure not use references
  • Try to add params manually with SoapParam
  • Try to add params manually with SoapVar

$soapClient->__soapCall('Method', array(
    new SoapParam($someelement1, 'someelement'),
    // or
    new SoapVar('<ns1:someelement><ns1:name>name1</ns1:name><ns1:value>value1</ns1:value></ns1:someelement>', XSD_ANYXML)
));

Comments

0

Hello You can try this fix:

You need to extends the SoapClient and fix the generated request:

You need to add the tags that are causing problems here

$tags = ['Tag1', 'Tag2', 'Tag3'];

And then use the MySoapClient instead of SoapClient

class MySoapClient extends SoapClient {

public function __construct($a, $b){
    parent::__construct($a, $b);
}

public function __doRequest($request, $location, $action, $version, $one_way = 0) {

    $tags = ['Tag1', 'Tag2', 'Tag3'];
    foreach($tags as $tag){
        if (preg_match("~<ns1:{$tag} id=\"ref(.+)\">(.+)</ns1:{$tag}>~ismU", $request, $matches)) {
            $ref = $matches[1];

            $request = str_replace([' id="ref'.$ref.'"'], '', $request);

            $tagValue = "<ns1:{$tag}>{$matches[2]}</ns1:{$tag}>";
            $request = str_replace("<ns1:{$tag} href=\"#ref{$ref}\"/>", $tagValue, $request);
        }
    }
    return parent::__doRequest($request, $location, $action, $version);
}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.