Search code examples
perlsoapsoaplite

How can I change what order the xml elements of a SOAP::Lite request are generated with in perl?


I'm trying to make a request to a SOAP::Lite server and the vendor wants me to send a request where MessageSource comes before MessageContent, but when I pass my hash to SOAP::Lite it always makes it the other way around.

I've tried using Tie::IxHash to no avail.

I'm thinking about just hand-writing the XML with SOAP::Data->type('xml' => $xml_content), but it really feels like a workaround that will get really annoying to support.


Solution

  • I have personally found that I prefer to use SOAP::Data::Builder for building the SOAP::Data and then passing it to SOAP::Lite.

    #!/usr/bin/perl
    use 5.006;
    use strict;
    use warnings;
    use SOAP::Lite +trace => [ 'debug' ];
    use SOAP::Data::Builder;
    
    my $req1 = SOAP::Lite->new(
        readable => 1,
        autotype => 0,
        proxy    => 'https://example.com/mysoapuri',
    );
    
    
    my $sb = SOAP::Data::Builder->new;
    $sb->autotype(0);
    
    
    $sb->add_elem(
        name  => 'clientLibrary',
        value => 'foo',
    );
    
    $sb->add_elem(
        name  => 'clientLibraryVersion',
        value => 'bar',
    );
    
    $sb->add_elem(
        name  => 'clientEnvironment',
        value => 'baz',
    );
    
    my $ret = $req1->requestMessage( $sb->to_soap_data );
    

    this generates the following SOAP

    <?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>
        <requestMessage>
          <clientLibrary>foo</clientLibrary>
    
          <clientLibraryVersion>bar</clientLibraryVersion>
    
          <clientEnvironment>baz</clientEnvironment>
        </requestMessage>
      </soap:Body>
    </soap:Envelope>
    

    Note: I realize that adding another dependency may not be in the cards... unfortunately I have never really figured out how else to get my data right.