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

99封情书 提交于 2020-01-14 09:52:27

问题


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.


回答1:


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.




回答2:


$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.




回答3:


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.




回答4:


I too had the same problem, and this is how I got it solved, maybe it may help others too.

The 'xsi:nil= true' is set if the soap data object's value is undef, set it to arrayref to solve the problem.

Please see below code for reference:

Soap format:

< m:clHotelIdInfo>< m:HotelIdInfo xsi:nil=true  id="1219615" />< /m:clHotelIdInfo>

Soap Object structure

*bless( {
     '_name' => 'clHotelIdInfo',
     '_signature' => [],
     '_value' => [
                   \bless( {
                              '_signature' => [],
                              '_value' => [
                                            bless( {
                                                     '_name' => 'HotelIdInfo',
                                                     '_signature' => [],
                                                     **'_value' => [
                                                                   undef
                                                                 ],**
                                                     '_prefix' => 'm',
                                                     '_attr' => {
                                                                  'id' => '1219615'
                                                                }
                                                   }, 'SOAP::Data' )
                                          ],
                              '_attr' => {}
                            }, 'SOAP::Data' )
                 ],
     '_prefix' => 'm',
     '_attr' => {}
 }, 'SOAP::Data' )*

Expected Soap format :

< m:clHotelIdInfo>< m:HotelIdInfo id="1219615" /></ m:clHotelIdInfo>                                                         

So Soap Object structure must be:

*bless( {
         '_name' => 'clHotelIdInfo',
         '_signature' => [],
         '_value' => [
                       \bless( {
                                  '_signature' => [],
                                  '_value' => [
                                                bless( {
                                                         '_name' => 'HotelIdInfo',
                                                         '_signature' => [],
                                                         **'_value' => [],**
                                                         '_prefix' => 'm',
                                                         '_attr' => {
                                                                      'id' => '1219615'
                                                                    }
                                                       }, 'SOAP::Data' )
                                              ],
                                  '_attr' => {}
                                }, 'SOAP::Data' )
                     ],
         '_prefix' => 'm',
         '_attr' => {}
}, 'SOAP::Data' )*

If you observe the objects carefully the value of HotelIdInfo was undef earlier, which when changed to arrayref, helped me to get rid of 'xsi:nil = true'.

I didn't have to change any of the existing modules of cpan. Just set the value arrayref instead of undef. This is a solution in perl language.



来源:https://stackoverflow.com/questions/7070553/soapdatabuilder-remove-xsinil-true-when-no-value-provided

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!