Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SOAP::Data::Builder, remove xsi:nil="true" when no value provided

Tags:

soap

xml

perl

If I write this SOAP::Data::Builder code (where $sb is a SOAP::Data::Builder Object)

    $sb->add_elem(
        attributes => { run => 'true' },
        name       => 'ccAuthService',
#       value      => ' ', # hack to prevent cs side unparseable xml
    );

it generates the following

<ccAuthService xsi:nil="true" run="true" />

Which is unacceptable because the xsi:nil causes problems on the the receiving end. However if I uncomment the commented out line, I get

<ccAuthService run="true"> </ccAuthService>

Technically this works, so it's a workaround. But what I'd like to ultimately have is

<ccAuthService run="true" />

Which I know works, I just can't figure out how to have it generated.

like image 350
xenoterracide Avatar asked Aug 15 '11 20:08

xenoterracide


3 Answers

This is a solution for fixing this issue with SOAP::Lite (which SOAP::Data::Builder uses).

Define the following somewhere in your code:

sub SOAP::Serializer::as_nonil
{
    my ($self, $value, $name, $type, $attr) = @_;
    delete $attr->{'xsi:nil'};
    return [ $name, $attr, $value ];
}

To use this type:

SOAP::Data->new(
   type => 'nonil',
   name => 'ping',
   prefix => '',
   uri => 'http://myschema.domain/',
);

Some hints on this are in SOAP::Serializer.

like image 96
tbrody Avatar answered Oct 28 '22 09:10

tbrody


$sb is taking your element and feeding it through an xslt processor to generate a SOAP message. Can you interject 'middle-man' logic into this process?

In my case, I used wsdl to generate a .Net 4 C# SoapHttpClientProtocol object which has a virtual method I was able to override called GetWriterForMessage. This method returns an XmlWriter object used to write out the SOAP message (in essence, the xslt processor). I was able to created a custom XmlWriter that ignored the 'write out attributes whose local name was nil' commands.

What's great about THIS solution is it's generic. So, now it's part of my library I can use whenever I want to 'filter' any Xml output. And it only took one custom class.

It looks like your code is c?? Maybe $sb has a pointer you can set to redirect it's 'xml writer' to a custom method.

Hope this helps someone.

like image 2
xJonx Avatar answered Oct 28 '22 08:10

xJonx


You could leave XML generation in SOAP as is, parse the code generated with a parser such as XML::Twig on the sending end, and print it out with the same library, applying the options you need for it to be successfully handled at the receiving end.

like image 1
P Shved Avatar answered Oct 28 '22 08:10

P Shved