I'm trying to use a WSDL file from a 3rd party, and they define some of their objects as inheriting from a common base class.
I can't use the real example for IP reasons, so I'll make a simple toy example:
FooUser is a class with base class "FooObject",
FooGroup is another class with base class "FooObject".
There is a method that wants an array of FooObject.
If I call it as $moo->set_Objects([$fooUserObject]);
then it complains that the method wanted a FooObject and not a FooUser.
If I call it as $moo->set_Objects($fooUserObject) then it accepts that, but outputs xml that looks like this:
<moo ...><FooObjects><userAttrib1>Field from User</userAttrib1><userAttrib2>Another field from User</userAttrib2></FooObjects></moo>
Basically, polymorphism in arrays just doesn't sit well at all.
I encountered the exact same problem. It appears that SOAP/WSDL/XSD/Typelib/ComplexType.pm doesn't check for subtypes when it encounters a sequence. The below patch fixes it for me.
Best regards,
Prutskovlen
Index: lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm
That patch seems to get me past the checking, but it's still casting it to the base class type to encode it.
I was afraid that was gonna be your next problem :)
I'm on the Typemap branch, and the below is what it took to get my web service up and running (serialization + deserialization). Note that the serialize_attr hack is REALLY disgusting, but it'll have to work until Martin gets around to adding proper xsi:type support to the serializer.
If you decide to try this out you'll have to switch to the Typemap branch, apply the patch and regenerate your perl classes using wsdl2perl.pl
Best regards,
Prutskovlen
Index: lib/SOAP/WSDL/Expat/MessageParser.pm
--- lib/SOAP/WSDL/Expat/MessageParser.pm (revision 743)
+++ lib/SOAP/WSDL/Expat/MessageParser.pm (working copy)
@@ -59,6 +59,15 @@
return $self->{ class_resolver };
}
+sub prefix_resolver {
+ my $self = shift;
+ if (@_) {
+ $self->{ prefix_resolver } = shift
+ or return;
+ }
+ return $self->{ prefix_resolver };
+}
+
sub load_classes {
my $self = shift;
return if $LOADED_OF{ $self->{ class_resolver } };
Index: lib/SOAP/WSDL/Deserializer/XSD.pm
===================================================================
--- lib/SOAP/WSDL/Deserializer/XSD.pm (revision 743)
+++ lib/SOAP/WSDL/Deserializer/XSD.pm (working copy)
@@ -43,8 +43,8 @@
if ($caller->can('get_class_resolver'));
# new style
- $parser_of{ ${ $self } }->set_name_resolver( $caller->_get_name_resolver() )
- if $caller->can('get_name_resolver');
+ $parser_of{ ${ $self } }->prefix_resolver( $caller->_get_name_resolver()->get_prefix_resolver() )
+ if $caller->can('_get_name_resolver');
if (ref $method) {
# set class resolver if serializer supports it
Index: lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm
===================================================================
--- lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm (revision 743)
+++ lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm (working copy)
@@ -81,8 +81,13 @@
}
sub serialize_attr {
- return q{} if not $xml_attr_of{ ${ $_[0] } };
- return $xml_attr_of{ ${ $_[0] } }->serialize();
+ if (ref($_) =~ m/::([^:]+)$/) {
+ return qq{ xsi:type="$1"} if not $xml_attr_of{ ${ $_[0] } };
+ return qq{ xsi:type="$1"}.$xml_attr_of{ ${ $_[0] } }->serialize();
+ }else{
+ return if not $xml_attr_of{ ${ $_[0] } };
+ return $xml_attr_of{ ${ $_[0] } }->serialize();
+ }
}
Whoops, lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm line 88 (after the patch) should have been:
return q{} if not $xml_attr_of{ ${ $_[0] } };
instead of
return if not $xml_attr_of{ ${ $_[0] } };
And this patch silences an annoying warning:
Index: lib/SOAP/WSDL/Expat/MessageParser.pm
--- lib/SOAP/WSDL/Expat/MessageParser.pm (revision 743)
+++ lib/SOAP/WSDL/Expat/MessageParser.pm (working copy)
@@ -95,7 +105,7 @@
}
return "SOAP::WSDL::XSD::Typelib::Builtin::$localname"
- if ($namespace eq 'http://www.w3.org/2001/XMLSchema');
+ if (defined $namespace && $namespace eq 'http://www.w3.org/2001/XMLSchema');
# resolve perl prefix
my $perl_prefix = $self->{ prefix_resolver }->resolve_prefix('type', $namespace);