SOAP::WSDL::SAX::MessageHandler - Convert SOAP messages to custom object trees
# this is the direct variant, recommended for performance use SOAP::WSDL::SAX::MessageHandler; use XML::LibXML; my $filter = SOAP::WSDL::SAX::MessageHandler->new( { class_resolver => FakeResolver->new() ), "Object creation"); my $parser = XML::LibXML->new(); $parser->set_handler( $filter ); $parser->parse_string( $soap_message ); my $object_tree = $filter->get_data(); # This is the XML::ParserFactory variant - for those who want other # parsers than XML::Simple.... use SOAP::WSDL::SAX::MessageHandler; use XML::SAX::ParserFactory; my $filter = SOAP::WSDL::SAX::MessageHandler->new( { class_resolver => FakeResolver->new(), base => 'XML::SAX::Base', ), "Object creation"); my $parser = XML::LibXML->new(); $parser->set_handler( $filter ); $parser->parse_string( $soap_message ); my $object_tree = $filter->get_data();
Parses a SOAP message into an object tree.
For every element in the SOAP message, an object is created. The class of the object is determined via a Resolver object which has to be passed to new via the class_resolver parameter.
The class resolver must returned a method "get_class", which is passed a list ref of the current element's XPath (relative to Body), split by /.
This method must return a class name appropriate for a XML element.
A class resolver package might look like this:
package FakeResolver; my %class_list = ( 'EnqueueMessage' => 'Typelib::TEnqueueMessage', 'EnqueueMessage/MMessage' => 'Typelib::TMessage', 'EnqueueMessage/MMessage/MRecipientURI' => 'SOAP::WSDL::XSD::Builtin::anyURI', 'EnqueueMessage/MMessage/MMessageContent' => 'SOAP::WSDL::XSD::Builtin::string', ); sub new { return bless {}, 'FakeResolver' }; sub get_class { my $name = join('/', @{ $_[1] }); return ($class_list{ $name }) ? $class_list{ $name } : warn "no class found for $name"; }; 1;
Every element must have a correspondent one in the type library.
Type library classes must provide the following methods:
Builtin types should be resolved as SOAP::WSDL::XSD::Builtin::* classes
new
Constructor
add_FOO
The add_FOO method is called for every child element of the XML node.
Characters are regarded as child element of the last XML node.
A tyelib class implemented as Inside-Out object using Class::Std::Storable as base class would look like this:
package Typelib::TEnqueueMessage; use strict; use Class::Std::Storable; my %MMessage_of :ATTR(:name<MMessage> :default<()>); sub add_MMessage { my ($self, $value) = @_; my $ident = ident $self; # we're the first value return $MMessage_of{ $ident } = $value if not defined $MMessage_of{ $ident }; # we're the second value return $MMessage_of{ $ident } = [ $MMessage_of{ $ident }, $value ] if not ref $MMessage_of{ $ident } eq 'ARRAY'; # we're third or later push @{ $MMessage_of{ $ident } }, $value; return $MMessage_of{ $ident }; } } 1;
Of course one could use a method factory for these add_FOO methods - see t/lib/Typelib/Base.pm for an example.
SOAP::WSDL::SAX::MessageHandler with a raw XML::LibXML parser almost reaches the performance of XML::Simple with XML::Parser (and expat) as low-level parser.
And SOAP::WSDL::SAX::MessageHandler builds up a object tree, while XML::Simple just emits hash data structures:
SOAP::WSDL::SAX::MessageHandler: 1 wallclock secs ( 1.39 usr + 0.00 sys = 1.39 CPU) @ 719.42/s (n=1000) XML::Simple: 2 wallclock secs ( 1.25 usr + 0.01 sys = 1.26 CPU) @ 790.51/s (n=1000)
If you know a faster way for parsing XML with a reasonable simple API than XML::LibXML, please let me know...
Ignores all namespaces
Does not handle mixed content
The SOAP header is ignored
Replace the whitespace by @ for E-Mail Address.
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
This module may be used under the same terms as perl itself.
$ID: $ $LastChangedDate: $ $LastChangedRevision: $ $LastChangedBy: $ $HeadURL: $
To install SOAP::WSDL, copy and paste the appropriate command in to your terminal.
cpanm
cpanm SOAP::WSDL
CPAN shell
perl -MCPAN -e shell install SOAP::WSDL
For more information on module installation, please visit the detailed CPAN module installation guide.