Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
008d06b72a | ||
|
|
c6a48ba84b | ||
|
|
30be0da3dc | ||
|
|
2347a88353 | ||
|
|
9e85f63aa0 | ||
|
|
7ba2f93e44 | ||
|
|
099c83b6bc |
34
Build.PL
34
Build.PL
@@ -1,41 +1,45 @@
|
||||
use Module::Build;
|
||||
|
||||
Module::Build->new(
|
||||
$build = Module::Build->new(
|
||||
create_makefile_pl => 'passthrough',
|
||||
dist_abstract => 'SOAP with WSDL support',
|
||||
dist_name => 'SOAP-WSDL',
|
||||
dist_version => '2.00_13',
|
||||
dist_version => '2.00_17',
|
||||
module_name => 'SOAP::WSDL',
|
||||
license => 'artistic',
|
||||
requires => {
|
||||
'Class::Std' => q/v0.0.8/,
|
||||
'Class::Std::Storable' => 0,
|
||||
'Data::Dumper' => 0,
|
||||
'Date::Parse' => 0,
|
||||
'Date::Format' => 0,
|
||||
'LWP::UserAgent' => 0,
|
||||
'List::Util' => 0,
|
||||
'File::Basename' => 0,
|
||||
'File::Path' => 0,
|
||||
'XML::Parser::Expat' => 0,
|
||||
'Template' => 0,
|
||||
'Getopt::Long' => 0,
|
||||
'List::Util' => 0,
|
||||
'LWP::UserAgent' => 0,
|
||||
'Template' => 0,
|
||||
'Term::ReadKey' => 0,
|
||||
'XML::Parser::Expat' => 0,
|
||||
},
|
||||
buildrequires => {
|
||||
'Date::Parse' => 0,
|
||||
'Date::Format' => 0,
|
||||
'Test::More' => 0,
|
||||
'Class::Std' => q/v0.0.8/,
|
||||
'Class::Std::Storable' => 0,
|
||||
'Cwd' => 0,
|
||||
'Date::Parse' => 0,
|
||||
'Date::Format' => 0,
|
||||
'Getopt::Long' => 0,
|
||||
'List::Util' => 0,
|
||||
'LWP::UserAgent' => 0,
|
||||
'File::Basename' => 0,
|
||||
'File::Path' => 0,
|
||||
'XML::Parser::Expat' => 0,
|
||||
'Template' => 0,
|
||||
'Getopt::Long' => 0,
|
||||
'Cwd' => 0,
|
||||
'File::Find' => 0,
|
||||
'File::Spec' => 0,
|
||||
'Storable' => 0,
|
||||
'Test::More' => 0,
|
||||
'Template' => 0,
|
||||
'XML::Parser::Expat' => 0,
|
||||
},
|
||||
recursive_test_files => 1,
|
||||
)->create_build_script;
|
||||
);
|
||||
$build->add_build_element('tt');
|
||||
$build->create_build_script;
|
||||
|
||||
175
CHANGES
175
CHANGES
@@ -1,9 +1,9 @@
|
||||
Release notes for SOAP::WSDL 2.00_12
|
||||
Release notes for SOAP::WSDL 2.00_17
|
||||
-------
|
||||
|
||||
I'm very happy to present a new pre-release version of SOAP::WSDL.
|
||||
I'm proud to present a new pre-release version of SOAP::WSDL.
|
||||
|
||||
SOAP::WSDL is a toolkit for creating SOAP interfaces in perl.
|
||||
SOAP::WSDL is a toolkit for creating WSDL-based SOAP client interfaces in perl.
|
||||
|
||||
Features:
|
||||
|
||||
@@ -12,10 +12,16 @@ Features:
|
||||
o Supports document/literal message style/encoding
|
||||
* Code generator for generating WSDL-based interface classes
|
||||
o Generated code includes usage documentation for the web service interface
|
||||
* Easy-to use API. SOAP::WSDL is much easier to use than SOAP::Lite.
|
||||
* Easy-to use API
|
||||
o Automatically encodes perl data structures as message data
|
||||
o Automatically sets HTTP headers right
|
||||
* SOAP::Lite like look and feel.
|
||||
* Efficient documentation
|
||||
o SOAP::WSDL::Manual guides you at getting your work done, not at
|
||||
the module's internals
|
||||
* Thorough test suite
|
||||
o SOAP::WSDL is heavily regression tested, with a test coverage of
|
||||
over 90%.
|
||||
* SOAP::Lite like look and feel
|
||||
o Where possible, SOAP::WSDL mimics SOAP::Lite's API to allow easy migrations
|
||||
* XML schema based class library for creating data objects
|
||||
* High-performance XML parser
|
||||
@@ -23,13 +29,168 @@ Features:
|
||||
The following plugins are supported:
|
||||
o Transport plugins via SOAP::WSDL::Factory::Transport
|
||||
o Serializer plugins via SOAP::WSDL::Factory::Serializer
|
||||
|
||||
o Deserializer plugins via SOAP::WSDL::Factory::Serializer
|
||||
|
||||
The following changes have been made:
|
||||
|
||||
2.00_17
|
||||
----
|
||||
The following features were added (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660924):
|
||||
|
||||
The following bugs have been fixed (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660921):
|
||||
|
||||
* [ 1772617 ] SOAP Header not working
|
||||
Added header support. Currently, SOAP headers are only supported with
|
||||
the SOM or the XSD (SOAP11) serializer.
|
||||
|
||||
* [ 1805238 ] Tests in t/SOAP/WSDL don't work when run from t/
|
||||
|
||||
* [ 1805241 ] explain() broken in SOAP::WSDL
|
||||
explain has been removed from SOAP::WSDL
|
||||
|
||||
The following uncategorized improvements have been made:
|
||||
|
||||
* Added limited support for complexType complexContent content model with
|
||||
restriction variety.
|
||||
SOAP::WSDL now supports this XML Schema definition variant, although no
|
||||
constraints are imposed on derived types yet.
|
||||
Derived types do not serialize with a xsi:type attribute (and the xsi:type
|
||||
attribute is not recognized by the XML parser), so you cannot use derived
|
||||
types as a substitute for theri parent, yet.
|
||||
|
||||
* Added support for complexType choice variety
|
||||
complexType definitions using the choice variety are now supported,
|
||||
even though the content is not checked (if you pass in invalid data,
|
||||
invalid XML will be generated).
|
||||
|
||||
* Added Loopback Transport backend.
|
||||
SOAP::WSDL::Tranport::Loopback just returns the request as respons, but
|
||||
allows testing the whole chain from user interface to transport backend.
|
||||
|
||||
* Fixed SOAP::WSDL::Factory::Transport prefer user-registered
|
||||
transport backend
|
||||
|
||||
* Fixed set_soap_version method in SOAP::WSDL::Client.
|
||||
Re-setting the SOAP version now invalidates (resets) serializer and
|
||||
deserializer, but not the transport backend.
|
||||
|
||||
* Fixed SOAP::WSDL::XSD::Typelib::Builtin::boolean to return false
|
||||
when false and true when true.
|
||||
|
||||
* SOAP::WSDL::XSD::Typelib::Builtin::normalizedString now replaces all
|
||||
occurences of tab, newline and carriage return by whitespce on set_value.
|
||||
|
||||
* Code cleanup
|
||||
o Lots of orphan methods now replaced by the SOAP::WSDL::Generator
|
||||
hierarchy have been removed.
|
||||
o Unused (and unusable) readable option checking has been removed in
|
||||
SOAP::WSDL::Serializer::SOAP11.
|
||||
o Unused XML Schema facet attributes have been removed from XSD Builtin
|
||||
classes
|
||||
o Methods common to all expat parser classes have been factored out
|
||||
into a common base class.
|
||||
|
||||
* XML serialization speedup for SOAP::WSDL::XSD::* objects
|
||||
|
||||
* Tests added to improve test coverage.
|
||||
|
||||
* A few documentation errors have been fixed
|
||||
|
||||
* Misspelled default Typemap and Interface prefixes have been corrected
|
||||
|
||||
2.00_16
|
||||
----
|
||||
The following features were added (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660924):
|
||||
|
||||
* [ 1761532 ] Support embedded atomic types
|
||||
SOAP::WSDL now supports a greater variety of XML Schema type definitions.
|
||||
Note that XML Schema support is still incomplete, though.
|
||||
|
||||
* [ 1797943 ] Create Perl Hash Deserializer
|
||||
There's a new deserializer which outputs perl hashes as data structures.
|
||||
Much like XML::Simple, but faster. No XML Attribute support, though.
|
||||
|
||||
* [ 1797678 ] Move Code generator from WSDL::Definitions to separate class
|
||||
|
||||
* [ 1803330 ] Create one interface per port
|
||||
SOAP::WSDL now creats one interface per port, not one per service.
|
||||
|
||||
The following bugs have been fixed (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660921):
|
||||
|
||||
* [ 1804441 ] parts from binding not regarded in SOAP::WSDL
|
||||
SOAP::WSDL (interpreter mode) now respects the body parts specified in the
|
||||
binding.
|
||||
|
||||
* [ 1803763 ] nonNegativeInteger misspelled in Schema::Builtin
|
||||
|
||||
* [ 1793965 ] _expand() does not work on non-root-node ns declarations
|
||||
|
||||
* [ 1792348 ] 006_client.t requires SOAP::Lite in 2.00_15
|
||||
SOAP::WSDL no longer attempts to load SOAP::WSDL::Deserializer::SOM when
|
||||
no_dispatch is set.
|
||||
006_client.t now sets outputxml(1), to be really sure.
|
||||
|
||||
The following uncategorized improvements have been made:
|
||||
|
||||
* Code generator only generates interface for the first port in a service
|
||||
The code generator now generates interfaces for all ports.
|
||||
Note: The naming scheme has changed. It is now
|
||||
InterfacePrefix::Service::Port
|
||||
|
||||
* XML Parser speedup
|
||||
The XML parser has received a little speedup.
|
||||
|
||||
* A number of errors in parsing / traversing WSDL documents have been
|
||||
corrected.
|
||||
|
||||
* Documentation has been improved
|
||||
|
||||
* A number of (incorrect, but passing) tests have been fixed.
|
||||
|
||||
* Code cleanup: The SOAP::WSDL::SAX* modules are no longer included, as they
|
||||
are not supported any more. They can still be found in SOAP::WSDL's
|
||||
subversion repository in the attic directory, though.
|
||||
|
||||
2.00_15
|
||||
----
|
||||
|
||||
The following bugs have been fixed (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660921):
|
||||
|
||||
* [ 1792321 ] 2.00_14 requires SOAP::Lite for passing tests
|
||||
|
||||
2.00_14
|
||||
----
|
||||
|
||||
The following bugs have been fixed (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660921):
|
||||
|
||||
* [ 1792235 ] SOAP::WSDL::Transport::Test missing from 2.00_13
|
||||
The package has been re-added
|
||||
|
||||
* [ 1792221 ] class_resolver not set from ::Client in 2.00_13
|
||||
Changed to set class_resolver correctly.
|
||||
|
||||
The following uncategorized improvements have been made:
|
||||
|
||||
* The ::SOM deserializer has been simplified to be just a subclass
|
||||
of SOAP::Deserializer from SOAP::Lite
|
||||
* Factories now emit more useful error messages when no class is registered
|
||||
for the protocol/soap_version requested
|
||||
* Documentation has been improved
|
||||
- refined ::Factory:: modules' documentation
|
||||
* Several tests have been added
|
||||
* XSD classes have been improved for testability
|
||||
|
||||
2.00_13
|
||||
----
|
||||
The following features were added (the numbers in square brackets are the
|
||||
tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660924):
|
||||
|
||||
* [ 1790619 ] Test transport backend
|
||||
A test transport backend has been implemented (SOAP::WSDL::Transport::Test).
|
||||
It returns the contents from a file and discards the response.
|
||||
@@ -62,7 +223,7 @@ tracker IDs from https://sourceforge.net/tracker/?group_id=111978&atid=660921):
|
||||
* [1785646] SOAPAction header not set from soap:operation soapAction
|
||||
SOAP::WSDL now sets the SOAPAction header correctly.
|
||||
|
||||
The following uncategorized improvements have been mad:
|
||||
The following uncategorized improvements have been made:
|
||||
|
||||
* Documentation improvements
|
||||
|
||||
|
||||
148
MANIFEST
148
MANIFEST
@@ -1,4 +1,6 @@
|
||||
benchmark/01_expat.t
|
||||
benchmark/smallprof.out
|
||||
benchmark/smallprof.out-whitespace
|
||||
benchmark/XSD/01_anyType.t
|
||||
benchmark/XSD/02_anySimpleType.t
|
||||
benchmark/XSD/03_string.t
|
||||
@@ -24,6 +26,7 @@ example/lib/MyInterfaces/FullerData_x0020_Fortune_x0020_Cookie.pm
|
||||
example/lib/MyInterfaces/GlobalWeather.pm
|
||||
example/lib/MyTypemaps/FullerData_x0020_Fortune_x0020_Cookie.pm
|
||||
example/lib/MyTypemaps/GlobalWeather.pm
|
||||
example/visitor/visitor.pl
|
||||
example/weather.pl
|
||||
example/weather_wsdl.pl
|
||||
example/wsdl/FortuneCookie.xml
|
||||
@@ -36,19 +39,59 @@ lib/SOAP/WSDL/Binding.pm
|
||||
lib/SOAP/WSDL/Client.pm
|
||||
lib/SOAP/WSDL/Client/Base.pm
|
||||
lib/SOAP/WSDL/Definitions.pm
|
||||
lib/SOAP/WSDL/Deserializer/Hash.pm
|
||||
lib/SOAP/WSDL/Deserializer/SOAP11.pm
|
||||
lib/SOAP/WSDL/Deserializer/SOM.pm
|
||||
lib/SOAP/WSDL/Expat/Base.pm
|
||||
lib/SOAP/WSDL/Expat/Message2Hash.pm
|
||||
lib/SOAP/WSDL/Expat/MessageParser.pm
|
||||
lib/SOAP/WSDL/Expat/MessageStreamParser.pm
|
||||
lib/SOAP/WSDL/Expat/MessageSubParser.pm
|
||||
lib/SOAP/WSDL/Expat/SubParser.pm
|
||||
lib/SOAP/WSDL/Expat/WSDLParser.pm
|
||||
lib/SOAP/WSDL/Factory/Deserializer.pm
|
||||
lib/SOAP/WSDL/Factory/Serializer.pm
|
||||
lib/SOAP/WSDL/Factory/Transport.pm
|
||||
lib/SOAP/WSDL/Generator/Template.pm
|
||||
lib/SOAP/WSDL/Generator/Template/XSD.pm
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/_type_class.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/all.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/atomicTypes.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/complexContent.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/contentModel.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/POD/all.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/POD/choice.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/POD/complexContent.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/POD/restriction.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/POD/structure.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/complexType/restriction.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/element.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/element/POD/structure.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Body.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Header.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Operation.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/POD/Element.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/POD/Message.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/POD/method_info.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/POD/Operation.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/POD/Part.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Interface/POD/Type.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/atomicType.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/contentModel.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/list.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/POD/list.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/POD/restriction.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/POD/structure.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/restriction.tt
|
||||
lib/SOAP/WSDL/Generator/Template/XSD/Typemap.tt
|
||||
lib/SOAP/WSDL/Generator/Visitor.pm
|
||||
lib/SOAP/WSDL/Generator/Visitor/Typelib.pm
|
||||
lib/SOAP/WSDL/Generator/Visitor/Typemap.pm
|
||||
lib/SOAP/WSDL/Manual.pod
|
||||
lib/SOAP/WSDL/Manual/Glossary.pod
|
||||
lib/SOAP/WSDL/Manual/WS_I.pod
|
||||
lib/SOAP/WSDL/Manual/XSD.pod
|
||||
lib/SOAP/WSDL/Message.pm
|
||||
lib/SOAP/WSDL/Operation.pm
|
||||
lib/SOAP/WSDL/OpMessage.pm
|
||||
@@ -56,13 +99,17 @@ lib/SOAP/WSDL/Parser.pod
|
||||
lib/SOAP/WSDL/Part.pm
|
||||
lib/SOAP/WSDL/Port.pm
|
||||
lib/SOAP/WSDL/PortType.pm
|
||||
lib/SOAP/WSDL/SAX/MessageHandler.pm
|
||||
lib/SOAP/WSDL/SAX/WSDLHandler.pm
|
||||
lib/SOAP/WSDL/Serializer/SOAP11.pm
|
||||
lib/SOAP/WSDL/Service.pm
|
||||
lib/SOAP/WSDL/SOAP/Address.pm
|
||||
lib/SOAP/WSDL/SOAP/Body.pm
|
||||
lib/SOAP/WSDL/SOAP/Header.pm
|
||||
lib/SOAP/WSDL/SOAP/HeaderFault.pm
|
||||
lib/SOAP/WSDL/SOAP/Operation.pm
|
||||
lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm
|
||||
lib/SOAP/WSDL/SoapOperation.pm
|
||||
lib/SOAP/WSDL/Transport/HTTP.pm
|
||||
lib/SOAP/WSDL/Transport/Loopback.pm
|
||||
lib/SOAP/WSDL/Transport/Test.pm
|
||||
lib/SOAP/WSDL/TypeLookup.pm
|
||||
lib/SOAP/WSDL/Types.pm
|
||||
lib/SOAP/WSDL/XSD/Builtin.pm
|
||||
@@ -122,19 +169,16 @@ lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm
|
||||
lib/SOAP/WSDL/XSD/Typelib/Element.pm
|
||||
lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm
|
||||
LICENSE
|
||||
MAINFEST
|
||||
Makefile.PL
|
||||
MANIFEST This list of files
|
||||
MANIFEST
|
||||
META.yml
|
||||
README
|
||||
t/001_use.t
|
||||
t/002_parse_wsdl.t
|
||||
t/002_sax.t
|
||||
t/003_sax_serializer.t
|
||||
t/003_wsdl_based_serializer.t
|
||||
t/004_parse_wsdl.t
|
||||
t/004_sax_wsdl.t
|
||||
t/005_parse_contributed.t
|
||||
t/005_sax_contributed_wsdl.t
|
||||
t/006_client.t
|
||||
t/007_envelope.t
|
||||
t/008_client_wsdl_complexType.t
|
||||
@@ -142,16 +186,10 @@ t/009_data_classes.t
|
||||
t/011_simpleType.t
|
||||
t/012_element.t
|
||||
t/013_complexType.t
|
||||
t/014_sax_typelib.t
|
||||
t/015_to_typemap.t
|
||||
t/016_client_object.t
|
||||
t/017_generator_expat.t
|
||||
t/017_generator_libxml.t
|
||||
t/018_generator_expat.t
|
||||
t/018_generator_libxml.t
|
||||
t/017_generator.t
|
||||
t/018_compat_2_00_15-generator.t
|
||||
t/020_storable.t
|
||||
t/021_generator_element_ref_expat.t
|
||||
t/021_generator_element_ref_libxml.t
|
||||
t/098_pod.t
|
||||
t/acceptance/results/03_complexType-all.xml
|
||||
t/acceptance/results/03_complexType-sequence.xml
|
||||
@@ -178,13 +216,21 @@ t/acceptance/wsdl/contributed/Axis.wsdl
|
||||
t/acceptance/wsdl/contributed/ETest.wsdl
|
||||
t/acceptance/wsdl/contributed/OITest.wsdl
|
||||
t/acceptance/wsdl/contributed/tools.wsdl
|
||||
t/acceptance/wsdl/elementAtomicComplexType.xml
|
||||
t/acceptance/wsdl/email_account.wsdl
|
||||
t/acceptance/wsdl/generator_test.wsdl
|
||||
t/acceptance/wsdl/generator_unsupported_test.wsdl
|
||||
t/acceptance/wsdl/message_gateway.wsdl
|
||||
t/contributed.wsdl
|
||||
t/Expat/01_expat.t
|
||||
t/Expat/02_sub_parser.t
|
||||
t/Expat/03_wsdl.t
|
||||
t/lib/MyComplexType.pm
|
||||
t/lib/MyElement.pm
|
||||
t/lib/MyElements/GetWeather.pm
|
||||
t/lib/MyElements/GetWeatherResponse.pm
|
||||
t/lib/MyInterfaces/GlobalWeather.pm
|
||||
t/lib/MySimpleType.pm
|
||||
t/lib/MyTypemaps/GlobalWeather.pm
|
||||
t/lib/Test/SOAPMessage.pm
|
||||
t/lib/Typelib/Base.pm
|
||||
t/lib/Typelib/TEnqueueMessage.pm
|
||||
@@ -204,11 +250,63 @@ t/SOAP/WSDL/04_element.t
|
||||
t/SOAP/WSDL/05_simpleType-list.t
|
||||
t/SOAP/WSDL/05_simpleType-restriction.t
|
||||
t/SOAP/WSDL/05_simpleType-union.t
|
||||
t/SOAP/WSDL/06_keep_alive.t
|
||||
t/SOAP/WSDL/11_helloworld.NET.t
|
||||
t/SOAP/WSDL/12_binding.pl
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/001_string.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/002_dateTime.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/003_date.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/004_time.t
|
||||
t/test.pl
|
||||
t/SOAP/WSDL/12_binding.t
|
||||
t/SOAP/WSDL/Deserializer/Hash.t
|
||||
t/SOAP/WSDL/Deserializer/SOM.t
|
||||
t/SOAP/WSDL/Deserializer/XSD.t
|
||||
t/SOAP/WSDL/Factory/Deserializer.t
|
||||
t/SOAP/WSDL/Factory/Serializer.t
|
||||
t/SOAP/WSDL/Factory/Transport.t
|
||||
t/SOAP/WSDL/Generator/Template.t
|
||||
t/SOAP/WSDL/Generator/Visitor.t
|
||||
t/SOAP/WSDL/Generator/Visitor/Typemap.t
|
||||
t/SOAP/WSDL/Generator/XSD.t
|
||||
t/SOAP/WSDL/Generator/XSD_unsupported.t
|
||||
t/SOAP/WSDL/Transport/01_Test.t
|
||||
t/SOAP/WSDL/Transport/02_HTTP.t
|
||||
t/SOAP/WSDL/Transport/acceptance/test2.xml
|
||||
t/SOAP/WSDL/Transport/acceptance/test3.xml
|
||||
t/SOAP/WSDL/Typelib/Fault11.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/01_constructors.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/anySimpleType.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/anyType.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/anyURI.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/base64Binary.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/boolean.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/byte.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/date.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/dateTime.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/decimal.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/double.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/ENTITY.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/float.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/hexBinary.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/ID.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/IDREF.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/IDREFS.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/int.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/integer.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/long.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/Name.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/NCName.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/negativeInteger.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/NMTOKEN.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/NMTOKENS.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/nonNegativeInteger.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/nonPositiveInteger.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/normalizedString.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/NOTATION.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/positiveInteger.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/short.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/string.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/time.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/token.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/unsignedByte.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/unsignedInt.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/unsignedLong.t
|
||||
t/SOAP/WSDL/XSD/Typelib/Builtin/unsignedShort.t
|
||||
t/test.wsdl
|
||||
TEST_COVERAGE
|
||||
TODO
|
||||
|
||||
444
META.yml
444
META.yml
@@ -1,200 +1,244 @@
|
||||
---
|
||||
name: SOAP-WSDL
|
||||
version: 2.00_13
|
||||
author:
|
||||
abstract: SOAP with WSDL support
|
||||
license: artistic
|
||||
requires:
|
||||
Class::Std: v0.0.8
|
||||
Class::Std::Storable: 0
|
||||
Date::Format: 0
|
||||
Date::Parse: 0
|
||||
File::Basename: 0
|
||||
File::Path: 0
|
||||
Getopt::Long: 0
|
||||
LWP::UserAgent: 0
|
||||
List::Util: 0
|
||||
Template: 0
|
||||
XML::Parser::Expat: 0
|
||||
generated_by: Module::Build version 0.2808
|
||||
meta-spec:
|
||||
url: http://module-build.sourceforge.net/META-spec-v1.2.html
|
||||
version: 1.2
|
||||
provides:
|
||||
SOAP::WSDL:
|
||||
file: lib/SOAP/WSDL.pm
|
||||
version: 2.00_13
|
||||
SOAP::WSDL::Base:
|
||||
file: lib/SOAP/WSDL/Base.pm
|
||||
SOAP::WSDL::Binding:
|
||||
file: lib/SOAP/WSDL/Binding.pm
|
||||
SOAP::WSDL::Client:
|
||||
file: lib/SOAP/WSDL/Client.pm
|
||||
version: 2.00_13
|
||||
SOAP::WSDL::Client::Base:
|
||||
file: lib/SOAP/WSDL/Client/Base.pm
|
||||
SOAP::WSDL::Definitions:
|
||||
file: lib/SOAP/WSDL/Definitions.pm
|
||||
SOAP::WSDL::Deserializer::SOAP11:
|
||||
file: lib/SOAP/WSDL/Deserializer/SOAP11.pm
|
||||
version: 2.00_13
|
||||
SOAP::WSDL::Deserializer::SOM:
|
||||
file: lib/SOAP/WSDL/Deserializer/SOM.pm
|
||||
version: 2.00_13
|
||||
SOAP::WSDL::Expat::MessageParser:
|
||||
file: lib/SOAP/WSDL/Expat/MessageParser.pm
|
||||
SOAP::WSDL::Expat::MessageStreamParser:
|
||||
file: lib/SOAP/WSDL/Expat/MessageStreamParser.pm
|
||||
SOAP::WSDL::Expat::MessageSubParser:
|
||||
file: lib/SOAP/WSDL/Expat/MessageSubParser.pm
|
||||
SOAP::WSDL::Factory::Deserializer:
|
||||
file: lib/SOAP/WSDL/Factory/Deserializer.pm
|
||||
SOAP::WSDL::Factory::Serializer:
|
||||
file: lib/SOAP/WSDL/Factory/Serializer.pm
|
||||
SOAP::WSDL::Factory::Transport:
|
||||
file: lib/SOAP/WSDL/Factory/Transport.pm
|
||||
SOAP::WSDL::Message:
|
||||
file: lib/SOAP/WSDL/Message.pm
|
||||
SOAP::WSDL::OpMessage:
|
||||
file: lib/SOAP/WSDL/OpMessage.pm
|
||||
SOAP::WSDL::Operation:
|
||||
file: lib/SOAP/WSDL/Operation.pm
|
||||
SOAP::WSDL::Part:
|
||||
file: lib/SOAP/WSDL/Part.pm
|
||||
SOAP::WSDL::Port:
|
||||
file: lib/SOAP/WSDL/Port.pm
|
||||
SOAP::WSDL::PortType:
|
||||
file: lib/SOAP/WSDL/PortType.pm
|
||||
SOAP::WSDL::SAX::MessageHandler:
|
||||
file: lib/SOAP/WSDL/SAX/MessageHandler.pm
|
||||
SOAP::WSDL::SOAP::Typelib::Fault11:
|
||||
file: lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm
|
||||
SOAP::WSDL::Serializer::SOAP11:
|
||||
file: lib/SOAP/WSDL/Serializer/SOAP11.pm
|
||||
version: 2.00_13
|
||||
SOAP::WSDL::Service:
|
||||
file: lib/SOAP/WSDL/Service.pm
|
||||
SOAP::WSDL::SoapOperation:
|
||||
file: lib/SOAP/WSDL/SoapOperation.pm
|
||||
SOAP::WSDL::Transport::HTTP:
|
||||
file: lib/SOAP/WSDL/Transport/HTTP.pm
|
||||
SOAP::WSDL::TypeLookup:
|
||||
file: lib/SOAP/WSDL/TypeLookup.pm
|
||||
SOAP::WSDL::Types:
|
||||
file: lib/SOAP/WSDL/Types.pm
|
||||
SOAP::WSDL::XSD::Builtin:
|
||||
file: lib/SOAP/WSDL/XSD/Builtin.pm
|
||||
SOAP::WSDL::XSD::ComplexType:
|
||||
file: lib/SOAP/WSDL/XSD/ComplexType.pm
|
||||
SOAP::WSDL::XSD::Element:
|
||||
file: lib/SOAP/WSDL/XSD/Element.pm
|
||||
SOAP::WSDL::XSD::Schema:
|
||||
file: lib/SOAP/WSDL/XSD/Schema.pm
|
||||
SOAP::WSDL::XSD::Schema::Builtin:
|
||||
file: lib/SOAP/WSDL/XSD/Schema/Builtin.pm
|
||||
SOAP::WSDL::XSD::SimpleType:
|
||||
file: lib/SOAP/WSDL/XSD/SimpleType.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::ENTITY:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/ENTITY.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::ID:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/ID.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::IDREF:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/IDREF.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::IDREFS:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/IDREFS.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NCName:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NCName.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NMTOKEN:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NMTOKEN.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NMTOKENS:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NMTOKENS.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NOTATION:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NOTATION.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::Name:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/Name.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::QName:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/QName.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/anySimpleType.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::anyType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/anyType.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::anyURI:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/anyURI.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::base64Binary:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/base64Binary.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::boolean:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/boolean.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::byte:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/byte.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::date:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/date.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::dateTime:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/dateTime.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::decimal:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/decimal.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::double:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/double.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::duration:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/duration.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::float:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/float.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gDay:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gDay.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gMonth:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gMonth.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gMonthDay:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gMonthDay.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gYear:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gYear.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gYearMonth:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gYearMonth.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::hexBinary:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/hexBinary.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::int:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/int.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::integer:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/integer.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::language:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/language.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::list:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/list.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::long:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/long.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::negativeInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/negativeInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::nonNegativeInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/nonNegativeInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::nonPositiveInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/nonPositiveInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::normalizedString:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/normalizedString.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::positiveInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/positiveInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::short:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/short.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::string:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/string.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::time:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/time.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::token:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/token.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedByte:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedByte.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedInt:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedInt.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedLong:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedLong.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedShort:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedShort.pm
|
||||
SOAP::WSDL::XSD::Typelib::ComplexType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm
|
||||
SOAP::WSDL::XSD::Typelib::Element:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Element.pm
|
||||
SOAP::WSDL::XSD::Typelib::SimpleType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm
|
||||
SOAP::WSDL::XSD::Typelib::SimpleType::restriction:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm
|
||||
resources:
|
||||
license: http://opensource.org/licenses/artistic-license.php
|
||||
---
|
||||
name: SOAP-WSDL
|
||||
version: 2.00_17
|
||||
author: []
|
||||
abstract: SOAP with WSDL support
|
||||
license: artistic
|
||||
resources:
|
||||
license: http://opensource.org/licenses/artistic-license.php
|
||||
requires:
|
||||
Class::Std: v0.0.8
|
||||
Class::Std::Storable: 0
|
||||
Data::Dumper: 0
|
||||
Date::Format: 0
|
||||
Date::Parse: 0
|
||||
File::Basename: 0
|
||||
File::Path: 0
|
||||
Getopt::Long: 0
|
||||
LWP::UserAgent: 0
|
||||
List::Util: 0
|
||||
Template: 0
|
||||
Term::ReadKey: 0
|
||||
XML::Parser::Expat: 0
|
||||
provides:
|
||||
SOAP::WSDL:
|
||||
file: lib/SOAP/WSDL.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Base:
|
||||
file: lib/SOAP/WSDL/Base.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Binding:
|
||||
file: lib/SOAP/WSDL/Binding.pm
|
||||
SOAP::WSDL::Client:
|
||||
file: lib/SOAP/WSDL/Client.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Client::Base:
|
||||
file: lib/SOAP/WSDL/Client/Base.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Definitions:
|
||||
file: lib/SOAP/WSDL/Definitions.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Deserializer::Hash:
|
||||
file: lib/SOAP/WSDL/Deserializer/Hash.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Deserializer::SOAP11:
|
||||
file: lib/SOAP/WSDL/Deserializer/SOAP11.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Deserializer::SOM:
|
||||
file: lib/SOAP/WSDL/Deserializer/SOM.pm
|
||||
version: 2.00_15
|
||||
SOAP::WSDL::Expat::Base:
|
||||
file: lib/SOAP/WSDL/Expat/Base.pm
|
||||
SOAP::WSDL::Expat::Message2Hash:
|
||||
file: lib/SOAP/WSDL/Expat/Message2Hash.pm
|
||||
SOAP::WSDL::Expat::MessageParser:
|
||||
file: lib/SOAP/WSDL/Expat/MessageParser.pm
|
||||
SOAP::WSDL::Expat::MessageStreamParser:
|
||||
file: lib/SOAP/WSDL/Expat/MessageStreamParser.pm
|
||||
SOAP::WSDL::Factory::Deserializer:
|
||||
file: lib/SOAP/WSDL/Factory/Deserializer.pm
|
||||
SOAP::WSDL::Factory::Serializer:
|
||||
file: lib/SOAP/WSDL/Factory/Serializer.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Factory::Transport:
|
||||
file: lib/SOAP/WSDL/Factory/Transport.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Generator::Template:
|
||||
file: lib/SOAP/WSDL/Generator/Template.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Generator::Template::XSD:
|
||||
file: lib/SOAP/WSDL/Generator/Template/XSD.pm
|
||||
SOAP::WSDL::Generator::Visitor:
|
||||
file: lib/SOAP/WSDL/Generator/Visitor.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Generator::Visitor::Typelib:
|
||||
file: lib/SOAP/WSDL/Generator/Visitor/Typelib.pm
|
||||
SOAP::WSDL::Generator::Visitor::Typemap:
|
||||
file: lib/SOAP/WSDL/Generator/Visitor/Typemap.pm
|
||||
SOAP::WSDL::Message:
|
||||
file: lib/SOAP/WSDL/Message.pm
|
||||
SOAP::WSDL::OpMessage:
|
||||
file: lib/SOAP/WSDL/OpMessage.pm
|
||||
SOAP::WSDL::Operation:
|
||||
file: lib/SOAP/WSDL/Operation.pm
|
||||
SOAP::WSDL::Part:
|
||||
file: lib/SOAP/WSDL/Part.pm
|
||||
SOAP::WSDL::Port:
|
||||
file: lib/SOAP/WSDL/Port.pm
|
||||
SOAP::WSDL::PortType:
|
||||
file: lib/SOAP/WSDL/PortType.pm
|
||||
SOAP::WSDL::SOAP::Address:
|
||||
file: lib/SOAP/WSDL/SOAP/Address.pm
|
||||
SOAP::WSDL::SOAP::Body:
|
||||
file: lib/SOAP/WSDL/SOAP/Body.pm
|
||||
SOAP::WSDL::SOAP::Header:
|
||||
file: lib/SOAP/WSDL/SOAP/Header.pm
|
||||
SOAP::WSDL::SOAP::HeaderFault:
|
||||
file: lib/SOAP/WSDL/SOAP/HeaderFault.pm
|
||||
SOAP::WSDL::SOAP::Operation:
|
||||
file: lib/SOAP/WSDL/SOAP/Operation.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::SOAP::Typelib::Fault11:
|
||||
file: lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Serializer::SOAP11:
|
||||
file: lib/SOAP/WSDL/Serializer/SOAP11.pm
|
||||
version: 2.00_13
|
||||
SOAP::WSDL::Service:
|
||||
file: lib/SOAP/WSDL/Service.pm
|
||||
SOAP::WSDL::Transport::HTTP:
|
||||
file: lib/SOAP/WSDL/Transport/HTTP.pm
|
||||
SOAP::WSDL::Transport::Loopback:
|
||||
file: lib/SOAP/WSDL/Transport/Loopback.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::Transport::Test:
|
||||
file: lib/SOAP/WSDL/Transport/Test.pm
|
||||
version: 2.00_14
|
||||
SOAP::WSDL::TypeLookup:
|
||||
file: lib/SOAP/WSDL/TypeLookup.pm
|
||||
SOAP::WSDL::Types:
|
||||
file: lib/SOAP/WSDL/Types.pm
|
||||
SOAP::WSDL::XSD::Builtin:
|
||||
file: lib/SOAP/WSDL/XSD/Builtin.pm
|
||||
SOAP::WSDL::XSD::ComplexType:
|
||||
file: lib/SOAP/WSDL/XSD/ComplexType.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::XSD::Element:
|
||||
file: lib/SOAP/WSDL/XSD/Element.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::XSD::Schema:
|
||||
file: lib/SOAP/WSDL/XSD/Schema.pm
|
||||
SOAP::WSDL::XSD::Schema::Builtin:
|
||||
file: lib/SOAP/WSDL/XSD/Schema/Builtin.pm
|
||||
SOAP::WSDL::XSD::SimpleType:
|
||||
file: lib/SOAP/WSDL/XSD/SimpleType.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::XSD::Typelib::Builtin:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::ENTITY:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/ENTITY.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::ID:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/ID.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::IDREF:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/IDREF.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::IDREFS:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/IDREFS.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NCName:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NCName.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NMTOKEN:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NMTOKEN.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NMTOKENS:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NMTOKENS.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::NOTATION:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/NOTATION.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::Name:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/Name.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::QName:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/QName.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/anySimpleType.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::anyType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/anyType.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::anyURI:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/anyURI.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::base64Binary:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/base64Binary.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::boolean:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/boolean.pm
|
||||
version: 2.00_17
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::byte:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/byte.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::date:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/date.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::dateTime:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/dateTime.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::decimal:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/decimal.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::double:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/double.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::duration:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/duration.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::float:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/float.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gDay:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gDay.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gMonth:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gMonth.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gMonthDay:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gMonthDay.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gYear:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gYear.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::gYearMonth:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/gYearMonth.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::hexBinary:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/hexBinary.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::int:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/int.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::integer:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/integer.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::language:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/language.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::list:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/list.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::long:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/long.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::negativeInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/negativeInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::nonNegativeInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/nonNegativeInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::nonPositiveInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/nonPositiveInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::normalizedString:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/normalizedString.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::positiveInteger:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/positiveInteger.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::short:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/short.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::string:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/string.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::time:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/time.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::token:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/token.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedByte:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedByte.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedInt:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedInt.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedLong:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedLong.pm
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::unsignedShort:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Builtin/unsignedShort.pm
|
||||
SOAP::WSDL::XSD::Typelib::ComplexType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm
|
||||
version: 2.00_16
|
||||
SOAP::WSDL::XSD::Typelib::Element:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/Element.pm
|
||||
SOAP::WSDL::XSD::Typelib::SimpleType:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm
|
||||
SOAP::WSDL::XSD::Typelib::SimpleType::restriction:
|
||||
file: lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm
|
||||
generated_by: Module::Build version 0.2808
|
||||
meta-spec:
|
||||
url: http://module-build.sourceforge.net/META-spec-v1.2.html
|
||||
version: 1.2
|
||||
|
||||
62
Makefile.PL
62
Makefile.PL
@@ -1,31 +1,31 @@
|
||||
# Note: this file was auto-generated by Module::Build::Compat version 0.03
|
||||
|
||||
unless (eval "use Module::Build::Compat 0.02; 1" ) {
|
||||
print "This module requires Module::Build to install itself.\n";
|
||||
|
||||
require ExtUtils::MakeMaker;
|
||||
my $yn = ExtUtils::MakeMaker::prompt
|
||||
(' Install Module::Build now from CPAN?', 'y');
|
||||
|
||||
unless ($yn =~ /^y/i) {
|
||||
die " *** Cannot install without Module::Build. Exiting ...\n";
|
||||
}
|
||||
|
||||
require Cwd;
|
||||
require File::Spec;
|
||||
require CPAN;
|
||||
|
||||
# Save this 'cause CPAN will chdir all over the place.
|
||||
my $cwd = Cwd::cwd();
|
||||
|
||||
CPAN::Shell->install('Module::Build::Compat');
|
||||
CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
|
||||
or die "Couldn't install Module::Build, giving up.\n";
|
||||
|
||||
chdir $cwd or die "Cannot chdir() back to $cwd: $!";
|
||||
}
|
||||
eval "use Module::Build::Compat 0.02; 1" or die $@;
|
||||
|
||||
Module::Build::Compat->run_build_pl(args => \@ARGV);
|
||||
require Module::Build;
|
||||
Module::Build::Compat->write_makefile(build_class => 'Module::Build');
|
||||
# Note: this file was auto-generated by Module::Build::Compat version 0.03
|
||||
|
||||
unless (eval "use Module::Build::Compat 0.02; 1" ) {
|
||||
print "This module requires Module::Build to install itself.\n";
|
||||
|
||||
require ExtUtils::MakeMaker;
|
||||
my $yn = ExtUtils::MakeMaker::prompt
|
||||
(' Install Module::Build now from CPAN?', 'y');
|
||||
|
||||
unless ($yn =~ /^y/i) {
|
||||
die " *** Cannot install without Module::Build. Exiting ...\n";
|
||||
}
|
||||
|
||||
require Cwd;
|
||||
require File::Spec;
|
||||
require CPAN;
|
||||
|
||||
# Save this 'cause CPAN will chdir all over the place.
|
||||
my $cwd = Cwd::cwd();
|
||||
|
||||
CPAN::Shell->install('Module::Build::Compat');
|
||||
CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
|
||||
or die "Couldn't install Module::Build, giving up.\n";
|
||||
|
||||
chdir $cwd or die "Cannot chdir() back to $cwd: $!";
|
||||
}
|
||||
eval "use Module::Build::Compat 0.02; 1" or die $@;
|
||||
|
||||
Module::Build::Compat->run_build_pl(args => \@ARGV);
|
||||
require Module::Build;
|
||||
Module::Build::Compat->write_makefile(build_class => 'Module::Build');
|
||||
|
||||
11
TEST_COVERAGE
Normal file
11
TEST_COVERAGE
Normal file
@@ -0,0 +1,11 @@
|
||||
# Unfortunately, Build testcover reports test coverage wrong.
|
||||
#
|
||||
# To get a complete coverage report, just run this file as a shell script
|
||||
# on a linux box (or execute the equivalent commands on another OS):
|
||||
|
||||
cd t/
|
||||
|
||||
find . -type f -name '*.t' | xargs -n 1 /usr/bin/perl -MDevel::Cover=-silent,1,-summary,0 -I../lib
|
||||
|
||||
cover -ignore_re \.t$ -ignore_re ^lib -coverage="statement" -coverage=condition -coverage=subroutine -coverage="branch"
|
||||
|
||||
27
TODO
27
TODO
@@ -2,35 +2,26 @@ TODO list for SOAP::WSDL
|
||||
|
||||
2.00 Pre-releases
|
||||
--------
|
||||
* SOAP Header support (#1764845)
|
||||
* Implement a Generator Plugin API
|
||||
|
||||
* Implement a interface similar to SOAP::Schema (#1783639)
|
||||
|
||||
* Check & probably fix simpleType support.
|
||||
The WS at http://www.webservicex.net/genericbarcode.asmx?wsdl should
|
||||
make up a good example for simpleType definitions.
|
||||
|
||||
* Remove benchmarks from test. Create benchmark/ directory to store benchmarks.
|
||||
|
||||
* write inheritance Test for all XSD::Typelib::Builtin::* classes
|
||||
|
||||
* support embedded atomic types (#1761532)
|
||||
Implement by including a second (and third and fourth)
|
||||
|
||||
package type_prefix::complex_type::element_name;
|
||||
|
||||
element package.
|
||||
Maybe even allow unlimited depth? What does the specs say?
|
||||
|
||||
2.1 release
|
||||
--------
|
||||
* Support namespaces in SOAP message payload
|
||||
|
||||
* Support the xsi:type attribute on derived types on the wire
|
||||
|
||||
* SOAP1.2 support
|
||||
|
||||
2.2 release
|
||||
--------
|
||||
* XML schema support ("minimal conformant") (#1764845)
|
||||
|
||||
* Support SOAP attachments
|
||||
|
||||
* Act as SOAP Server
|
||||
|
||||
3.0 release
|
||||
--------
|
||||
We're not thinking that far ahead right now.
|
||||
We're not thinking that far ahead right now.
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#!/usr/bin/perl -w
|
||||
%DB::packages=(SOAP::WSDL::Expat::MessageParser => 1);
|
||||
use strict;
|
||||
use warnings;
|
||||
use lib '../lib';
|
||||
use lib 'lib';
|
||||
use lib '../t/lib';
|
||||
use SOAP::WSDL::SAX::MessageHandler;
|
||||
# use SOAP::WSDL::SAX::MessageHandler;
|
||||
|
||||
use Benchmark;
|
||||
use SOAP::WSDL::Expat::MessageParser;
|
||||
use SOAP::WSDL::Expat::Message2Hash;
|
||||
use XML::Simple;
|
||||
use XML::LibXML;
|
||||
use MyComplexType;
|
||||
@@ -19,30 +21,57 @@ my $xml = q{<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-insta
|
||||
<SOAP-ENV:Body><MyAtomicComplexTypeElement xmlns="urn:Test" >
|
||||
<test>Test</test>
|
||||
<test2 >Test2</test2>
|
||||
</MyAtomicComplexTypeElement></SOAP-ENV:Body></SOAP-ENV:Envelope>};
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test2 >Test2</test2>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
<test>Test</test>
|
||||
</MyAtomicComplexTypeElement>
|
||||
</SOAP-ENV:Body></SOAP-ENV:Envelope>};
|
||||
|
||||
|
||||
my $parser = SOAP::WSDL::Expat::MessageParser->new({
|
||||
class_resolver => 'FakeResolver'
|
||||
});
|
||||
|
||||
my $hash_parser = SOAP::WSDL::Expat::Message2Hash->new();
|
||||
|
||||
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
|
||||
|
||||
my $libxml = XML::LibXML->new();
|
||||
|
||||
timethese 1000,
|
||||
my @data;
|
||||
timethese 10000,
|
||||
{
|
||||
'SOAP::WSDL' => sub { $parser->parse( $xml ) },
|
||||
#'XML::Simple (Hash)' => sub { XMLin $xml },
|
||||
'XML::LibXML (DOM)' => sub { my $dom = $libxml->parse_string( $xml ) },
|
||||
'Hash (SOAP:WSDL)' => sub { push @data, $hash_parser->parse( $xml ) },
|
||||
'XSD (SOAP::WSDL)' => sub { push @data, $parser->parse( $xml ) },
|
||||
'XML::Simple (Hash)' => sub { push @data, XMLin $xml },
|
||||
# 'XML::LibXML (DOM)' => sub { push @data, $libxml->parse_string( $xml ) },
|
||||
};
|
||||
|
||||
use Test::More tests => 1;
|
||||
is $parser->get_data(), q{<MyAtomicComplexTypeElement xmlns="urn:Test" >}
|
||||
. q{<test >Test</test><test2 >Test2</test2></MyAtomicComplexTypeElement>}
|
||||
, 'Content comparison';
|
||||
# use Test::More tests => 1;
|
||||
#is $parser->get_data(), q{<MyAtomicComplexTypeElement xmlns="urn:Test" >}
|
||||
# . q{<test >Test</test><test2 >Test2</test2></MyAtomicComplexTypeElement>}
|
||||
# , 'Content comparison';
|
||||
|
||||
$parser->class_resolver( 'FakeResolver2' );
|
||||
#$parser->class_resolver( 'FakeResolver2' );
|
||||
|
||||
|
||||
# data classes reside in t/lib/Typelib/
|
||||
|
||||
324
benchmark/smallprof.out
Normal file
324
benchmark/smallprof.out
Normal file
@@ -0,0 +1,324 @@
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 1
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 1:#!/usr/bin/perl
|
||||
0 0.00000 0.00000 2:package SOAP::WSDL::Expat::MessageParser;
|
||||
0 0.00000 0.00000 3:use strict;
|
||||
0 0.00000 0.00000 4:use warnings;
|
||||
0 0.00000 0.00000 5:use SOAP::WSDL::XSD::Typelib::Builtin;
|
||||
0 0.00000 0.00000 6:use XML::Parser::Expat;
|
||||
0 0.00000 0.00000 7:
|
||||
0 0.00000 0.00000 8:sub new {
|
||||
1 0.00000 0.00000 9: my ($class, $args) = @_;
|
||||
0 0.00000 0.00000 10: my $self = {
|
||||
0 0.00000 0.00000 11: class_resolver => $args->{
|
||||
1 0.00001 0.00000 12: strict => exists $args->{ strict } ?
|
||||
0 0.00000 0.00000 13: };
|
||||
1 0.00001 0.00000 14: bless $self, $class;
|
||||
1 0.02383 0.02000 15: return $self;
|
||||
0 0.00000 0.00000 16:}
|
||||
0 0.00000 0.00000 17:
|
||||
0 0.00000 0.00000 18:sub class_resolver {
|
||||
0 0.00000 0.00000 19: my $self = shift;
|
||||
0 0.00000 0.00000 20: $self->{ class_resolver } = shift;
|
||||
0 0.00000 0.00000 21: return;
|
||||
0 0.00000 0.00000 22:}
|
||||
0 0.00000 0.00000 23:
|
||||
0 0.00000 0.00000 24:sub _initialize {
|
||||
1000 0.00098 0.01000 25: my ($self, $parser) = @_;
|
||||
1000 0.04304 0.02000 26: $self->{ parser } = $parser;
|
||||
0 0.00000 0.00000 27:
|
||||
1000 0.00140 0.01000 28: delete $self->{ data };
|
||||
0 0.00000 0.00000 29:
|
||||
1000 0.00042 0.03000 30: my $characters;
|
||||
0 0.00000 0.00000 31: #my @characters_from = ();
|
||||
1000 0.00059 0.00000 32: my $current = undef;
|
||||
1000 0.00093 0.00000 33: my $list = []; #
|
||||
1000 0.00065 0.02000 34: my $path = []; #
|
||||
1000 0.00064 0.02000 35: my $skip = 0; #
|
||||
1000 0.00049 0.01000 36: my $current_part = q{}; # are
|
||||
0 0.00000 0.00000 37:
|
||||
1000 0.00041 0.00000 38: my $depth = 0;
|
||||
0 0.00000 0.00000 39:
|
||||
0 0.00000 0.00000 40: my %content_check = $self->{strict}
|
||||
0 0.00000 0.00000 41: ? (
|
||||
0 0.00000 0.00000 42: 0 => sub {
|
||||
1000 0.00115 0.00000 43: die "Bad top node $_[1]"
|
||||
1000 0.01666 0.03000 44: die "Bad namespace for
|
||||
0 0.00000 0.00000 45: if $_[0]-
|
||||
1000 0.00051 0.02000 46: $depth++;
|
||||
1000 0.00413 0.01000 47: return;
|
||||
0 0.00000 0.00000 48: },
|
||||
0 0.00000 0.00000 49: 1 => sub {
|
||||
1000 0.00050 0.02000 50: $depth++;
|
||||
1000 0.03690 0.04000 51: return;
|
||||
0 0.00000 0.00000 52: }
|
||||
0 0.00000 0.00000 53: )
|
||||
1000 0.01120 0.03000 54: : ();
|
||||
0 0.00000 0.00000 55:
|
||||
0 0.00000 0.00000 56: my $char_handler = sub {
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 2
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 57: # push @characters_from, $_[1] if
|
||||
80000 0.19296 1.00000 58: $characters .= $_[1] if $_[1]
|
||||
0 0.00000 0.00000 59:
|
||||
80000 0.27660 0.97000 60: return;
|
||||
1000 0.00449 0.00000 61: };
|
||||
0 0.00000 0.00000 62:
|
||||
0 0.00000 0.00000 63: # use "globals" for speed
|
||||
1000 0.00162 0.01000 64: my ($_prefix, $_method,
|
||||
0 0.00000 0.00000 65: $_class) = ();
|
||||
0 0.00000 0.00000 66:
|
||||
0 0.00000 0.00000 67: no strict qw(refs);
|
||||
0 0.00000 0.00000 68: $parser->setHandlers(
|
||||
0 0.00000 0.00000 69: Start => sub {
|
||||
0 0.00000 0.00000 70: # my ($parser, $element, %_attrs)
|
||||
0 0.00000 0.00000 71: # $depth = $parser->depth();
|
||||
0 0.00000 0.00000 72:
|
||||
0 0.00000 0.00000 73: # call methods without using
|
||||
0 0.00000 0.00000 74: # That's slightly faster than
|
||||
0 0.00000 0.00000 75: # and we don't have to pass $_[1]
|
||||
0 0.00000 0.00000 76: # Yup, that's dirty.
|
||||
28000 0.03037 0.32000 77: return &{$content_check{ $depth
|
||||
0 0.00000 0.00000 78:
|
||||
26000 0.02735 0.15000 79: push @{ $path }, $_[1]; #
|
||||
26000 0.01366 0.29000 80: return if $skip; #
|
||||
0 0.00000 0.00000 81:
|
||||
0 0.00000 0.00000 82: # resolve class of this element
|
||||
0 0.00000 0.00000 83: $_class = $self->{ class_resolver
|
||||
0 0.00000 0.00000 84: or die "Cannot resolve class
|
||||
26000 0.28196 0.56000 85: . join('/', @{ $path }) .
|
||||
0 0.00000 0.00000 86:
|
||||
26000 0.01695 0.35000 87: if ($_class eq '__SKIP__') {
|
||||
0 0.00000 0.00000 88: $skip = join('/', @{ $path
|
||||
0 0.00000 0.00000 89: $self->setHandlers( Char =>
|
||||
0 0.00000 0.00000 90: return;
|
||||
0 0.00000 0.00000 91: }
|
||||
0 0.00000 0.00000 92:
|
||||
26000 0.02064 0.35000 93: push @$list, $current; # step
|
||||
0 0.00000 0.00000 94:
|
||||
26000 0.02021 0.23000 95: $characters = q(); # empty
|
||||
0 0.00000 0.00000 96: #@characters_from = ();
|
||||
0 0.00000 0.00000 97:
|
||||
0 0.00000 0.00000 98: # Check whether we have a builtin
|
||||
0 0.00000 0.00000 99: # We could replace this with
|
||||
0 0.00000 0.00000 100: # match is a bit faster if the
|
||||
0 0.00000 0.00000 101: # if $class matches...
|
||||
26000 0.01676 0.21000 102: if (index $_class,
|
||||
0 0.00000 0.00000 103: # check wheter there is a
|
||||
0 0.00000 0.00000 104: # or a "new" method
|
||||
0 0.00000 0.00000 105: # If not, require it - all
|
||||
0 0.00000 0.00000 106: # define new()
|
||||
0 0.00000 0.00000 107: # This is not exactly the
|
||||
0 0.00000 0.00000 108: defined *{ "$_class\::new" }{
|
||||
26000 0.07804 0.33000 109: or scalar @{ *{
|
||||
0 0.00000 0.00000 110: or eval "require $_class"
|
||||
0 0.00000 0.00000 111: or die $@;
|
||||
0 0.00000 0.00000 112: }
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 3
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 113:
|
||||
26000 0.45038 0.81000 114: $current = $_class->new({
|
||||
0 0.00000 0.00000 115:
|
||||
0 0.00000 0.00000 116: # remember top level element
|
||||
0 0.00000 0.00000 117: exists $self->{ data }
|
||||
26000 0.02113 0.22000 118: or ($self->{ data } =
|
||||
26000 0.01267 0.25000 119: $depth++;
|
||||
26000 0.07978 0.40000 120: return;
|
||||
0 0.00000 0.00000 121: },
|
||||
0 0.00000 0.00000 122:
|
||||
0 0.00000 0.00000 123: Char => $char_handler,
|
||||
0 0.00000 0.00000 124:
|
||||
0 0.00000 0.00000 125: End => sub {
|
||||
0 0.00000 0.00000 126:
|
||||
28000 0.01974 0.26000 127: pop @{ $path };
|
||||
0 0.00000 0.00000 128:
|
||||
28000 0.01197 0.18000 129: if ($skip) {
|
||||
0 0.00000 0.00000 130: return if $skip ne join '/',
|
||||
0 0.00000 0.00000 131: $skip = 0;
|
||||
0 0.00000 0.00000 132: $_[0]->setHandler( Char =>
|
||||
0 0.00000 0.00000 133: return;
|
||||
0 0.00000 0.00000 134: }
|
||||
0 0.00000 0.00000 135:
|
||||
28000 0.01687 0.25000 136: $depth--;
|
||||
0 0.00000 0.00000 137:
|
||||
0 0.00000 0.00000 138: # This one easily handles ignores
|
||||
28000 0.10769 0.33000 139: return if not ref $list->[-1];
|
||||
0 0.00000 0.00000 140:
|
||||
0 0.00000 0.00000 141: # set characters in current if we
|
||||
0 0.00000 0.00000 142: # we may have characters in
|
||||
0 0.00000 0.00000 143: # too - maybe we should rely on
|
||||
0 0.00000 0.00000 144: # may get a speedup by defining a
|
||||
0 0.00000 0.00000 145: # and looking it up via exists
|
||||
0 0.00000 0.00000 146:# if ( $current-
|
||||
0 0.00000 0.00000 147:# $current->set_value(
|
||||
0 0.00000 0.00000 148:# }
|
||||
0 0.00000 0.00000 149: # currently doesn't work, as
|
||||
0 0.00000 0.00000 150: # maybe change ?
|
||||
25000 0.21156 0.56000 151: $current->set_value( $characters
|
||||
0 0.00000 0.00000 152: #$current->set_value( join
|
||||
25000 0.08260 0.32000 153: $characters = q{};
|
||||
0 0.00000 0.00000 154:# undef @characters_from;
|
||||
0 0.00000 0.00000 155: # set appropriate attribute in
|
||||
0 0.00000 0.00000 156: # multiple values must be
|
||||
0 0.00000 0.00000 157: #$_method = "add_$_localname";
|
||||
25000 0.01494 0.21000 158: $_method = "add_$_[1]";
|
||||
25000 0.55155 0.86000 159: $list->[-1]->$_method( $current
|
||||
0 0.00000 0.00000 160:
|
||||
25000 0.02121 0.14000 161: $current = pop @$list;
|
||||
25000 0.07002 0.34000 162: return;
|
||||
0 0.00000 0.00000 163: }
|
||||
1000 0.12135 0.08000 164: );
|
||||
1000 0.13602 0.11000 165: return $parser;
|
||||
0 0.00000 0.00000 166:}
|
||||
0 0.00000 0.00000 167:
|
||||
0 0.00000 0.00000 168:sub parse {
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 4
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
1000 0.00055 0.03000 169: eval {
|
||||
1000 0.07420 0.07000 170: $_[0]->_initialize(
|
||||
0 0.00000 0.00000 171: XML::Parser::Expat->new(
|
||||
0 0.00000 0.00000 172: Namespaces => 1
|
||||
0 0.00000 0.00000 173: )
|
||||
0 0.00000 0.00000 174: )->parse( $_[1] );
|
||||
1000 0.01030 0.02000 175: $_[0]->{ parser }->release();
|
||||
0 0.00000 0.00000 176: };
|
||||
1000 0.00034 0.00000 177: die $@ if $@;
|
||||
1000 2.73620 2.67000 178: return $_[0]->{ data };
|
||||
0 0.00000 0.00000 179:}
|
||||
0 0.00000 0.00000 180:
|
||||
0 0.00000 0.00000 181:sub parsefile {
|
||||
0 0.00000 0.00000 182: eval {
|
||||
0 0.00000 0.00000 183: $_[0]->_initialize(
|
||||
0 0.00000 0.00000 184: $_[0]->{ parser }->release();
|
||||
0 0.00000 0.00000 185: };
|
||||
0 0.00000 0.00000 186: die $@, $_[1] if $@;
|
||||
0 0.00000 0.00000 187: return $_[0]->{ data };
|
||||
0 0.00000 0.00000 188:}
|
||||
0 0.00000 0.00000 189:
|
||||
0 0.00000 0.00000 190:# SAX-like aliases
|
||||
0 0.00000 0.00000 191:sub parse_string;
|
||||
0 0.00000 0.00000 192:*parse_string = \&parse;
|
||||
0 0.00000 0.00000 193:
|
||||
0 0.00000 0.00000 194:sub parse_file;
|
||||
0 0.00000 0.00000 195:*parse_file = \&parsefile;
|
||||
0 0.00000 0.00000 196:
|
||||
0 0.00000 0.00000 197:sub get_data {
|
||||
0 0.00000 0.00000 198: return $_[0]->{ data };
|
||||
0 0.00000 0.00000 199:}
|
||||
0 0.00000 0.00000 200:
|
||||
0 0.00000 0.00000 201:1;
|
||||
0 0.00000 0.00000 202:
|
||||
0 0.00000 0.00000 203:=pod
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of 01_expat.t Page 5
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 1:#!/usr/bin/perl -w
|
||||
1 0.00003 0.00000 2:%DB::packages=(SOAP::WSDL::Expat::MessagePars
|
||||
0 0.00000 0.00000 3:use strict;
|
||||
0 0.00000 0.00000 4:use warnings;
|
||||
0 0.00000 0.00000 5:use lib '../lib';
|
||||
0 0.00000 0.00000 6:use lib 'lib';
|
||||
0 0.00000 0.00000 7:use lib '../t/lib';
|
||||
0 0.00000 0.00000 8:use SOAP::WSDL::SAX::MessageHandler;
|
||||
0 0.00000 0.00000 9:
|
||||
0 0.00000 0.00000 10:use Benchmark;
|
||||
0 0.00000 0.00000 11:use SOAP::WSDL::Expat::MessageParser;
|
||||
0 0.00000 0.00000 12:use SOAP::WSDL::Expat::Message2Hash;
|
||||
0 0.00000 0.00000 13:use XML::Simple;
|
||||
0 0.00000 0.00000 14:use XML::LibXML;
|
||||
0 0.00000 0.00000 15:use MyComplexType;
|
||||
0 0.00000 0.00000 16:use MyElement;
|
||||
0 0.00000 0.00000 17:use MySimpleType;
|
||||
0 0.00000 0.00000 18:
|
||||
0 0.00000 0.00000 19:my $xml = q{<SOAP-ENV:Envelope
|
||||
0 0.00000 0.00000 20: xmlns:SOAP-
|
||||
0 0.00000 0.00000 21: <SOAP-
|
||||
0 0.00000 0.00000 22: <test>Test</test>
|
||||
0 0.00000 0.00000 23: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 24: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 25: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 26: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 27: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 28: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 29: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 30: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 31: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 32: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 33: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 34: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 35: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 36: <test>Test</test>
|
||||
0 0.00000 0.00000 37: <test>Test</test>
|
||||
0 0.00000 0.00000 38: <test>Test</test>
|
||||
0 0.00000 0.00000 39: <test>Test</test>
|
||||
0 0.00000 0.00000 40: <test>Test</test>
|
||||
0 0.00000 0.00000 41: <test>Test</test>
|
||||
0 0.00000 0.00000 42: <test>Test</test>
|
||||
0 0.00000 0.00000 43: <test>Test</test>
|
||||
0 0.00000 0.00000 44: <test>Test</test>
|
||||
0 0.00000 0.00000 45: <test>Test</test>
|
||||
0 0.00000 0.00000 46: <test>Test</test>
|
||||
0 0.00000 0.00000 47: </MyAtomicComplexTypeElement>
|
||||
0 0.00000 0.00000 48:</SOAP-ENV:Body></SOAP-ENV:Envelope>};
|
||||
0 0.00000 0.00000 49:
|
||||
0 0.00000 0.00000 50:
|
||||
0 0.00000 0.00000 51:my $parser =
|
||||
0 0.00000 0.00000 52: class_resolver => 'FakeResolver'
|
||||
0 0.00000 0.00000 53:});
|
||||
0 0.00000 0.00000 54:
|
||||
0 0.00000 0.00000 55:my $hash_parser =
|
||||
0 0.00000 0.00000 56:
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of 01_expat.t Page 6
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 57:$XML::Simple::PREFERRED_PARSER =
|
||||
0 0.00000 0.00000 58:
|
||||
0 0.00000 0.00000 59:my $libxml = XML::LibXML->new();
|
||||
0 0.00000 0.00000 60:my @data;
|
||||
0 0.00000 0.00000 61:timethese 1000,
|
||||
0 0.00000 0.00000 62:{
|
||||
0 0.00000 0.00000 63: # 'Hash (SOAP:WSDL)' => sub { push @data,
|
||||
0 0.00000 0.00000 64: 'SOAP::WSDL' => sub { push @data, $parser-
|
||||
0 0.00000 0.00000 65:# 'XML::Simple (Hash)' => sub { push @data,
|
||||
0 0.00000 0.00000 66:# 'XML::LibXML (DOM)' => sub { push @data,
|
||||
0 0.00000 0.00000 67:};
|
||||
0 0.00000 0.00000 68:
|
||||
0 0.00000 0.00000 69:# use Test::More tests => 1;
|
||||
0 0.00000 0.00000 70:#is $parser->get_data(),
|
||||
0 0.00000 0.00000 71:# . q{<test >Test</test><test2
|
||||
0 0.00000 0.00000 72:# , 'Content comparison';
|
||||
0 0.00000 0.00000 73:
|
||||
0 0.00000 0.00000 74:#$parser->class_resolver( 'FakeResolver2' );
|
||||
0 0.00000 0.00000 75:
|
||||
0 0.00000 0.00000 76:
|
||||
0 0.00000 0.00000 77:# data classes reside in t/lib/Typelib/
|
||||
0 0.00000 0.00000 78:BEGIN {
|
||||
0 0.00000 0.00000 79: package FakeResolver;
|
||||
0 0.00000 0.00000 80: {
|
||||
0 0.00000 0.00000 81: my %class_list = (
|
||||
0 0.00000 0.00000 82: 'MyAtomicComplexTypeElement' =>
|
||||
0 0.00000 0.00000 83: 'MyAtomicComplexTypeElement/test'
|
||||
0 0.00000 0.00000 84:
|
||||
0 0.00000 0.00000 85: );
|
||||
0 0.00000 0.00000 86:
|
||||
0 0.00000 0.00000 87: sub get_map { return \%class_list };
|
||||
0 0.00000 0.00000 88:
|
||||
0 0.00000 0.00000 89: sub new { return bless {},
|
||||
0 0.00000 0.00000 90:
|
||||
0 0.00000 0.00000 91: sub get_class {
|
||||
0 0.00000 0.00000 92: my $name = join('/', @{ $_[1] });
|
||||
0 0.00000 0.00000 93: return ($class_list{ $name }) ?
|
||||
0 0.00000 0.00000 94: : warn "no class found for
|
||||
0 0.00000 0.00000 95: };
|
||||
0 0.00000 0.00000 96: };
|
||||
0 0.00000 0.00000 97:};
|
||||
315
benchmark/smallprof.out-whitespace
Normal file
315
benchmark/smallprof.out-whitespace
Normal file
@@ -0,0 +1,315 @@
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 1
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 1:#!/usr/bin/perl
|
||||
0 0.00000 0.00000 2:package SOAP::WSDL::Expat::MessageParser;
|
||||
0 0.00000 0.00000 3:use strict;
|
||||
0 0.00000 0.00000 4:use warnings;
|
||||
0 0.00000 0.00000 5:use SOAP::WSDL::XSD::Typelib::Builtin;
|
||||
0 0.00000 0.00000 6:use XML::Parser::Expat;
|
||||
0 0.00000 0.00000 7:
|
||||
0 0.00000 0.00000 8:sub new {
|
||||
1 0.00000 0.00000 9: my ($class, $args) = @_;
|
||||
0 0.00000 0.00000 10: my $self = {
|
||||
0 0.00000 0.00000 11: class_resolver => $args->{
|
||||
1 0.00001 0.00000 12: strict => exists $args->{ strict } ?
|
||||
0 0.00000 0.00000 13: };
|
||||
1 0.00001 0.00000 14: bless $self, $class;
|
||||
1 0.02309 0.03000 15: return $self;
|
||||
0 0.00000 0.00000 16:}
|
||||
0 0.00000 0.00000 17:
|
||||
0 0.00000 0.00000 18:sub class_resolver {
|
||||
1 0.00000 0.00000 19: my $self = shift;
|
||||
1 2.74336 2.69000 20: $self->{ class_resolver } = shift;
|
||||
0 0.00000 0.00000 21:}
|
||||
0 0.00000 0.00000 22:
|
||||
0 0.00000 0.00000 23:sub _initialize {
|
||||
1000 0.00163 0.01000 24: my ($self, $parser) = @_;
|
||||
1000 0.03682 0.05000 25: $self->{ parser } = $parser;
|
||||
0 0.00000 0.00000 26:
|
||||
1000 0.00138 0.01000 27: delete $self->{ data };
|
||||
0 0.00000 0.00000 28:
|
||||
1000 0.00048 0.01000 29: my $characters;
|
||||
1000 0.00091 0.00000 30: my $current = undef;
|
||||
1000 0.00097 0.01000 31: my $list = []; #
|
||||
1000 0.00107 0.01000 32: my $path = []; #
|
||||
1000 0.00054 0.01000 33: my $skip = 0; #
|
||||
1000 0.00053 0.01000 34: my $current_part = q{}; # are
|
||||
0 0.00000 0.00000 35:
|
||||
1000 0.00041 0.02000 36: my $depth = 0;
|
||||
0 0.00000 0.00000 37:
|
||||
0 0.00000 0.00000 38: my %content_check = $self->{strict}
|
||||
0 0.00000 0.00000 39: ? (
|
||||
0 0.00000 0.00000 40: 0 => sub {
|
||||
1000 0.00097 0.02000 41: die "Bad top node $_[1]"
|
||||
1000 0.01651 0.00000 42: die "Bad namespace for
|
||||
0 0.00000 0.00000 43: if $_[0]-
|
||||
1000 0.00068 0.00000 44: $depth++;
|
||||
1000 0.00441 0.02000 45: return;
|
||||
0 0.00000 0.00000 46: },
|
||||
0 0.00000 0.00000 47: 1 => sub {
|
||||
1000 0.00369 0.02000 48: die "Bad node $_[1].
|
||||
1000 0.00060 0.00000 49: $depth++;
|
||||
1000 0.03693 0.03000 50: return;
|
||||
0 0.00000 0.00000 51: }
|
||||
0 0.00000 0.00000 52: )
|
||||
1000 0.01252 0.01000 53: : ();
|
||||
0 0.00000 0.00000 54:
|
||||
0 0.00000 0.00000 55: # use "globals" for speed
|
||||
1000 0.00095 0.01000 56: my ($_prefix, $_method,
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 2
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 57: $_class) = ();
|
||||
0 0.00000 0.00000 58:
|
||||
0 0.00000 0.00000 59: no strict qw(refs);
|
||||
0 0.00000 0.00000 60: $parser->setHandlers(
|
||||
0 0.00000 0.00000 61: Start => sub {
|
||||
0 0.00000 0.00000 62: # my ($parser, $element, %_attrs)
|
||||
0 0.00000 0.00000 63: # $depth = $parser->depth();
|
||||
0 0.00000 0.00000 64:
|
||||
0 0.00000 0.00000 65: # call methods without using
|
||||
0 0.00000 0.00000 66: # That's slightly faster than
|
||||
0 0.00000 0.00000 67: # and we don't have to pass $_[1]
|
||||
0 0.00000 0.00000 68: # Yup, that's dirty.
|
||||
28000 0.03090 0.31000 69: return &{$content_check{ $depth
|
||||
0 0.00000 0.00000 70:
|
||||
26000 0.03309 0.32000 71: push @{ $path }, $_[1]; #
|
||||
26000 0.01337 0.21000 72: return if $skip; #
|
||||
0 0.00000 0.00000 73:
|
||||
0 0.00000 0.00000 74: # resolve class of this element
|
||||
0 0.00000 0.00000 75: $_class = $self->{ class_resolver
|
||||
0 0.00000 0.00000 76: or die "Cannot resolve class
|
||||
26000 0.28467 0.53000 77: . join('/', @{ $path }) .
|
||||
0 0.00000 0.00000 78:
|
||||
0 0.00000 0.00000 79: # maybe write as "return $skip =
|
||||
0 0.00000 0.00000 80: # would save a BLOCK...
|
||||
26000 0.03919 0.30000 81: return $skip = join('/', @{ $path
|
||||
0 0.00000 0.00000 82:
|
||||
26000 0.05079 0.22000 83: push @$list, $current; # step
|
||||
0 0.00000 0.00000 84:
|
||||
26000 0.07934 0.26000 85: $characters = q(); # empty
|
||||
0 0.00000 0.00000 86:
|
||||
0 0.00000 0.00000 87: # Check whether we have a builtin
|
||||
0 0.00000 0.00000 88: # We could replace this with
|
||||
0 0.00000 0.00000 89: # match is a bit faster if the
|
||||
0 0.00000 0.00000 90: # if $class matches...
|
||||
26000 0.01981 0.22000 91: if (index $_class,
|
||||
0 0.00000 0.00000 92: # check wheter there is a
|
||||
0 0.00000 0.00000 93: # or a "new" method
|
||||
0 0.00000 0.00000 94: # If not, require it - all
|
||||
0 0.00000 0.00000 95: # define new()
|
||||
0 0.00000 0.00000 96: # This is not exactly the
|
||||
0 0.00000 0.00000 97: defined *{ "$_class\::new" }{
|
||||
26000 0.08308 0.26000 98: or scalar @{ *{
|
||||
0 0.00000 0.00000 99: or eval "require $_class"
|
||||
0 0.00000 0.00000 100: or die $@;
|
||||
0 0.00000 0.00000 101: }
|
||||
0 0.00000 0.00000 102:
|
||||
26000 0.45611 0.64000 103: $current = $_class->new({
|
||||
0 0.00000 0.00000 104:
|
||||
0 0.00000 0.00000 105: # remember top level element
|
||||
0 0.00000 0.00000 106: exists $self->{ data }
|
||||
26000 0.02518 0.26000 107: or ($self->{ data } =
|
||||
26000 0.01496 0.32000 108: $depth++;
|
||||
26000 0.07949 0.39000 109: return;
|
||||
0 0.00000 0.00000 110: },
|
||||
0 0.00000 0.00000 111:
|
||||
0 0.00000 0.00000 112: Char => sub {
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 3
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
80000 0.05801 0.73000 113: return if $skip;
|
||||
80000 0.38097 1.05000 114: return if $_[1] =~m{ \A \s* \z
|
||||
25000 0.01804 0.24000 115: $characters .= $_[1];
|
||||
25000 0.07404 0.32000 116: return;
|
||||
0 0.00000 0.00000 117: },
|
||||
0 0.00000 0.00000 118:
|
||||
0 0.00000 0.00000 119: End => sub {
|
||||
0 0.00000 0.00000 120:
|
||||
28000 0.02209 0.25000 121: pop @{ $path };
|
||||
0 0.00000 0.00000 122:
|
||||
28000 0.01658 0.29000 123: if ($skip) {
|
||||
0 0.00000 0.00000 124: return if $skip ne join '/',
|
||||
0 0.00000 0.00000 125: $skip = 0;
|
||||
0 0.00000 0.00000 126: return;
|
||||
0 0.00000 0.00000 127: }
|
||||
0 0.00000 0.00000 128:
|
||||
28000 0.01628 0.26000 129: $depth--;
|
||||
0 0.00000 0.00000 130:
|
||||
0 0.00000 0.00000 131: # This one easily handles ignores
|
||||
28000 0.11185 0.27000 132: return if not ref $list->[-1];
|
||||
0 0.00000 0.00000 133:
|
||||
0 0.00000 0.00000 134: # set characters in current if we
|
||||
0 0.00000 0.00000 135: # we may have characters in
|
||||
0 0.00000 0.00000 136: # too - maybe we should rely on
|
||||
0 0.00000 0.00000 137: # may get a speedup by defining a
|
||||
0 0.00000 0.00000 138: # and looking it up via exists
|
||||
0 0.00000 0.00000 139:# if ( $current-
|
||||
0 0.00000 0.00000 140:# $current->set_value(
|
||||
0 0.00000 0.00000 141:# }
|
||||
0 0.00000 0.00000 142: # currently doesn't work, as
|
||||
0 0.00000 0.00000 143: # maybe change ?
|
||||
25000 0.28121 0.53000 144: $current->set_value( $characters
|
||||
25000 0.01730 0.20000 145: $characters = q{};
|
||||
0 0.00000 0.00000 146: # set appropriate attribute in
|
||||
0 0.00000 0.00000 147: # multiple values must be
|
||||
0 0.00000 0.00000 148: #$_method = "add_$_localname";
|
||||
25000 0.01976 0.23000 149: $_method = "add_$_[1]";
|
||||
25000 0.55083 0.85000 150: $list->[-1]->$_method( $current
|
||||
0 0.00000 0.00000 151:
|
||||
25000 0.02277 0.25000 152: $current = pop @$list;
|
||||
25000 0.06949 0.36000 153: return;
|
||||
0 0.00000 0.00000 154: }
|
||||
1000 0.12369 0.12000 155: );
|
||||
1000 0.13620 0.08000 156: return $parser;
|
||||
0 0.00000 0.00000 157:}
|
||||
0 0.00000 0.00000 158:
|
||||
0 0.00000 0.00000 159:sub parse {
|
||||
1000 0.00065 0.02000 160: eval {
|
||||
1000 0.07514 0.09000 161: $_[0]->_initialize(
|
||||
0 0.00000 0.00000 162: XML::Parser::Expat->new(
|
||||
0 0.00000 0.00000 163: Namespaces => 1
|
||||
0 0.00000 0.00000 164: )
|
||||
0 0.00000 0.00000 165: )->parse( $_[1] );
|
||||
1000 0.01077 0.02000 166: $_[0]->{ parser }->release();
|
||||
0 0.00000 0.00000 167: };
|
||||
1000 0.00051 0.00000 168: die $@ if $@;
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of ../lib/SOAP/WSDL/Expat/MessageParser.pm Page 4
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
1000 0.01431 0.04000 169: return $_[0]->{ data };
|
||||
0 0.00000 0.00000 170:}
|
||||
0 0.00000 0.00000 171:
|
||||
0 0.00000 0.00000 172:sub parsefile {
|
||||
0 0.00000 0.00000 173: eval {
|
||||
0 0.00000 0.00000 174: $_[0]->_initialize(
|
||||
0 0.00000 0.00000 175: $_[0]->{ parser }->release();
|
||||
0 0.00000 0.00000 176: };
|
||||
0 0.00000 0.00000 177: die $@, $_[1] if $@;
|
||||
0 0.00000 0.00000 178: return $_[0]->{ data };
|
||||
0 0.00000 0.00000 179:}
|
||||
0 0.00000 0.00000 180:
|
||||
0 0.00000 0.00000 181:# SAX-like aliases
|
||||
0 0.00000 0.00000 182:sub parse_string;
|
||||
0 0.00000 0.00000 183:*parse_string = \&parse;
|
||||
0 0.00000 0.00000 184:
|
||||
0 0.00000 0.00000 185:sub parse_file;
|
||||
0 0.00000 0.00000 186:*parse_file = \&parsefile;
|
||||
0 0.00000 0.00000 187:
|
||||
0 0.00000 0.00000 188:sub get_data {
|
||||
0 0.00000 0.00000 189: return $_[0]->{ data };
|
||||
0 0.00000 0.00000 190:}
|
||||
0 0.00000 0.00000 191:
|
||||
0 0.00000 0.00000 192:1;
|
||||
0 0.00000 0.00000 193:
|
||||
0 0.00000 0.00000 194:=pod
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of 01_expat.t Page 5
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 1:#!/usr/bin/perl -w
|
||||
1 0.00002 0.00000 2:%DB::packages=(SOAP::WSDL::Expat::MessagePars
|
||||
0 0.00000 0.00000 3:use strict;
|
||||
0 0.00000 0.00000 4:use warnings;
|
||||
0 0.00000 0.00000 5:use lib '../lib';
|
||||
0 0.00000 0.00000 6:use lib 'lib';
|
||||
0 0.00000 0.00000 7:use lib '../t/lib';
|
||||
0 0.00000 0.00000 8:use SOAP::WSDL::SAX::MessageHandler;
|
||||
0 0.00000 0.00000 9:
|
||||
0 0.00000 0.00000 10:use Benchmark;
|
||||
0 0.00000 0.00000 11:use SOAP::WSDL::Expat::MessageParser;
|
||||
0 0.00000 0.00000 12:use SOAP::WSDL::Expat::Message2Hash;
|
||||
0 0.00000 0.00000 13:use XML::Simple;
|
||||
0 0.00000 0.00000 14:use XML::LibXML;
|
||||
0 0.00000 0.00000 15:use MyComplexType;
|
||||
0 0.00000 0.00000 16:use MyElement;
|
||||
0 0.00000 0.00000 17:use MySimpleType;
|
||||
0 0.00000 0.00000 18:
|
||||
0 0.00000 0.00000 19:my $xml = q{<SOAP-ENV:Envelope
|
||||
0 0.00000 0.00000 20: xmlns:SOAP-
|
||||
0 0.00000 0.00000 21: <SOAP-
|
||||
0 0.00000 0.00000 22: <test>Test</test>
|
||||
0 0.00000 0.00000 23: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 24: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 25: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 26: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 27: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 28: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 29: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 30: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 31: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 32: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 33: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 34: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 35: <test2 >Test2</test2>
|
||||
0 0.00000 0.00000 36: <test>Test</test>
|
||||
0 0.00000 0.00000 37: <test>Test</test>
|
||||
0 0.00000 0.00000 38: <test>Test</test>
|
||||
0 0.00000 0.00000 39: <test>Test</test>
|
||||
0 0.00000 0.00000 40: <test>Test</test>
|
||||
0 0.00000 0.00000 41: <test>Test</test>
|
||||
0 0.00000 0.00000 42: <test>Test</test>
|
||||
0 0.00000 0.00000 43: <test>Test</test>
|
||||
0 0.00000 0.00000 44: <test>Test</test>
|
||||
0 0.00000 0.00000 45: <test>Test</test>
|
||||
0 0.00000 0.00000 46: <test>Test</test>
|
||||
0 0.00000 0.00000 47: </MyAtomicComplexTypeElement>
|
||||
0 0.00000 0.00000 48:</SOAP-ENV:Body></SOAP-ENV:Envelope>};
|
||||
0 0.00000 0.00000 49:
|
||||
0 0.00000 0.00000 50:
|
||||
0 0.00000 0.00000 51:my $parser =
|
||||
0 0.00000 0.00000 52: class_resolver => 'FakeResolver'
|
||||
0 0.00000 0.00000 53:});
|
||||
0 0.00000 0.00000 54:
|
||||
0 0.00000 0.00000 55:my $hash_parser =
|
||||
0 0.00000 0.00000 56:
|
||||
================ SmallProf version 2.02 ================
|
||||
Profile of 01_expat.t Page 6
|
||||
=================================================================
|
||||
count wall tm cpu time line
|
||||
0 0.00000 0.00000 57:$XML::Simple::PREFERRED_PARSER =
|
||||
0 0.00000 0.00000 58:
|
||||
0 0.00000 0.00000 59:my $libxml = XML::LibXML->new();
|
||||
0 0.00000 0.00000 60:my @data;
|
||||
0 0.00000 0.00000 61:timethese 1000,
|
||||
0 0.00000 0.00000 62:{
|
||||
0 0.00000 0.00000 63:# 'SOAP::WSDL Hash' => sub { push @data,
|
||||
0 0.00000 0.00000 64: 'SOAP::WSDL' => sub { push @data, $parser-
|
||||
0 0.00000 0.00000 65:# 'XML::Simple (Hash)' => sub { push @data,
|
||||
0 0.00000 0.00000 66:# 'XML::LibXML (DOM)' => sub { push @data,
|
||||
0 0.00000 0.00000 67:};
|
||||
0 0.00000 0.00000 68:
|
||||
0 0.00000 0.00000 69:# use Test::More tests => 1;
|
||||
0 0.00000 0.00000 70:#is $parser->get_data(),
|
||||
0 0.00000 0.00000 71:# . q{<test >Test</test><test2
|
||||
0 0.00000 0.00000 72:# , 'Content comparison';
|
||||
0 0.00000 0.00000 73:
|
||||
0 0.00000 0.00000 74:$parser->class_resolver( 'FakeResolver2' );
|
||||
0 0.00000 0.00000 75:
|
||||
0 0.00000 0.00000 76:
|
||||
0 0.00000 0.00000 77:# data classes reside in t/lib/Typelib/
|
||||
0 0.00000 0.00000 78:BEGIN {
|
||||
0 0.00000 0.00000 79: package FakeResolver;
|
||||
0 0.00000 0.00000 80: {
|
||||
0 0.00000 0.00000 81: my %class_list = (
|
||||
0 0.00000 0.00000 82: 'MyAtomicComplexTypeElement' =>
|
||||
0 0.00000 0.00000 83: 'MyAtomicComplexTypeElement/test'
|
||||
0 0.00000 0.00000 84:
|
||||
0 0.00000 0.00000 85: );
|
||||
0 0.00000 0.00000 86:
|
||||
0 0.00000 0.00000 87: sub get_map { return \%class_list };
|
||||
0 0.00000 0.00000 88:
|
||||
0 0.00000 0.00000 89: sub new { return bless {},
|
||||
0 0.00000 0.00000 90:
|
||||
0 0.00000 0.00000 91: sub get_class {
|
||||
0 0.00000 0.00000 92: my $name = join('/', @{ $_[1] });
|
||||
0 0.00000 0.00000 93: return ($class_list{ $name }) ?
|
||||
0 0.00000 0.00000 94: : warn "no class found for
|
||||
0 0.00000 0.00000 95: };
|
||||
0 0.00000 0.00000 96: };
|
||||
0 0.00000 0.00000 97:};
|
||||
130
bin/wsdl2perl.pl
130
bin/wsdl2perl.pl
@@ -5,29 +5,58 @@ use Pod::Usage;
|
||||
use Getopt::Long;
|
||||
use LWP::UserAgent;
|
||||
use SOAP::WSDL::Expat::WSDLParser;
|
||||
use SOAP::WSDL::Generator::Template::XSD;
|
||||
use Term::ReadKey;
|
||||
|
||||
my %opt = (
|
||||
url => '',
|
||||
prefix => undef,
|
||||
type_prefix => 'MyTypes::',
|
||||
element_prefix => 'MyElements::',
|
||||
typemap_prefix => 'MyTypemaps::',
|
||||
interface_prefix => 'MyInterfaces::',
|
||||
type_prefix => 'MyTypes',
|
||||
element_prefix => 'MyElements',
|
||||
typemap_prefix => 'MyTypemaps',
|
||||
interface_prefix => 'MyInterfaces',
|
||||
base_path => 'lib/',
|
||||
proxy => undef
|
||||
);
|
||||
|
||||
{ # a block just to scope "no warnings"
|
||||
no warnings qw(redefine);
|
||||
|
||||
*LWP::UserAgent::get_basic_credentials = sub {
|
||||
my ($user, $password);
|
||||
# remove user from option if called, to force prompting for a user
|
||||
# name the next time
|
||||
print "URL requires authorization.\n";
|
||||
if (not $user = delete $opt{user}) {
|
||||
print 'User name:';
|
||||
ReadMode 1;
|
||||
$user = ReadLine();
|
||||
ReadMode 0;
|
||||
};
|
||||
if (not $password = delete $opt{password}) {
|
||||
print 'Password:';
|
||||
ReadMode 2;
|
||||
$user = ReadLine;
|
||||
ReadMode 0;
|
||||
};
|
||||
return ($user, $password);
|
||||
};
|
||||
}
|
||||
|
||||
GetOptions(\%opt,
|
||||
qw(
|
||||
url|u=s
|
||||
prefix|p=s
|
||||
type_prefix|t=s
|
||||
element_prefix|e=s
|
||||
typemap_prefix|m=s
|
||||
interface_prefix|i=s
|
||||
base_path|b=s
|
||||
typemap_include|mi=s
|
||||
help|h
|
||||
proxy|x=s
|
||||
keep_alive
|
||||
user=s
|
||||
password=s
|
||||
)
|
||||
);
|
||||
|
||||
@@ -39,23 +68,43 @@ pod2usage( -exit => 1 , verbose => 1 ) if not ($url);
|
||||
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
|
||||
|
||||
local $ENV{HTTP_PROXY} = $opt{proxy} if $opt{proxy};
|
||||
my $lwp = LWP::UserAgent->new();
|
||||
local $ENV{HTTPS_PROXY} = $opt{proxy} if $opt{proxy};
|
||||
|
||||
my $lwp = LWP::UserAgent->new(
|
||||
$opt{keep_alive}
|
||||
? ( keep_alive => 1 )
|
||||
: ()
|
||||
);
|
||||
$lwp->env_proxy(); # get proxy from environment. Works for both http & https.
|
||||
|
||||
my $response = $lwp->get($url);
|
||||
die $response->message(), "\n" if $response->code != 200;
|
||||
|
||||
my $xml = $response->content();
|
||||
|
||||
my $wsdl = $parser->parse_string( $xml );
|
||||
my $definitions = $parser->parse_string( $xml );
|
||||
|
||||
my %typemap = ();
|
||||
|
||||
if ($opt{typemap_include}) {
|
||||
open my $fh , $opt{typemap_include}
|
||||
or die "cannot open typemap_include file $opt{typemap_include}\n";
|
||||
$opt{custom_types} .= join q{}, <$fh>;
|
||||
close $fh;
|
||||
delete $opt{typemap_include};
|
||||
die "$opt{typemap_include} not found " if not -f $opt{typemap_include};
|
||||
%typemap = do $opt{typemap_include};
|
||||
}
|
||||
|
||||
$wsdl->create({ %opt });
|
||||
my $generator = SOAP::WSDL::Generator::Template::XSD->new({
|
||||
type_prefix => $opt{ type_prefix },
|
||||
typemap_prefix => $opt{ typemap_prefix },
|
||||
element_prefix => $opt{ element_prefix },
|
||||
interface_prefix => $opt{ interface_prefix },
|
||||
OUTPUT_PATH => $opt{ base_path },
|
||||
definitions => $definitions,
|
||||
});
|
||||
|
||||
# start with typelib, as errors will most likely occur here...
|
||||
$generator->generate_typelib();
|
||||
$generator->generate_interface();
|
||||
$generator->generate_typemap({ (%typemap) ? (typemap => \%typemap) : () });
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
@@ -73,17 +122,24 @@ wsdl2perl.pl - create perl bindings for SOAP webservices.
|
||||
NAME SHORT DESCRITPION
|
||||
----------------------------------------------------------------------------
|
||||
prefix p Prefix for both type and element classes.
|
||||
type_prefix t Prefix for type classes. Should end with '::'
|
||||
Default: MyTypes::
|
||||
element_prefix e Prefix for element classes. Should end with '::'
|
||||
Default: MyElements::
|
||||
typemap_prefix m Prefix for typemap classes. Should end with '::'
|
||||
Default: MyTypemaps::
|
||||
interface_prefix i Prefix for interface classes. Should end with '::'
|
||||
Default: MyInterfaces::
|
||||
type_prefix t Prefix for type classes.
|
||||
Default: MyTypes
|
||||
element_prefix e Prefix for element classes.
|
||||
Default: MyElements
|
||||
typemap_prefix m Prefix for typemap classes.
|
||||
Default: MyTypemaps
|
||||
interface_prefix i Prefix for interface classes.
|
||||
Default: MyInterfaces
|
||||
base_path b Path to create classes in.
|
||||
Default: ./lib
|
||||
typemap_include mi File to include in typemap.
|
||||
Default: .
|
||||
typemap_include mi File to include in typemap. Must eval() to a valid
|
||||
perl hash (not a has ref !).
|
||||
proxy x HTTP(S) proxy to use (if any). wsdl2perl will also
|
||||
use the proxy settings specified via the HTTP_PROXY
|
||||
and HTTPS_PROXY environment variables.
|
||||
keep_alive Use http keep_alive.
|
||||
user Username for HTTP authentication
|
||||
password Password. wsdl2perl will prompt if not given.
|
||||
help h Show help content
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@@ -95,7 +151,7 @@ The following classes are created:
|
||||
|
||||
=over
|
||||
|
||||
=item * A interface class for every service
|
||||
=item * A interface class for every SOAP port in service
|
||||
|
||||
Interface classes are what you will mainly deal with: They provide a method
|
||||
for accessing every web service method.
|
||||
@@ -116,10 +172,34 @@ typemap_include (mi) option.
|
||||
You may need to write additional type classes if your WSDL is incomplete.
|
||||
|
||||
For writing your own lib classes, see L<SOAP::WSDL::XSD::Typelib::Element>,
|
||||
L<SOAP::WSDL::XSD::Typelib::ComplexType> and L<SOAP::WSDL::XSD::Typelib::SimpleType>.
|
||||
L<SOAP::WSDL::XSD::Typelib::ComplexType>
|
||||
and L<SOAP::WSDL::XSD::Typelib::SimpleType>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 TROUBLESHOOTING
|
||||
|
||||
=head2 Accessing HTTPS URLs
|
||||
|
||||
You need Crypt::SSLeay installed for accessing HTTPS URLs.
|
||||
|
||||
=head2 Accessing protected documents
|
||||
|
||||
Use the -u option for specifying the user name. You will be prompted for a
|
||||
password.
|
||||
|
||||
Alternatively, you may specify a passowrd with --password on the command
|
||||
line.
|
||||
|
||||
=head2 Accessing documents protected by NTLM authentication
|
||||
|
||||
Set the --keep_alive option.
|
||||
|
||||
Note that accessing documents protected by NTLM authentication is currently
|
||||
untested, because I have no access to a system using NTLM authentication.
|
||||
If you try it, I would be glad if you could just drop me a note about
|
||||
success or failure.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2007 Martin Kutter.
|
||||
|
||||
26
example/visitor/visitor.pl
Normal file
26
example/visitor/visitor.pl
Normal file
@@ -0,0 +1,26 @@
|
||||
package PersonVisitor;
|
||||
use Class::Std; # handles all basic stuff like constructors etc.
|
||||
|
||||
sub visit_Person {
|
||||
my ( $self, $object ) = @_;
|
||||
print "Person name is ", $object->get_name(), "\n";
|
||||
}
|
||||
|
||||
package Person;
|
||||
use Class::Std;
|
||||
my %name : ATTR(:name<name> :default<anonymous>);
|
||||
|
||||
sub accept { $_[1]->visit_Person( $_[0] ) }
|
||||
|
||||
package main;
|
||||
my @person_from = ();
|
||||
for (qw(Gamma Helm Johnson Vlissides)) {
|
||||
push @person_from, Person->new( { name => $_ } );
|
||||
}
|
||||
|
||||
my $visitor = PersonVisitor->new();
|
||||
for (@person_from) {
|
||||
$_->accept($visitor);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
use lib 'lib/';
|
||||
use MyInterfaces::GlobalWeather;
|
||||
my $weather = MyInterfaces::GlobalWeather->new();
|
||||
my $weather = MyInterfaces::GlobalWeather->new({ no_dispatch => 1 });
|
||||
my $result = $weather->GetWeather({ CountryName => 'Germany', CityName => 'Munich' });
|
||||
|
||||
print $result;
|
||||
# boolean comparison overloaded
|
||||
die $result->get_faultstring()->get_value() if not ($result);
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@ print $som->result();
|
||||
# Note that you have to look both the proxy and the xmlns attribute
|
||||
# set on the GetWeather SOAP::Data object from the WSDL.
|
||||
|
||||
use SOAP::Lite; # +trace;
|
||||
my $soap = SOAP::Lite->new()->on_action( sub { join'/', @_ } )
|
||||
use SOAP::Lite +trace;
|
||||
$soap = SOAP::Lite->new()->on_action( sub { join'/', @_ } )
|
||||
->proxy("http://www.webservicex.net/globalweather.asmx"); # from WSDL
|
||||
my $som = $soap->call(
|
||||
$som = $soap->call(
|
||||
SOAP::Data->name('GetWeather')
|
||||
->attr({ xmlns => 'http://www.webserviceX.NET' }), # from WSDL
|
||||
SOAP::Data->name('CountryName')->value('Germany'),
|
||||
|
||||
171
lib/SOAP/WSDL.pm
171
lib/SOAP/WSDL.pm
@@ -10,12 +10,11 @@ use Class::Std;
|
||||
use SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType;
|
||||
use LWP::UserAgent;
|
||||
|
||||
our $VERSION='2.00_13';
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %no_dispatch_of :ATTR(:name<no_dispatch>);
|
||||
my %wsdl_of :ATTR(:name<wsdl>);
|
||||
my %proxy_of :ATTR(:name<proxy>);
|
||||
my %readable_of :ATTR(:name<readable>);
|
||||
my %autotype_of :ATTR(:name<autotype>);
|
||||
my %outputxml_of :ATTR(:name<outputxml> :default<0>);
|
||||
my %outputtree_of :ATTR(:name<outputtree>);
|
||||
@@ -31,24 +30,33 @@ my %binding_of :ATTR(:default<()>);
|
||||
my %service_of :ATTR(:default<()>);
|
||||
my %definitions_of :ATTR(:get<definitions> :default<()>);
|
||||
my %serialize_options_of :ATTR(:default<()>);
|
||||
my %explain_options_of :ATTR(:default<()>);
|
||||
|
||||
my %client_of :ATTR(:name<client> :default<()>);
|
||||
my %keep_alive_of :ATTR(:name<keep_alive> :default<0> );
|
||||
|
||||
my %LOOKUP = (
|
||||
no_dispatch => \%no_dispatch_of,
|
||||
class_resolver => \%class_resolver_of,
|
||||
wsdl => \%wsdl_of,
|
||||
proxy => \%proxy_of,
|
||||
readable => \%readable_of,
|
||||
autotype => \%autotype_of,
|
||||
outputxml => \%outputxml_of,
|
||||
outputtree => \%outputtree_of,
|
||||
outputhash => \%outputhash_of,
|
||||
portname => \%portname_of,
|
||||
servicename => \%servicename_of,
|
||||
keep_alive => \%keep_alive_of,
|
||||
);
|
||||
|
||||
sub readable { warn <<EOT;
|
||||
'readable' has no effect any more. If you want formatted XML,
|
||||
copy the debug output to your favorite XML editor and run the
|
||||
source format command.
|
||||
EOT
|
||||
}
|
||||
|
||||
sub set_readable; *set_readable = \&readable;
|
||||
|
||||
for my $method (keys %LOOKUP ) {
|
||||
no strict qw(refs);
|
||||
*{ $method } = sub {
|
||||
@@ -62,10 +70,12 @@ for my $method (keys %LOOKUP ) {
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
{ # just a BLOCK for scoping warnings.
|
||||
|
||||
# we need to roll our own for supporting
|
||||
# SOAP::WSDL->new( key => value ) syntax,
|
||||
# like SOAP::Lite does
|
||||
# like SOAP::Lite does. Class::Std enforces a single hash ref as
|
||||
# parameters to new()
|
||||
no warnings qw(redefine);
|
||||
sub new {
|
||||
my $class = shift;
|
||||
@@ -92,16 +102,20 @@ sub wsdlinit {
|
||||
my $ident = ident $self;
|
||||
my %opt = @_;
|
||||
|
||||
my $lwp = LWP::UserAgent->new();
|
||||
my $lwp = LWP::UserAgent->new(
|
||||
$keep_alive_of{ $ident }
|
||||
? (keep_alive => 1)
|
||||
: ()
|
||||
);
|
||||
my $response = $lwp->get( $wsdl_of{ $ident } );
|
||||
croak $response->message() if ($response->code != 200);
|
||||
|
||||
# TODO: Port parser to expat and remove XML::LibXML dependency
|
||||
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
|
||||
$parser->parse_string( $response->content() );
|
||||
|
||||
my $wsdl_definitions = $parser->get_data();
|
||||
|
||||
# sanity checks
|
||||
my $wsdl_definitions = $parser->get_data() or die "unable to parse WSDL";
|
||||
my $types = $wsdl_definitions->first_types()
|
||||
or die "unable to extract schema from WSDL";
|
||||
my $ns = $wsdl_definitions->get_xmlns()
|
||||
@@ -115,12 +129,6 @@ sub wsdlinit {
|
||||
typelib => $types,
|
||||
namespace => $ns,
|
||||
};
|
||||
$explain_options_of{ $ident } = {
|
||||
readable => $self->readable(),
|
||||
wsdl => $wsdl_definitions,
|
||||
namespace => $ns,
|
||||
typelib => $types,
|
||||
};
|
||||
|
||||
$servicename_of{ $ident } = $opt{servicename} if $opt{servicename};
|
||||
$portname_of{ $ident } = $opt{portname} if $opt{portname};
|
||||
@@ -149,7 +157,7 @@ sub _wsdl_get_binding :PRIVATE {
|
||||
my $ident = ident $self;
|
||||
my $wsdl = $definitions_of{ $ident };
|
||||
my $port = $port_of{ $ident } || $self->_wsdl_get_port();
|
||||
$binding_of{ $ident } = $wsdl->find_binding( $wsdl->_expand( $port->get_binding() ) )
|
||||
$binding_of{ $ident } = $wsdl->find_binding( $port->expand( $port->get_binding() ) )
|
||||
or die "no binding found for ", $port->get_binding();
|
||||
return $binding_of{ $ident };
|
||||
}
|
||||
@@ -159,7 +167,7 @@ sub _wsdl_get_portType :PRIVATE {
|
||||
my $ident = ident $self;
|
||||
my $wsdl = $definitions_of{ $ident };
|
||||
my $binding = $binding_of{ $ident } || $self->_wsdl_get_binding();
|
||||
$porttype_of{ $ident } = $wsdl->find_portType( $wsdl->_expand( $binding->get_type() ) )
|
||||
$porttype_of{ $ident } = $wsdl->find_portType( $binding->expand( $binding->get_type() ) )
|
||||
or die "cannot find portType for " . $binding->get_type();
|
||||
return $porttype_of{ $ident };
|
||||
}
|
||||
@@ -200,15 +208,29 @@ sub _wsdl_init_methods :PRIVATE {
|
||||
# 3. get input message
|
||||
my $message = $wsdl->find_message( $ns, $localname )
|
||||
or die "Message {$ns}$localname not found in WSDL definition";
|
||||
|
||||
if (my $body=$binding_operation->first_input()->first_body()) {
|
||||
if ($body->get_parts()) {
|
||||
$method->{ parts } = []; # make sure it's empty
|
||||
my $message_part_ref = $message->get_part();
|
||||
for my $name (split m{\s} , $body->get_parts() ) {
|
||||
$name =~s{ \A [^:]+: }{}x; # throw away ns prefix
|
||||
# could probably made more efficient, but our lists are
|
||||
# usually quite short
|
||||
push @{ $method->{ parts } },
|
||||
grep { $_->get_name() eq $name } @{ $message_part_ref };
|
||||
}
|
||||
}
|
||||
}
|
||||
$method->{ parts } ||= $message->get_part();
|
||||
|
||||
$method->{ parts } = $message->get_part();
|
||||
|
||||
# rpc / encoded methods may have a namespace specified.
|
||||
# look it up and set it...
|
||||
$method->{ namespace } = $binding_operation
|
||||
? do {
|
||||
my $input = $binding_operation->first_input();
|
||||
$input ? $input->get_namespace() : undef;
|
||||
$input ? $input->first_body()->get_namespace() : undef;
|
||||
}
|
||||
: undef;
|
||||
|
||||
@@ -232,16 +254,23 @@ sub call {
|
||||
$self->_wsdl_init_methods() if not ($method_info_of{ $ident });
|
||||
|
||||
my $client = $client_of{ $ident };
|
||||
$client->set_proxy( $proxy_of{ $ident } || $port_of{ $ident }->get_location() );
|
||||
|
||||
# pass-through keep_alive if we need it...
|
||||
$client->set_proxy( $proxy_of{ $ident }
|
||||
|| $port_of{ $ident }->first_address()->get_location(),
|
||||
$keep_alive_of{ $ident } ? (keep_alive => 1) : (),
|
||||
);
|
||||
|
||||
$client->set_no_dispatch( $no_dispatch_of{ $ident } );
|
||||
|
||||
$client->set_outputxml( $outputxml_of{ $ident } ? 1 : 0 );
|
||||
|
||||
# only load ::Deserializer::SOM if we really need to deserialize to SOM.
|
||||
# maybe we should introduce something like $output{ $ident } with a fixed
|
||||
# set of values - m{^(TREE|HASH|XML|SOM)$}xms ?
|
||||
if ( ( ! $outputtree_of{ $ident } )
|
||||
&& ( ! $outputhash_of{ $ident } )
|
||||
&& ( ! $outputxml_of{ $ident } ) ) {
|
||||
&& ( ! $outputxml_of{ $ident } )
|
||||
&& ( ! $no_dispatch_of{ $ident } ) ) {
|
||||
require SOAP::WSDL::Deserializer::SOM;
|
||||
$client->set_deserializer( SOAP::WSDL::Deserializer::SOM->new() );
|
||||
};
|
||||
@@ -249,7 +278,7 @@ sub call {
|
||||
my $method_info = $method_info_of{ $ident }->{ $method };
|
||||
|
||||
# TODO serialize both header and body, not only header
|
||||
my $response = (blessed $data)
|
||||
my (@response) = (blessed $data)
|
||||
? $client->call( {
|
||||
operation => $method,
|
||||
soap_action => $method_info->{ soap_action },
|
||||
@@ -261,7 +290,6 @@ sub call {
|
||||
$content .= $part->serialize( $method, $data,
|
||||
{
|
||||
%{ $serialize_options_of{ $ident } },
|
||||
readable => $readable_of{ $ident },
|
||||
} );
|
||||
}
|
||||
$client->call(
|
||||
@@ -280,14 +308,8 @@ sub call {
|
||||
);
|
||||
};
|
||||
|
||||
return unless defined $response; # nothing to do for one-ways
|
||||
return $response;
|
||||
}
|
||||
|
||||
sub explain {
|
||||
my $ident = ident shift;
|
||||
my $opt = $explain_options_of{ $ident };
|
||||
return $definitions_of{ $ident }->explain( $opt );
|
||||
return unless @response; # nothing to do for one-ways
|
||||
return wantarray ? @response : $response[0];
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -312,7 +334,6 @@ SOAP client, which mimics L<SOAP::Lite|SOAP::Lite>'s API, read on.
|
||||
|
||||
my $soap = SOAP::WSDL->new(
|
||||
wsdl => 'file://bla.wsdl',
|
||||
readable => 1,
|
||||
);
|
||||
|
||||
my $result = $soap->call('MyMethod', %data);
|
||||
@@ -356,6 +377,13 @@ Does not support SOAP header data.
|
||||
Does support SOAP header data. $body_ref and $header ref may either be
|
||||
hash refs or SOAP::WSDL::XSD::Typelib::* derived objects.
|
||||
|
||||
Result headers are accessible via the result SOAP::SOM object.
|
||||
|
||||
If outputtree or outputhash are set, you may also use the following to
|
||||
access response header data:
|
||||
|
||||
my ($body, $header) = $soap->call('method', $body_ref, $header_ref );
|
||||
|
||||
=back
|
||||
|
||||
=head2 wsdlinit
|
||||
@@ -384,7 +412,7 @@ When outputtree is set, SOAP::WSDL will return an object tree instead of a
|
||||
SOAP::SOM object.
|
||||
|
||||
You have to specify a class_resolver for this to work. See
|
||||
<class_resolver|class_resolver>
|
||||
L<class_resolver|class_resolver>
|
||||
|
||||
=head2 class_resolver
|
||||
|
||||
@@ -394,8 +422,8 @@ Class resolvers must implement the method get_class which has to return the
|
||||
name of the class name for deserializing a XML node at the current XPath
|
||||
location.
|
||||
|
||||
Class resolvers are typically generated by using the to_typemap method on a
|
||||
SOAP::WSDL::Definitions objects.
|
||||
Class resolvers are typically generated by using the generate_typemap method
|
||||
of a SOAP::WSDL::Generator subclass.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -455,15 +483,6 @@ SOAP call to the SOAP service. Handy for testing/debugging.
|
||||
Returns the SOAP client implementation used (normally a SOAP::WSDL::Client
|
||||
object).
|
||||
|
||||
Useful for enabling tracing:
|
||||
|
||||
# enable tracing via 'warn'
|
||||
$soap->get_client->set_trace(1);
|
||||
|
||||
# enable tracing via a custom facility -
|
||||
# Log::Log4perl in this case...
|
||||
$soap->get_client->set_trace(sub { Log::Log4perl->get_logger->info(@_) } );
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
See the examples/ directory.
|
||||
@@ -476,7 +495,7 @@ See the examples/ directory.
|
||||
|
||||
SOAP::WSDL 2 is a complete rewrite. While SOAP::WSDL 1.x attempted to
|
||||
process the WSDL file on the fly by using XPath queries, SOAP:WSDL 2 uses a
|
||||
SAX filter for parsing the WSDL and building up a object tree representing
|
||||
Expat handler for parsing the WSDL and building up a object tree representing
|
||||
it's content.
|
||||
|
||||
The object tree has two main functions: It knows how to serialize data passed
|
||||
@@ -487,12 +506,12 @@ L<SOAP::WSDL::Manual> for using it.
|
||||
|
||||
=item * no_dispatch
|
||||
|
||||
call() with outputtxml set to true now returns the complete SOAP
|
||||
call() with no_dispatch set to true now returns the complete SOAP request
|
||||
envelope, not only the body's content.
|
||||
|
||||
=item * outputxml
|
||||
|
||||
call() with outputxml set to true now returns the complete SOAP
|
||||
call() with outputxml set to true now returns the complete SOAP response
|
||||
envelope, not only the body's content.
|
||||
|
||||
=item * servicename/portname
|
||||
@@ -505,6 +524,14 @@ You may pass the servicename and portname as attributes to wsdlinit, though.
|
||||
|
||||
=head1 Differences to SOAP::Lite
|
||||
|
||||
=head2 readable
|
||||
|
||||
readable is a no-op in SOAP::WSDL. Actually, the XML output from SOAP::Lite
|
||||
is hardly readable, either with readable switched on.
|
||||
|
||||
If you need readable XML messages, I suggest using your favorite XML editor
|
||||
for displaying and formatting.
|
||||
|
||||
=head2 Message style/encoding
|
||||
|
||||
While SOAP::Lite supports rpc/encoded style/encoding only, SOAP::WSDL currently
|
||||
@@ -549,7 +576,7 @@ See below.
|
||||
SOAP::Lite returns only the content of the SOAP body when outputxml is set
|
||||
to true. SOAP::WSDL returns the complete XML response.
|
||||
|
||||
=head3 Auto-Dispatching
|
||||
=head2 Auto-Dispatching
|
||||
|
||||
SOAP::WSDL does B<does not> support auto-dispatching.
|
||||
|
||||
@@ -564,7 +591,7 @@ SOAP::WSDL::Client and implementing something like
|
||||
You may even do this in a class factory - see L<wsdl2perl.pl> for creating
|
||||
such interfaces.
|
||||
|
||||
=head3 Debugging / Tracing
|
||||
=head2 Debugging / Tracing
|
||||
|
||||
While SOAP::Lite features a global tracing facility, SOAP::WSDL
|
||||
allows to switch tracing on/of on a per-object base.
|
||||
@@ -577,29 +604,30 @@ details.
|
||||
|
||||
=over
|
||||
|
||||
=item * SOAP Headers are not supported
|
||||
|
||||
There's no way to use SOAP Headers with SOAP::WSDL yet.
|
||||
|
||||
=item * Apache SOAP datatypes are not supported
|
||||
|
||||
You currently can't use SOAP::WSDL with Apache SOAP datatypes like map.
|
||||
|
||||
If you want this changed, email me a copy of the specs, please.
|
||||
|
||||
=item * outputhash
|
||||
=item * Incomplete XML Schema definitions support
|
||||
|
||||
outputhash is not implemented yet.
|
||||
XML Schema attribute definitions are not supported yet.
|
||||
|
||||
=item * Unsupported XML Schema definitions
|
||||
Importing external definitions is not supported yet.
|
||||
|
||||
The following XML Schema definitions are not supported:
|
||||
The following XML Schema definitions varieties are not supported:
|
||||
|
||||
choice
|
||||
group
|
||||
union
|
||||
simpleContent
|
||||
complexContent
|
||||
|
||||
The following XML Schema definition content model is only partially
|
||||
supported:
|
||||
|
||||
complexContent - only restriction variety supported
|
||||
|
||||
See L<SOAP::WSDL::Manual::XSD> for details.
|
||||
|
||||
=item * Serialization of hash refs dos not work for ambiguos values
|
||||
|
||||
@@ -674,18 +702,21 @@ L<http://www.cpanforum.com/dist/SOAP-WSDL>
|
||||
There are many people out there who fostered SOAP::WSDL's developement.
|
||||
I would like to thank them all (and apologize to all those I have forgotten).
|
||||
|
||||
Giovanni S. Fois wrote a improved version of SOAP::WSDL (which eventually became v1.23)
|
||||
Giovanni S. Fois wrote a improved version of SOAP::WSDL (which eventually
|
||||
became v1.23)
|
||||
|
||||
Damian A. Martinez Gelabert, Dennis S. Hennen, Dan Horne, Peter Orvos, Mark Overmeer,
|
||||
Jon Robens, Isidro Vila Verde and Glenn Wood spotted bugs and/or
|
||||
suggested improvements in the 1.2x releases.
|
||||
David Bussenschutt, Damian A. Martinez Gelabert, Dennis S. Hennen, Dan Horne,
|
||||
Peter Orvos, Mark Overmeer, Jon Robens, Isidro Vila Verde and Glenn Wood
|
||||
spotted bugs and/or suggested improvements in the 1.2x releases.
|
||||
|
||||
Andreas 'ACID' Specht constantly asked for better performance.
|
||||
Andreas 'ac0v' Specht constantly asked for better performance.
|
||||
|
||||
JT Justman provided some early feedback for the 2.xx pre-releases.
|
||||
|
||||
Numerous people sent me their real-world WSDL files for testing. Thank you.
|
||||
|
||||
Paul Kulchenko and Byrne Reese wrote and maintained SOAP::Lite and thus provided a
|
||||
base (and counterpart) for SOAP::WSDL.
|
||||
Paul Kulchenko and Byrne Reese wrote and maintained SOAP::Lite and
|
||||
thus provided a base (and counterpart) for SOAP::WSDL.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
@@ -700,10 +731,10 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$Rev: 308 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: WSDL.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL.pm $
|
||||
$Id: WSDL.pm 308 2007-10-05 17:35:28Z kutterma $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL.pm $
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package SOAP::WSDL::Base;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
use Class::Std::Storable;
|
||||
use List::Util qw(first);
|
||||
use Carp qw(confess);
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %id_of :ATTR(:name<id> :default<()>);
|
||||
my %name_of :ATTR(:name<name> :default<()>);
|
||||
@@ -23,6 +25,16 @@ sub STORABLE_freeze_post :CUMULATIVE {};
|
||||
sub STORABLE_thaw_pre :CUMULATIVE {};
|
||||
sub STORABLE_thaw_post :CUMULATIVE { return $_[0] };
|
||||
|
||||
sub _accept {
|
||||
my $self = shift;
|
||||
my $class = ref $self;
|
||||
$class =~ s{ \A SOAP::WSDL:: }{}xms;
|
||||
$class =~ s{ (:? :: ) }{_}gxms;
|
||||
my $method = "visit_$class";
|
||||
no strict qw(refs);
|
||||
shift->$method( $self );
|
||||
}
|
||||
|
||||
# unfortunately, AUTOMETHOD is SLOW.
|
||||
# Re-implement in derived package wherever speed is an issue...
|
||||
#
|
||||
@@ -39,8 +51,6 @@ sub AUTOMETHOD {
|
||||
## And we would have to check getters, too.
|
||||
## Maybe do it the Conway way via the Symbol table...
|
||||
## ... can is way slow...
|
||||
# croak "no set accessor found for push_$subname"
|
||||
# if not ($self->can( $setter ));
|
||||
return sub {
|
||||
no strict qw(refs);
|
||||
my $old_value = $self->$getter();
|
||||
@@ -54,6 +64,7 @@ sub AUTOMETHOD {
|
||||
|
||||
# we're called as $obj->find_something($ns, $key)
|
||||
elsif ($subname =~s {^find_}{get_}xms) {
|
||||
@values = @{ $values[0] } if ref $values[0] eq 'ARRAY';
|
||||
return sub {
|
||||
return first {
|
||||
$_->get_targetNamespace() eq $values[0] &&
|
||||
@@ -70,7 +81,7 @@ sub AUTOMETHOD {
|
||||
return $result_ref->[0];
|
||||
};
|
||||
}
|
||||
croak "$subname not found in class " . (ref $self || $self);
|
||||
confess "$subname not found in class " . (ref $self || $self) ;
|
||||
}
|
||||
|
||||
sub init {
|
||||
@@ -94,80 +105,26 @@ sub init {
|
||||
# TODO handle xmlns correctly - maybe via setting a prefix ?
|
||||
next;
|
||||
}
|
||||
my $name = $value->{ LocalName };
|
||||
my $method = "set_$name";
|
||||
$self->$method( $value->{ Value } ) if ( $method );
|
||||
|
||||
my $name = $value->{ LocalName };
|
||||
my $method = "set_$name";
|
||||
$self->$method( $value->{ Value } );
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub add_namespace {
|
||||
my ($self, $uri, $prefix ) = @_;
|
||||
return unless $uri;
|
||||
$self->{ namespace } ||= {};
|
||||
$self->{ namespace }->{ $uri } = $prefix;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
warn "to_typemap";
|
||||
return q{};
|
||||
}
|
||||
|
||||
sub toClass {
|
||||
my $self = shift;
|
||||
warn 'toClass is deprecated and will be removed before reaching 2.01 - '
|
||||
. 'use to_class instead (' . caller() . ')';
|
||||
$self->to_class(@_);
|
||||
}
|
||||
|
||||
sub to_class {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $template = shift;
|
||||
|
||||
$opt->{ base_path } ||= '.';
|
||||
|
||||
my $element_prefix = $opt->{ element_prefix } || $opt->{ prefix };
|
||||
my $type_prefix = $opt->{ type_prefix } || $opt->{ prefix };
|
||||
sub expand {
|
||||
my ($self, , $qname) = @_;
|
||||
my ($prefix, $localname) = split /:/, $qname;
|
||||
my %ns_map = reverse %{ $self->get_xmlns() };
|
||||
return ($ns_map{ $prefix }, $localname) if ($ns_map{ $prefix });
|
||||
|
||||
if (($type_prefix) && ($type_prefix !~m{ :: $ }xms ) ) {
|
||||
warn 'type_prefix should end with "::"';
|
||||
$type_prefix .= '::';
|
||||
if (my $parent = $self->get_parent()) {
|
||||
return $parent->expand($qname);
|
||||
}
|
||||
|
||||
if (($element_prefix) && ($element_prefix !~m{ :: $ }xms) ) {
|
||||
warn 'element_prefix should end with "::"';
|
||||
$element_prefix .= '::';
|
||||
}
|
||||
|
||||
# Be careful: a Element may be ComplexType, too
|
||||
# (but not vice versa)
|
||||
my $prefix = $self->isa('SOAP::WSDL::XSD::Element')
|
||||
? $element_prefix
|
||||
: $type_prefix;
|
||||
|
||||
die 'No prefix specified' if not $prefix;
|
||||
|
||||
my $filename = $prefix . $self->get_name() . '.pm';
|
||||
$filename =~s{::}{/}xmsg;
|
||||
|
||||
my $output = $opt->{ output } || $filename;
|
||||
|
||||
require Template;
|
||||
my $tt = Template->new(
|
||||
RELATIVE => 1,
|
||||
OUTPUT_PATH => $opt->{ base_path },
|
||||
);
|
||||
|
||||
my $code = $tt->process( \$template, {
|
||||
element_prefix => $element_prefix,
|
||||
type_prefix => $type_prefix,
|
||||
self => $self,
|
||||
nsmap => { reverse %{ $opt->{ wsdl }->get_xmlns() } },
|
||||
structure => $self->explain( { wsdl => $opt->{ wsdl } } ),
|
||||
},
|
||||
$output
|
||||
)
|
||||
or die $tt->error();
|
||||
confess "unbound prefix $prefix found for $prefix:$localname";
|
||||
}
|
||||
sub _expand;
|
||||
*_expand = \&expand;
|
||||
|
||||
1;
|
||||
|
||||
@@ -10,106 +10,4 @@ my %type_of :ATTR(:name<type> :default<()>);
|
||||
my %transport_of :ATTR(:name<transport> :default<()>);
|
||||
my %style_of :ATTR(:name<style> :default<()>);
|
||||
|
||||
|
||||
sub explain {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $name = $self->get_name();
|
||||
|
||||
die 'required atribute wsdl missing' if not $opt->{ wsdl };
|
||||
|
||||
my $portType = $opt->{ wsdl }->find_portType(
|
||||
$opt->{ wsdl }->_expand( $self->get_type() )
|
||||
) or die 'portType not found: ' . $self->get_type();
|
||||
|
||||
my $txt = <<"EOT";
|
||||
|
||||
=head2 SOAP Operations
|
||||
|
||||
B<Note:>
|
||||
|
||||
Input, output and fault messages are stated as perl hash refs.
|
||||
|
||||
These are only for informational purposes - the actual implementation
|
||||
normally uses object trees, not hash refs, though the input messages
|
||||
may be passed to the respective methods as hash refs and will be
|
||||
converted to object trees automatically.
|
||||
|
||||
EOT
|
||||
|
||||
foreach my $operation (@{ $self->get_operation() }) {
|
||||
|
||||
my $operation_name = $operation->get_name();
|
||||
my $operation_style = $operation->get_style() || q{};
|
||||
|
||||
my $port_operation = first { $_->get_name eq $operation_name }
|
||||
@{ $portType->get_operation() }
|
||||
or die "operation not found:" . $operation->get_name();
|
||||
|
||||
# TODO rename lexical $input to "message"
|
||||
my $input_message = do {
|
||||
my $input = $port_operation->first_input();
|
||||
$input ? $input->explain($opt) : q{};
|
||||
};
|
||||
my $output_message = do {
|
||||
my $input = $port_operation->first_output();
|
||||
$input ? $input->explain($opt) : q{};
|
||||
};
|
||||
my $fault_message = do {
|
||||
my $input = $port_operation->first_fault();
|
||||
$input ? $input->explain($opt) : q{};
|
||||
};
|
||||
|
||||
$txt .= <<"EOT";
|
||||
|
||||
=head3 $operation_name
|
||||
|
||||
B<Input Message:>
|
||||
|
||||
$input_message
|
||||
|
||||
B<Output Message:>
|
||||
|
||||
$output_message
|
||||
|
||||
B<Fault:>
|
||||
|
||||
$fault_message
|
||||
|
||||
EOT
|
||||
}
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
my ($self, $opt) = @_;
|
||||
my $name = $self->get_name();
|
||||
|
||||
my $portType = $opt->{ wsdl }->find_portType(
|
||||
$opt->{ wsdl }->_expand( $self->get_type )
|
||||
) or die 'portType not found: ' . $self->get_type;
|
||||
|
||||
my $txt = q{};
|
||||
foreach my $operation (@{ $self->get_operation() })
|
||||
{
|
||||
my $operation_name = $operation->get_name();
|
||||
my $operation_style = $operation->get_style() || q{};
|
||||
|
||||
my ($port_operation) = grep { $_->get_name eq $operation_name }
|
||||
@{ $portType->get_operation() }
|
||||
or die "operation not found:" . $operation->get_name();
|
||||
|
||||
no strict qw(refs);
|
||||
$txt .= join q{},
|
||||
map {
|
||||
my $message = $port_operation->$_;
|
||||
$message
|
||||
? $message->to_typemap($opt)
|
||||
: q{}
|
||||
} qw(first_input first_output first_fault);
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -4,8 +4,6 @@ use warnings;
|
||||
use Carp;
|
||||
|
||||
use Class::Std::Storable;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Request;
|
||||
use Scalar::Util qw(blessed);
|
||||
|
||||
use SOAP::WSDL::Factory::Deserializer;
|
||||
@@ -13,11 +11,7 @@ use SOAP::WSDL::Factory::Serializer;
|
||||
use SOAP::WSDL::Factory::Transport;
|
||||
use SOAP::WSDL::Expat::MessageParser;
|
||||
|
||||
our $VERSION='2.00_13';
|
||||
|
||||
# Package global for speed and memory savings.
|
||||
# But should be factored out into serializer/deserializer...
|
||||
my $PARSER;
|
||||
our $VERSION = '2.00_17';
|
||||
|
||||
my %class_resolver_of :ATTR(:name<class_resolver> :default<()>);
|
||||
my %no_dispatch_of :ATTR(:name<no_dispatch> :default<()>);
|
||||
@@ -27,16 +21,11 @@ my %endpoint_of :ATTR(:name<endpoint> :default<()>);
|
||||
|
||||
my %soap_version_of :ATTR(:get<soap_version> :init_attr<soap_version> :default<'1.1'>);
|
||||
|
||||
my %trace_of :ATTR(:set<trace> :init_arg<trace> :default<()> );
|
||||
my %on_action_of :ATTR(:name<on_action> :default<()>);
|
||||
my %content_type_of :ATTR(:name<content_type> :default<text/xml; charset=utf8>); #/#trick editors
|
||||
my %serializer_of :ATTR(:name<serializer> :default<()>);
|
||||
my %deserializer_of :ATTR(:name<deserializer> :default<()>);
|
||||
|
||||
# TODO remove when preparing 2.01
|
||||
sub outputtree { warn 'outputtree is deprecated and'
|
||||
. 'will be removed before reaching v2.01 !' }
|
||||
|
||||
sub BUILD {
|
||||
my ($self, $ident, $attrs_of_ref) = @_;
|
||||
|
||||
@@ -47,15 +36,6 @@ sub BUILD {
|
||||
|
||||
}
|
||||
|
||||
sub get_trace {
|
||||
my $ident = ident $_[0];
|
||||
return $trace_of{ $ident }
|
||||
? ref $trace_of{ $ident } eq 'CODE'
|
||||
? $trace_of{ $ident }
|
||||
: sub { warn @_ }
|
||||
: ()
|
||||
}
|
||||
|
||||
sub get_proxy {
|
||||
return $_[0]->get_transport();
|
||||
}
|
||||
@@ -90,7 +70,6 @@ sub set_soap_version {
|
||||
# serializer object
|
||||
delete $serializer_of{ $ident };
|
||||
delete $deserializer_of{ $ident };
|
||||
delete $transport_of{ $ident };
|
||||
|
||||
$soap_version_of{ $ident } = shift;
|
||||
|
||||
@@ -169,10 +148,7 @@ sub call {
|
||||
content_type => $content_type_of{ $ident },
|
||||
envelope => $envelope,
|
||||
action => $soap_action,
|
||||
on_receive_chunk => sub {} # optional, may be used for parsing large responses as they arrive.
|
||||
# might not be supported by all transport layers...
|
||||
# and, of course, only is of interest for chunk parsers -
|
||||
# namely ExpatNB and XML::LibXML's Push parser interface...
|
||||
# on_receive_chunk => sub {} # optional, may be used for parsing large responses as they arrive.
|
||||
);
|
||||
|
||||
return $response if ($outputxml_of{ $ident } );
|
||||
@@ -183,16 +159,20 @@ sub call {
|
||||
});
|
||||
|
||||
# set class resolver if serializer supports it
|
||||
$deserializer_of{ $ident }->class_resolver( $class_resolver_of{ $ident } )
|
||||
if ( $deserializer_of{ $ident }->can('class_resolver') );
|
||||
|
||||
my $result;
|
||||
$deserializer_of{ $ident }->set_class_resolver( $class_resolver_of{ $ident } )
|
||||
if ( $deserializer_of{ $ident }->can('set_class_resolver') );
|
||||
|
||||
# Try deserializing response - there may be some,
|
||||
# even if transport did not succeed (got a 500 response)
|
||||
if ( $response ) {
|
||||
eval { $result = $deserializer_of{ $ident }->deserialize( $response ); };
|
||||
return $result if (not $@);
|
||||
my ($result_body, $result_header) = eval {
|
||||
$deserializer_of{ $ident }->deserialize( $response );
|
||||
};
|
||||
if (not $@) {
|
||||
return wantarray
|
||||
? ($result_body, $result_header)
|
||||
: $result_body;
|
||||
}
|
||||
return $deserializer_of{ $ident }->generate_fault({
|
||||
code => 'soap:Server',
|
||||
role => 'urn:localhost',
|
||||
@@ -218,6 +198,8 @@ sub call {
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
@@ -357,12 +339,18 @@ SOAP::WSDL::Client and implementing something like
|
||||
You may even do this in a class factory - see L<wsdl2perl.pl> for creating
|
||||
such interfaces.
|
||||
|
||||
=head3 Debugging / Tracing
|
||||
=head1 Troubleshooting
|
||||
|
||||
While SOAP::Lite features a global tracing facility, SOAP::WSDL::Client
|
||||
allows to switch tracing on/of on a per-object base.
|
||||
=head2 Accessing protected web services
|
||||
|
||||
See L<set_trace|set_trace> on how to enable tracing.
|
||||
Accessing protected web services is very specific for the transport
|
||||
backend used.
|
||||
|
||||
In general, you may pass additional arguments to the set_proxy method (or
|
||||
a list ref of the web service address and any additional arguments to the
|
||||
new method's I<proxy> argument).
|
||||
|
||||
Refer to the appropriate transport module for documentation.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
@@ -377,10 +365,10 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$Rev: 303 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: Client.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client.pm $
|
||||
$Id: Client.pm 303 2007-10-01 18:51:50Z kutterma $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client.pm $
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -2,29 +2,52 @@ package SOAP::WSDL::Client::Base;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'SOAP::WSDL::Client';
|
||||
use Scalar::Util qw(blessed);
|
||||
|
||||
sub __create_new {
|
||||
my ($package, %args_of) = @_;
|
||||
|
||||
no strict qw(refs);
|
||||
|
||||
*{ "$package\::new" } = sub {
|
||||
my $class = shift;
|
||||
my $self = $class->SUPER::new({
|
||||
proxy => $args_of{ proxy },
|
||||
class_resolver => $args_of{ class_resolver }
|
||||
});
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
our $VERSION = '2.00_17';
|
||||
|
||||
sub call {
|
||||
my ($self, $method, $body, $header) = @_;
|
||||
if (not blessed $body) {
|
||||
my $class = $method->{ body }->{ parts }->[0];
|
||||
eval "require $class" || die $@;
|
||||
$body = $class->new($body);
|
||||
}
|
||||
|
||||
# if we have a header
|
||||
if (%{ $method->{ header } }) {
|
||||
if (not blessed $header) {
|
||||
my $class = $method->{ header }->{ parts }->[0];
|
||||
eval "require $class" || die $@;
|
||||
$header = $class->new($header);
|
||||
}
|
||||
}
|
||||
return $self->SUPER::call($method, $body, $header);
|
||||
}
|
||||
|
||||
#sub __create_new {
|
||||
# my ($package, %args_of) = @_;
|
||||
#
|
||||
# no strict qw(refs);
|
||||
# no warnings qw(redefine);
|
||||
#
|
||||
# # TODO factor out and replace by generated START method
|
||||
# *{ "$package\::new" } = sub {
|
||||
# my $class = shift;
|
||||
# my $self = $class->SUPER::new({
|
||||
# proxy => $args_of{ proxy },
|
||||
# class_resolver => $args_of{ class_resolver }
|
||||
# });
|
||||
# bless $self, $class;
|
||||
# return $self;
|
||||
# }
|
||||
#}
|
||||
|
||||
sub __create_methods {
|
||||
my ($package, %info_of) = @_;
|
||||
|
||||
no strict qw(refs);
|
||||
|
||||
no warnings qw(redefine);
|
||||
for my $method (keys %info_of){
|
||||
my ($soap_action, @parts);
|
||||
|
||||
@@ -93,9 +116,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 214 $
|
||||
$Rev: 303 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: Base.pm 214 2007-09-10 15:54:52Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client/Base.pm $
|
||||
$Id: Base.pm 303 2007-10-01 18:51:50Z kutterma $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client/Base.pm $
|
||||
|
||||
=cut
|
||||
|
||||
@@ -9,6 +9,8 @@ use List::Util qw(first);
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %types_of :ATTR(:name<types> :default<[]>);
|
||||
my %message_of :ATTR(:name<message> :default<()>);
|
||||
my %portType_of :ATTR(:name<portType> :default<()>);
|
||||
@@ -32,286 +34,24 @@ BLOCK: {
|
||||
foreach my $method(keys %attributes_of ) {
|
||||
|
||||
*{ "find_$method" } = sub {
|
||||
my ($self, @args) = @_;
|
||||
my ($self, @args_from) = @_;
|
||||
@args_from = @{ $args_from[0] } if ref $args_from[0] eq 'ARRAY';
|
||||
return first {
|
||||
$_->get_targetNamespace() eq $args[0]
|
||||
&& $_->get_name() eq $args[1]
|
||||
$_->get_targetNamespace() eq $args_from[0]
|
||||
&& $_->get_name() eq $args_from[1]
|
||||
}
|
||||
@{ $attributes_of{ $method }->{ ident $self } };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sub explain {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
$opt->{ wsdl } ||= $self;
|
||||
$opt->{ namespace } ||= $self->get_xmlns() || {};
|
||||
my $txt = '';
|
||||
|
||||
for my $service (@{ $self->get_service() }) {
|
||||
$txt .= $service->explain( $opt ) . "\n";
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
|
||||
sub _expand {
|
||||
my ($self, $prefix, $localname) = ($_[0], split /:/, $_[1]);
|
||||
my %ns_map = reverse %{ $self->get_xmlns() };
|
||||
return ($ns_map{ $prefix }, $localname);
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
$opt->{ prefix } ||= q{};
|
||||
$opt->{ wsdl } ||= $self;
|
||||
$opt->{ type_prefix } ||= $opt->{ prefix };
|
||||
$opt->{ element_prefix } ||= $opt->{ prefix };
|
||||
return join "\n",
|
||||
map { $_->to_typemap( $opt ) } @{ $service_of{ ident $self } };
|
||||
}
|
||||
|
||||
sub create {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
|
||||
my $base_path = $opt->{ base_path }
|
||||
or croak "missing or empty argument base_path";
|
||||
$opt->{ prefix } ||= q{};
|
||||
$opt->{ type_prefix } ||= $opt->{ prefix };
|
||||
$opt->{ element_prefix } ||= $opt->{ prefix };
|
||||
$opt->{ typemap_prefix } or die 'Required argument typemap_prefix missing';
|
||||
|
||||
mkpath $base_path;
|
||||
|
||||
for my $service (@{ $service_of{ ident $self } }) {
|
||||
warn "creating typemap $opt->{ typemap_prefix }". $service->get_name() . "\n";
|
||||
$self->_create_typemap({ %{ $opt }, service => $service });
|
||||
$self->_create_interface({ %{ $opt }, service => $service });
|
||||
}
|
||||
|
||||
my @schema = @{ $self->first_types()->get_schema() };
|
||||
for my $type (map { @{ $_->get_type() } , @{ $_->get_element() } } @schema[1..$#schema] ) {
|
||||
warn 'creating class for '. $type->get_name() . "\n";
|
||||
$type->to_class( { %$opt, wsdl => $self } );
|
||||
}
|
||||
}
|
||||
|
||||
sub _create_interface {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $service_name = $opt->{ service }->get_name();
|
||||
$service_name =~s{\.}{\:\:}xmsg;
|
||||
# TODO: iterate over ports.
|
||||
# - ignore non-SOAP ports
|
||||
# - generate interface for all SOAP ports...
|
||||
my $binding = $self->find_binding( $self->_expand( $opt->{ service }->first_port()->get_binding() ) );
|
||||
my $porttype = $self->find_portType( $self->_expand( $binding->get_type() ) );
|
||||
|
||||
my $port_operation_ref = $porttype->get_operation();
|
||||
my $operation_ref = $binding->get_operation();
|
||||
|
||||
# make up operations map - name => [ part types / elements class names ]
|
||||
#
|
||||
my %operations = ();
|
||||
for my $operation ( @{ $operation_ref } ) {
|
||||
my $operation_name = $operation->get_name();
|
||||
my $soap_operation = $operation->first_operation();
|
||||
|
||||
$operations{ $operation_name }->{ style } = $soap_operation
|
||||
? $soap_operation->get_style()
|
||||
: undef;
|
||||
|
||||
$operations{ $operation_name }->{ soap_action } = $soap_operation
|
||||
? $soap_operation->get_soapAction()
|
||||
: undef;
|
||||
|
||||
my $port_op = first { $_->get_name() eq $operation_name } @{ $port_operation_ref };
|
||||
|
||||
$operations{ $operation_name }->{ documentation } = $port_op->get_documentation();
|
||||
|
||||
my %msg_from = (
|
||||
'input' => ($port_op->first_input() ) ? $port_op->first_input()->get_message() : undef,
|
||||
'output' => ($port_op->first_output()) ? $port_op->first_output()->get_message(): undef,
|
||||
'fault' => ($port_op->first_fault()) ? $port_op->first_fault()->get_message() : undef,
|
||||
);
|
||||
|
||||
for my $msg (keys %msg_from) {
|
||||
next if not $msg_from{ $msg };
|
||||
for my $part (@{ $self->find_message( $self->_expand( $msg_from{$msg} ) )->get_part }) {
|
||||
my $name;
|
||||
if (my $element_name = $part->get_element() ) {
|
||||
$name = $element_name;
|
||||
push @{ $operations{ $operation_name }->{$msg}->{ types } },
|
||||
$self->first_types()->find_element( $self->_expand( $element_name ) )
|
||||
->explain({ wsdl => $self , anonymous => 1 });
|
||||
|
||||
}
|
||||
elsif (my $type_name = $part->get_element() ) {
|
||||
push @{ $operations{ $operation_name }->{$msg}->{ types } },
|
||||
$self->first_types()->find_type( $self->_expand( $element_name ) )
|
||||
->explain({ wsdl => $self });
|
||||
$name = $type_name;
|
||||
}
|
||||
my ($prefix, $localname) = split m{:}xms , $name;
|
||||
push @{ $operations{ $operation_name }->{$msg}->{ class } },
|
||||
"$opt->{ element_prefix }$localname";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $template = <<'EOT';
|
||||
package [% interface_prefix %][% service.get_name.replace('\.', '::') %];
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use [% typemap_prefix %][% service.get_name %];
|
||||
use base 'SOAP::WSDL::Client::Base';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $arg_ref = shift || {};
|
||||
my $self = $class->SUPER::new({
|
||||
class_resolver => '[% typemap_prefix %][% service.get_name.replace('\.', '::') %]',
|
||||
proxy => '[% service.first_port.get_location %]',
|
||||
%{ $arg_ref }
|
||||
});
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
__PACKAGE__->__create_methods(
|
||||
[% FOREACH name = operations.keys -%]
|
||||
[% name %] => {
|
||||
parts => [ [% FOREACH class = operations.$name.input.class %]'[% class %]', [% END %]],
|
||||
soap_action => '[% operations.$name.soap_action %]',
|
||||
style => '[% operations.$name.style %]',
|
||||
# use => '', # use not implemented yet
|
||||
},
|
||||
[% END %]
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
[% MACRO pod BLOCK %]=pod[% END %]
|
||||
[% MACRO cut BLOCK %]=pod[% END %]
|
||||
[% MACRO head1 BLOCK %]=head1[% END %]
|
||||
[% MACRO head2 BLOCK %]=head2[% END %]
|
||||
[% pod %]
|
||||
|
||||
[% head1 %] NAME
|
||||
|
||||
[% interface_prefix %][% service.get_name %] - SOAP interface to [% service.get_name %] at
|
||||
[% service.first_port.get_location %]
|
||||
|
||||
[% head1 %] SYNOPSIS
|
||||
|
||||
my $interface = [% interface_prefix %][% service.get_name %]->new();
|
||||
my $[% operations.keys.1 %] = $interface->[% operations.keys.1 %]();
|
||||
|
||||
|
||||
[% head1 %] METHODS
|
||||
[% FOREACH name=operations.keys;
|
||||
operation=operations.$name;
|
||||
%]
|
||||
[% head2 %] [% name %]
|
||||
|
||||
[% operation.documentation %]
|
||||
|
||||
SYNOPSIS:
|
||||
|
||||
$service->[% name %]({
|
||||
[% FOREACH type = operation.input.types; type; END %] });
|
||||
|
||||
[% END %]
|
||||
|
||||
[% cut %]
|
||||
|
||||
EOT
|
||||
|
||||
require Template;
|
||||
my $file_name = "$opt->{ base_path }/$opt->{ interface_prefix }/$service_name.pm";
|
||||
$file_name =~s{::}{/}gms;
|
||||
my $path = dirname $file_name;
|
||||
my $name = basename $file_name;
|
||||
my $tt = Template->new(
|
||||
OUTPUT_PATH => $path,
|
||||
);
|
||||
$tt->process(\$template,
|
||||
{ %{ $opt }, operations => \%operations, binding => $binding, wsdl => $self },
|
||||
$name,
|
||||
binmode => ':utf8'
|
||||
)
|
||||
or die $tt->error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub _create_typemap {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $service_name = $opt->{ service }->get_name();
|
||||
$service_name =~s{\.}{\:\:}xmsg;
|
||||
my $file_name = "$opt->{ base_path }/$opt->{ typemap_prefix }/$service_name.pm";
|
||||
$file_name =~s{::}{/}gms;
|
||||
my $path = dirname $file_name;
|
||||
my $name = basename $file_name;
|
||||
|
||||
my $typemap = $opt->{ service }->to_typemap( { %{ $opt }, wsdl => $self } );
|
||||
|
||||
my $template = <<'EOT';
|
||||
package [% typemap_prefix %][% service.get_name.replace('\.', '::') %];
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %typemap = (
|
||||
# SOAP 1.1 fault typemap
|
||||
'Fault' => 'SOAP::WSDL::SOAP::Typelib::Fault11',
|
||||
'Fault/faultcode' => 'SOAP::WSDL::XSD::Typelib::Builtin::anyURI',
|
||||
'Fault/faultactor' => 'SOAP::WSDL::XSD::Typelib::Builtin::TOKEN',
|
||||
'Fault/faultstring' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
'Fault/detail' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
|
||||
# generated typemap
|
||||
[% typemap %]
|
||||
[% custom_types %]
|
||||
);
|
||||
|
||||
sub get_class {
|
||||
my $name = join '/', @{ $_[1] };
|
||||
exists $typemap{ $name } or die "Cannot resolve $name via " . __PACKAGE__;
|
||||
return $typemap{ $name };
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
EOT
|
||||
|
||||
require Template;
|
||||
my $tt = Template->new(
|
||||
OUTPUT_PATH => $path,
|
||||
);
|
||||
$tt->process(\$template,
|
||||
{ %{ $opt }, typemap => $typemap },
|
||||
$name,
|
||||
binmode => ':utf8',
|
||||
)
|
||||
or die $tt->error();
|
||||
|
||||
}
|
||||
|
||||
sub listify {
|
||||
my $data = shift;
|
||||
return if not defined $data;
|
||||
return [ $data ] if not ref $data;
|
||||
return [ $data ] if not ref $data eq 'ARRAY';
|
||||
return $data;
|
||||
}
|
||||
#sub listify {
|
||||
# my $data = shift;
|
||||
# return if not defined $data;
|
||||
# return [ $data ] if not ref $data;
|
||||
# return [ $data ] if not ref $data eq 'ARRAY';
|
||||
# return $data;
|
||||
#}
|
||||
|
||||
1;
|
||||
|
||||
@@ -374,142 +114,6 @@ Returns the message matching the namespace/localname pair passed as arguments.
|
||||
Accessors/Mutators for accessing / setting the E<gt>typesE<lt> child
|
||||
element(s).
|
||||
|
||||
=head2 explain
|
||||
|
||||
Returns a POD string describing how to call the methods of the service(s)
|
||||
described in the WSDL.
|
||||
|
||||
=head2 to_typemap
|
||||
|
||||
Creates a typemap for use with a generated type class library.
|
||||
|
||||
Options:
|
||||
|
||||
NAME DESCRIPTION
|
||||
-------------------------------------------------------------------------
|
||||
prefix Prefix to use for all classes
|
||||
type_prefix Prefix to use for all (Complex/Simple)Type classes
|
||||
element_prefix Prefix to use for all Element classes (with atomic types)
|
||||
|
||||
As some webservices tend to use globally unique type definitions, but
|
||||
locally unique elements with atomic types, type and element classes may
|
||||
be separated by specifying type_prefix and element_prefix instead of
|
||||
prefix.
|
||||
|
||||
The typemap is plain text which can be used as snipped for building a
|
||||
SOAP::WSDL class_resolver perl class.
|
||||
|
||||
Try something like this for creating typemap classes:
|
||||
|
||||
my $parser = XML::LibXML->new();
|
||||
my $handler = SOAP::WSDL::SAX::WSDLHandler->new()
|
||||
$parser->set_handler( $handler );
|
||||
|
||||
$parser->parse_url('file:///path/to/wsdl');
|
||||
|
||||
my $wsdl = $handler->get_data();
|
||||
my $typemap = $wsdl->to_typemap();
|
||||
|
||||
print <<"EOT"
|
||||
package MyTypemap;
|
||||
my \%typemap = (
|
||||
$typemap
|
||||
);
|
||||
sub get_class { return \$typemap{\$_[1] } };
|
||||
1;
|
||||
"EOT"
|
||||
|
||||
=head2 create_interface
|
||||
|
||||
Creates a typemap class, classes for all types and elements, and interface
|
||||
classes for every service.
|
||||
|
||||
See L<CODE GENERATOR|CODE GENERATOR> below.
|
||||
|
||||
Options:
|
||||
|
||||
Name Description
|
||||
----------------------------------------------------------------------------
|
||||
prefix Prefix to use for types and elements. Should end with '::'.
|
||||
element_prefix Prefix to use for element packages. Should end with '::'.
|
||||
Must be specified if prefix is not given.
|
||||
type_prefix Prefix to use for type packages. Should end with '::'.
|
||||
Must be specified if prefix is not given.
|
||||
typemap_prefix Prefix to use for type packages. Should end with '::'.
|
||||
Mandatory.
|
||||
custom_types A perl source code snippet defining custom types for the
|
||||
class resolver (typemap).
|
||||
Must look like this:
|
||||
q{
|
||||
'path/to/my/element' => 'My::Element',
|
||||
'path/to/my/element/prop' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
'path/to/my/element/prop2' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
};
|
||||
|
||||
=head2 _expand
|
||||
|
||||
Expands a qualified name into a list consisting of namespace URI and
|
||||
localname by using the definition's xmlns table.
|
||||
|
||||
Used internally by SOAP::WSDL::* classes.
|
||||
|
||||
=head1 CODE GENERATOR
|
||||
|
||||
TODO: move somewhere else - maybe SOAP::WSDL::Client ?
|
||||
|
||||
SOAP::WSDL::Definitions features a code generation facility for generating
|
||||
perl classes (packages) from a WSDL definition.
|
||||
|
||||
The following classes are generated:
|
||||
|
||||
=over
|
||||
|
||||
=item * Typemaps
|
||||
|
||||
A typemap class is created for every service.
|
||||
|
||||
Typemaps are basically lookup classes. They allow the
|
||||
SOAP::WSDL::SAX::MessageHandler to find out which class a XML element
|
||||
in a SOAP message shoud be processed as.
|
||||
|
||||
Typemaps are passed to SOAP::WSDL::Client via the class_resolver
|
||||
method.
|
||||
|
||||
=item * Interfaces
|
||||
|
||||
TODO: Implement Interface generation
|
||||
|
||||
Interface classes are just convenience shortcuts for accessing web
|
||||
service methods. They define a method for every web service method,
|
||||
dispatching the request to SOAP::WSDL::Client.
|
||||
|
||||
=item * Type and Element classes
|
||||
|
||||
For every top-level E<lt>elementE<gt>, E<lt>complexTypeE<gt> and
|
||||
E<lt>simpleTypeE<gt> definition in the WSDL's schema, a perl class is
|
||||
created.
|
||||
|
||||
Classes for E<lt>complexTypeE<gt> and E<lt>simpleTypeE<gt> definitions
|
||||
are prefixed by the C<type_prefix> argument passed to
|
||||
L<create_interface|create_interface>, classes for E<lt>elementE<gt>
|
||||
definitions are prefixed by the C<element_prefix> passed to
|
||||
L<create_interface|create_interface>. If the specific prefixes are not
|
||||
specified, the C<prefix> argument is used instead.
|
||||
|
||||
If your web service is part of a bigger framework which defines types
|
||||
globally, you probably do well always using the same C<type_prefix>:
|
||||
This reduces the number of classes generated (provided types
|
||||
are re-used by more than one service).
|
||||
|
||||
You probably should use different element prefixes, though -
|
||||
E<lt>elementE<gt> definitions tend to be unique in the defining WSDL
|
||||
only, especially when using document/literal style/encoding.
|
||||
|
||||
If not, you probably want to specify just C<prefix> (and use a
|
||||
different one for every web service).
|
||||
|
||||
=back
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2004-2007 Martin Kutter.
|
||||
|
||||
160
lib/SOAP/WSDL/Deserializer/Hash.pm
Normal file
160
lib/SOAP/WSDL/Deserializer/Hash.pm
Normal file
@@ -0,0 +1,160 @@
|
||||
package SOAP::WSDL::Deserializer::Hash;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use SOAP::WSDL::SOAP::Typelib::Fault11;
|
||||
use SOAP::WSDL::Expat::Message2Hash;
|
||||
|
||||
use SOAP::WSDL::Factory::Deserializer;
|
||||
SOAP::WSDL::Factory::Deserializer->register( '1.1', __PACKAGE__ );
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
sub BUILD {
|
||||
my ($self, $ident, $args_of_ref) = @_;
|
||||
|
||||
# ignore all options
|
||||
for (keys %{ $args_of_ref }) {
|
||||
delete $args_of_ref->{ $_ }
|
||||
}
|
||||
}
|
||||
|
||||
sub deserialize {
|
||||
my ($self, $content) = @_;
|
||||
|
||||
my $parser = SOAP::WSDL::Expat::Message2Hash->new();
|
||||
eval { $parser->parse_string( $content ) };
|
||||
if ($@) {
|
||||
die $self->generate_fault({
|
||||
code => 'soap:Server',
|
||||
role => 'urn:localhost',
|
||||
message => "Error deserializing message: $@. \n"
|
||||
. "Message was: \n$content"
|
||||
});
|
||||
}
|
||||
return $parser->get_data();
|
||||
}
|
||||
|
||||
sub generate_fault {
|
||||
my ($self, $args_from_ref) = @_;
|
||||
return SOAP::WSDL::SOAP::Typelib::Fault11->new({
|
||||
faultcode => $args_from_ref->{ code } || 'soap:Client',
|
||||
faultactor => $args_from_ref->{ role } || 'urn:localhost',
|
||||
faultstring => $args_from_ref->{ message } || "Unknown error"
|
||||
});
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Deserializer::Hash - Deserializer SOAP messages into perl hash refs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use SOAP::WSDL;
|
||||
use SOAP::WSDL::Deserializer::Hash;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Deserializer for creating perl hash refs as result of a SOAP call.
|
||||
|
||||
=head2 Output structure
|
||||
|
||||
The XML structure is converted into a perl data structure consisting of
|
||||
hash and or list references. List references are used for holding array data.
|
||||
|
||||
SOAP::WSDL::Deserializer::Hash creates list references always at the maximum
|
||||
depth possible.
|
||||
|
||||
Examples:
|
||||
|
||||
XML:
|
||||
<MyDataArray>
|
||||
<MyData>1</MyData>
|
||||
<MyData>1</MyData>
|
||||
</MyDataArray>
|
||||
|
||||
Perl:
|
||||
{
|
||||
MyDataArray => {
|
||||
MyData => [ 1, 1 ]
|
||||
}
|
||||
}
|
||||
|
||||
XML:
|
||||
<DeepArray>
|
||||
<MyData><int>1<int>/MyData>
|
||||
<MyData><int>1<int>/MyData>
|
||||
</DeepArray>
|
||||
|
||||
Perl:
|
||||
{
|
||||
MyDataArray => {
|
||||
MyData => [
|
||||
{ int => 1 },
|
||||
{ int => 1 }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
List reference creation is triggered by the second occurance of an element.
|
||||
XML Array types with one element only will not be represented as list
|
||||
references.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
All you need to do is to use SOAP::WSDL::Deserializer::Hash.
|
||||
|
||||
SOAP::WSDL::Deserializer::Hash autoregisters itself for SOAP1.1 messages
|
||||
|
||||
You may register SOAP::WSDLDeserializer::Hash for other SOAP Versions by
|
||||
calling
|
||||
|
||||
SOAP::Factory::Deserializer->register('1.2',
|
||||
SOAP::WSDL::Deserializer::Hash)
|
||||
|
||||
=head1 Limitations
|
||||
|
||||
=over
|
||||
|
||||
=item * Namespaces
|
||||
|
||||
All namespaces are ignored.
|
||||
|
||||
=item * XML attributes
|
||||
|
||||
All XML attributes are ignored.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Differences from other SOAP::WSDL::Deserializer classes
|
||||
|
||||
=over
|
||||
|
||||
=item * generate_fault
|
||||
|
||||
SOAP::WSDL::Deserializer::Hash will die with a SOAP::WSDL::Fault11 object when
|
||||
a parse error appears
|
||||
|
||||
=back
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2004-2007 Martin Kutter.
|
||||
|
||||
This file is part of SOAP-WSDL. You may distribute/modify it under
|
||||
the same terms as perl itself
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 176 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: Serializer.pm 176 2007-08-31 15:28:29Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
|
||||
|
||||
=cut
|
||||
@@ -3,8 +3,9 @@ use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use SOAP::WSDL::SOAP::Typelib::Fault11;
|
||||
use SOAP::WSDL::Expat::MessageParser;
|
||||
|
||||
our $VERSION='2.00_13';
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %class_resolver_of :ATTR(:name<class_resolver> :default<()>);
|
||||
|
||||
@@ -18,7 +19,6 @@ sub BUILD {
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub deserialize {
|
||||
my ($self, $content) = @_;
|
||||
|
||||
@@ -34,7 +34,7 @@ sub deserialize {
|
||||
. "Message was: \n$content"
|
||||
});
|
||||
}
|
||||
return $parser->get_data();
|
||||
return ( $parser->get_data(), $parser->get_header() );
|
||||
}
|
||||
|
||||
sub generate_fault {
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
package SOAP::WSDL::Deserializer::SOM;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use SOAP::Lite;
|
||||
|
||||
our $VERSION='2.00_13';
|
||||
our $VERSION = '2.00_15';
|
||||
our @ISA;
|
||||
|
||||
sub BUILD {
|
||||
my ($self, $ident, $args_of_ref) = @_;
|
||||
|
||||
# ignore all options
|
||||
for (keys %{ $args_of_ref }) {
|
||||
delete $args_of_ref->{ $_ };
|
||||
}
|
||||
}
|
||||
|
||||
sub deserialize {
|
||||
my ($self, $content) = @_;
|
||||
return SOAP::Deserializer->new()->deserialize( $content );
|
||||
eval {
|
||||
require SOAP::Lite;
|
||||
push @ISA, 'SOAP::Deserializer';
|
||||
}
|
||||
or die "Cannot load SOAP::Lite.
|
||||
Cannot deserialize to SOM object without SOAP::Lite.
|
||||
Please install SOAP::Lite.";
|
||||
|
||||
sub generate_fault {
|
||||
my ($self, $args_from_ref) = @_;
|
||||
@@ -49,13 +42,44 @@ SOAP::WSDL::Deserializer::SOM - Deserializer SOAP messages into SOM objects
|
||||
|
||||
Deserializer for creating SOAP::Lite's SOM object as result of a SOAP call.
|
||||
|
||||
This package is mainly here for compatibility reasons: You don't have to
|
||||
change the rest of your SOAP::Lite based app when switching to SOAP::WSDL,
|
||||
but can just use SOAP::WSDL::Deserializer::SOM to get back the same objects
|
||||
as you were used to.
|
||||
This package is here for two reasons:
|
||||
|
||||
SOAP::WSDL::Deserializer will not auroregister itself - just use the lines
|
||||
from the L</SYNOPSIS> to register it as deserializer for SOAP::WSDL.
|
||||
=over
|
||||
|
||||
=item * Compatibility
|
||||
|
||||
You don't have to change the rest of your SOAP::Lite based app when switching
|
||||
to SOAP::WSDL, but can just use SOAP::WSDL::Deserializer::SOM to get back the
|
||||
same objects as you were used to.
|
||||
|
||||
=item * Completeness
|
||||
|
||||
SOAP::Lite covers much more of the SOAP specification than SOAP::WSDL.
|
||||
|
||||
SOAP::WSDL::Deserializer::SOM can be used for content which cannot be
|
||||
deserialized by L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>.
|
||||
This may be XML including mixed content, attachements and other XML data not
|
||||
(yet) handled by L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>.
|
||||
|
||||
=back
|
||||
|
||||
SOAP::WSDL::Deserializer::SOM is a subclass of L<SOAP::Deserializer|SOAP::Deserializer>
|
||||
from the L<SOAP::Lite|SOAP::Lite> package.
|
||||
|
||||
You may
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
SOAP::WSDL::Deserializer will not auroregister itself - to use it for a particular
|
||||
SOAP version just use the following lines:
|
||||
|
||||
my $soap_version = '1.1'; # or '1.2', further versions may appear.
|
||||
|
||||
use SOAP::WSDL::Deserializer::SOM;
|
||||
use SOAP::WSDL::Factory::Deserializer;
|
||||
SOAP::WSDL::Factory::Deserializer->register( $soap_version, __PACKAGE__ );
|
||||
|
||||
=head1 DIFFERENCES FROM OTHER CLASSES
|
||||
|
||||
=head2 Differences from SOAP::Lite
|
||||
|
||||
|
||||
42
lib/SOAP/WSDL/Expat/Base.pm
Normal file
42
lib/SOAP/WSDL/Expat/Base.pm
Normal file
@@ -0,0 +1,42 @@
|
||||
package SOAP::WSDL::Expat::Base;
|
||||
use strict;
|
||||
use warnings;
|
||||
use XML::Parser::Expat;
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub parse {
|
||||
eval {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new( Namespaces => 1 ) )->parse( $_[1] );
|
||||
$_[0]->{ parser }->release();
|
||||
};
|
||||
$_[0]->{ parser }->xpcroak( $@ ) if $@;
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
sub parsefile {
|
||||
eval {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new(Namespaces => 1) )->parsefile( $_[1] );
|
||||
$_[0]->{ parser }->release();
|
||||
};
|
||||
$_[0]->{ parser }->xpcroak( $@ ) if $@;
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
# SAX-like aliases
|
||||
sub parse_string;
|
||||
*parse_string = \&parse;
|
||||
|
||||
sub parse_file;
|
||||
*parse_file = \&parsefile;
|
||||
|
||||
sub get_data {
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
1;
|
||||
127
lib/SOAP/WSDL/Expat/Message2Hash.pm
Normal file
127
lib/SOAP/WSDL/Expat/Message2Hash.pm
Normal file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/perl
|
||||
package SOAP::WSDL::Expat::Message2Hash;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(SOAP::WSDL::Expat::Base);
|
||||
|
||||
sub _initialize {
|
||||
my ($self, $parser) = @_;
|
||||
$self->{ parser } = $parser;
|
||||
delete $self->{ data }; # remove potential old results
|
||||
|
||||
my $characters;
|
||||
my $current = {};
|
||||
my $list = []; # node list
|
||||
my $current_part = q{}; # are we in header or body ?
|
||||
$self->{ data } = $current;
|
||||
|
||||
# use "globals" for speed
|
||||
my ($_element, $_method,
|
||||
$_class, $_parser, %_attrs) = ();
|
||||
|
||||
no strict qw(refs);
|
||||
$parser->setHandlers(
|
||||
Start => sub {
|
||||
push @$list, $current;
|
||||
#If our element exists and is a list ref, add to it
|
||||
if ( exists $current->{ $_[1] }
|
||||
&& ( ref ($current->{ $_[1] }) eq 'ARRAY')
|
||||
) {
|
||||
push @{ $current->{ $_[1] } }, {};
|
||||
$current = $current->{ $_[1] }->[-1];
|
||||
}
|
||||
elsif ( exists $current->{ $_[1] } )
|
||||
{
|
||||
$current->{ $_[1] } = [ $current->{ $_[1] }, {} ];
|
||||
$current = $current->{ $_[1] }->[-1];
|
||||
}
|
||||
else {
|
||||
$current->{ $_[1] } = {};
|
||||
$current = $current->{ $_[1] };
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
Char => sub {
|
||||
$characters .= $_[1] if $_[1] !~m{ \A \s* \z}xms;
|
||||
return;
|
||||
},
|
||||
|
||||
End => sub {
|
||||
$_element = $_[1];
|
||||
|
||||
# This one easily handles ignores for us, too...
|
||||
# return if not ref $$list[-1];
|
||||
|
||||
if (length $characters) {
|
||||
if (ref $list->[-1]->{ $_element } eq 'ARRAY') {
|
||||
$list->[-1]->{ $_element }->[-1] = $characters ;
|
||||
}
|
||||
else {
|
||||
$list->[-1]->{ $_element } = $characters;
|
||||
}
|
||||
}
|
||||
$characters = q{};
|
||||
$current = pop @$list; # step up in object hierarchy...
|
||||
return;
|
||||
}
|
||||
);
|
||||
return $parser;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Expat::Message2Hash - Convert SOAP messages to perl hash refs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $parser = SOAP::WSDL::Expat::MessageParser->new({
|
||||
class_resolver => 'My::Resolver'
|
||||
});
|
||||
$parser->parse( $xml );
|
||||
my $obj = $parser->get_data();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Real fast expat based SOAP message parser.
|
||||
|
||||
See L<SOAP::WSDL::Parser> for details.
|
||||
|
||||
=head1 Bugs and Limitations
|
||||
|
||||
=over
|
||||
|
||||
=item * Ignores all namespaces
|
||||
|
||||
=item * Ignores all attributes
|
||||
|
||||
=item * Does not handle mixed content
|
||||
|
||||
=item * The SOAP header is ignored
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Replace the whitespace by @ for E-Mail Address.
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 COPYING
|
||||
|
||||
This module may be used under the same terms as perl itself.
|
||||
|
||||
=head1 Repository information
|
||||
|
||||
$ID: $
|
||||
|
||||
$LastChangedDate: 2007-09-10 18:19:23 +0200 (Mo, 10 Sep 2007) $
|
||||
$LastChangedRevision: 218 $
|
||||
$LastChangedBy: kutterma $
|
||||
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageParser.pm $
|
||||
|
||||
@@ -3,12 +3,13 @@ package SOAP::WSDL::Expat::MessageParser;
|
||||
use strict;
|
||||
use warnings;
|
||||
use SOAP::WSDL::XSD::Typelib::Builtin;
|
||||
use XML::Parser::Expat;
|
||||
use base qw(SOAP::WSDL::Expat::Base);
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = {
|
||||
class_resolver => $args->{ class_resolver },
|
||||
strict => exists $args->{ strict } ? $args->{ strict } : 1,
|
||||
};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
@@ -16,68 +17,98 @@ sub new {
|
||||
|
||||
sub class_resolver {
|
||||
my $self = shift;
|
||||
$self->{ class_resolver } = shift;
|
||||
$self->{ class_resolver } = shift if @_;
|
||||
return $self->{ class_resolver };
|
||||
}
|
||||
|
||||
sub _initialize {
|
||||
my ($self, $parser) = @_;
|
||||
$self->{ parser } = $parser;
|
||||
|
||||
delete $self->{ data }; # remove potential old results
|
||||
delete $self->{ header };
|
||||
|
||||
my $characters;
|
||||
#my @characters_from = ();
|
||||
my $current = undef;
|
||||
my $ignore = [ 'Envelope', 'Body' ]; # top level elements to ignore
|
||||
my $list = []; # node list
|
||||
my $path = []; # current path
|
||||
my $skip = 0; # skip elements
|
||||
my $list = []; # node list
|
||||
my $path = []; # current path
|
||||
my $skip = 0; # skip elements
|
||||
my $current_part = q{}; # are we in header or body ?
|
||||
|
||||
my $depth = 0;
|
||||
|
||||
my %content_check = $self->{strict}
|
||||
? (
|
||||
0 => sub {
|
||||
die "Bad top node $_[1]" if $_[1] ne 'Envelope';
|
||||
die "Bad namespace for SOAP envelope: " . $_[0]->recognized_string()
|
||||
if $_[0]->namespace($_[1]) ne 'http://schemas.xmlsoap.org/soap/envelope/';
|
||||
$depth++;
|
||||
return;
|
||||
},
|
||||
1 => sub {
|
||||
$depth++;
|
||||
if ($_[1] eq 'Body') {
|
||||
if (exists $self->{ data }) { # there was header data
|
||||
$self->{ header } = $self->{ data };
|
||||
delete $self->{ data };
|
||||
$list = [];
|
||||
$path = [];
|
||||
undef $current;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
)
|
||||
: ();
|
||||
|
||||
my $char_handler = sub {
|
||||
# push @characters_from, $_[1] if $_[1] =~m{ [^s] }xms;
|
||||
$characters .= $_[1] if $_[1] =~m{ [^\s] }xms;
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
# use "globals" for speed
|
||||
my ($_prefix, $_localname, $_element, $_method,
|
||||
$_class, $_parser, %_attrs) = ();
|
||||
my ($_prefix, $_method,
|
||||
$_class) = ();
|
||||
|
||||
no strict qw(refs);
|
||||
$parser->setHandlers(
|
||||
Start => sub {
|
||||
($_parser, $_element, %_attrs) = @_;
|
||||
($_prefix, $_localname) = split m{:}xms , $_element;
|
||||
Start => sub {
|
||||
# my ($parser, $element, %_attrs) = @_;
|
||||
# $depth = $parser->depth();
|
||||
|
||||
$_localname ||= $_element; # for non-prefixed elements
|
||||
# call methods without using their parameter stack
|
||||
# That's slightly faster than $content_check{ $depth }->()
|
||||
# and we don't have to pass $_[1] to the method.
|
||||
# Yup, that's dirty.
|
||||
return &{$content_check{ $depth }} if exists $content_check{ $depth };
|
||||
|
||||
push @{ $path }, $_[1]; # step down in path
|
||||
return if $skip; # skip inside __SKIP__
|
||||
|
||||
# ignore top level elements
|
||||
if (@{ $ignore } && $_localname eq $ignore->[0]) {
|
||||
CHECK_ENVELOPE: {
|
||||
last CHECK_ENVELOPE if $_localname ne 'Envelope';
|
||||
last CHECK_ENVELOPE if exists $_attrs{ 'xmlns' }
|
||||
&& $_attrs{ 'xmlns' } eq 'http://schemas.xmlsoap.org/soap/envelope/';
|
||||
last CHECK_ENVELOPE if $_attrs{ "xmlns:$_prefix"}
|
||||
eq 'http://schemas.xmlsoap.org/soap/envelope/';
|
||||
die "Bad namespace for SOAP envelope: " . $parser->recognized_string();
|
||||
}
|
||||
shift @{ $ignore };
|
||||
return;
|
||||
}
|
||||
|
||||
push @{ $path }, $_localname; # step down in path
|
||||
return if $skip; # skip inside __SKIP__
|
||||
|
||||
# resolve class of this element
|
||||
$_class = $self->{ class_resolver }->get_class( $path )
|
||||
or die "Cannot resolve class for "
|
||||
. join('/', @{ $path }) . " via " . $self->{ class_resolver };
|
||||
|
||||
# maybe write as "return $skip = join ... if (...)" ?
|
||||
# would save a BLOCK...
|
||||
return $skip = join('/', @{ $path }) if ($_class eq '__SKIP__');
|
||||
if ($_class eq '__SKIP__') {
|
||||
$skip = join('/', @{ $path });
|
||||
$self->setHandlers( Char => undef );
|
||||
return;
|
||||
}
|
||||
|
||||
push @$list, $current; # step down in tree ()remember current)
|
||||
|
||||
$characters = q{}; # empty characters
|
||||
$characters = q(); # empty characters
|
||||
#@characters_from = ();
|
||||
|
||||
# Check whether we have a primitive - we implement them as classes
|
||||
# Check whether we have a builtin - we implement them as classes
|
||||
# We could replace this with UNIVERSAL->isa() - but it's slow...
|
||||
# match is a bit faster if the string does not match, but WAY slower
|
||||
# if $class matches...
|
||||
|
||||
# if $class matches...
|
||||
if (index $_class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
|
||||
# check wheter there is a non-empty ARRAY reference for $_class::ISA
|
||||
# or a "new" method
|
||||
@@ -90,77 +121,62 @@ sub _initialize {
|
||||
or die $@;
|
||||
}
|
||||
|
||||
$current = $_class->new({ %_attrs }); # set new current object
|
||||
$current = $_class->new({ @_[2..$#_] }); # set new current object
|
||||
|
||||
# remember top level element
|
||||
exists $self->{ data }
|
||||
or ($self->{ data } = $current);
|
||||
$depth++;
|
||||
return;
|
||||
},
|
||||
|
||||
Char => sub {
|
||||
return if $skip;
|
||||
$characters .= $_[1];
|
||||
},
|
||||
Char => $char_handler,
|
||||
|
||||
End => sub {
|
||||
$_element = $_[1];
|
||||
|
||||
($_prefix, $_localname) = split m{:}xms , $_element;
|
||||
$_localname ||= $_element; # for non-prefixed elements
|
||||
|
||||
End => sub {
|
||||
pop @{ $path }; # step up in path
|
||||
|
||||
if ($skip) {
|
||||
return if $skip ne join '/', @{ $path }, $_localname;
|
||||
return if $skip ne join '/', @{ $path }, $_[1];
|
||||
$skip = 0;
|
||||
$_[0]->setHandler( Char => $char_handler );
|
||||
return;
|
||||
}
|
||||
|
||||
$depth--;
|
||||
|
||||
# This one easily handles ignores for us, too...
|
||||
return if not ref $$list[-1];
|
||||
return if not ref $list->[-1];
|
||||
|
||||
# set characters in current if we are a simple type
|
||||
# we may have characters in complexTypes with simpleContent,
|
||||
# too - maybe we should rely on the presence of characters ?
|
||||
# may get a speedup by defining a ident method in anySimpleType
|
||||
# and looking it up via exists &$class::ident;
|
||||
if ( $current->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') ) {
|
||||
$current->set_value( $characters );
|
||||
}
|
||||
# if ( $current->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') ) {
|
||||
# $current->set_value( $characters );
|
||||
# }
|
||||
# currently doesn't work, as anyType does not implement value -
|
||||
# maybe change ?
|
||||
# $current->set_value( $characters ) if ($characters);
|
||||
|
||||
$current->set_value( $characters ) if (length $characters);
|
||||
#$current->set_value( join @characters_from ) if (@characters_from);
|
||||
$characters = q{};
|
||||
# undef @characters_from;
|
||||
# set appropriate attribute in last element
|
||||
# multiple values must be implemented in base class
|
||||
$_method = "add_$_localname";
|
||||
$$list[-1]->$_method( $current );
|
||||
#$_method = "add_$_localname";
|
||||
$_method = "add_$_[1]";
|
||||
$list->[-1]->$_method( $current );
|
||||
|
||||
$current = pop @$list; # step up in object hierarchy...
|
||||
return;
|
||||
}
|
||||
);
|
||||
return $parser;
|
||||
}
|
||||
|
||||
sub parse {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new() )->parse( $_[1] );
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
sub parsefile {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new() )->parsefile( $_[1] );
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
# SAX-like aliases
|
||||
sub parse_string;
|
||||
*parse_string = \&parse;
|
||||
|
||||
sub parse_file;
|
||||
*parse_file = \&parsefile;
|
||||
|
||||
sub get_data {
|
||||
return $_[0]->{ data };
|
||||
sub get_header {
|
||||
return $_[0]->{ header };
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -218,9 +234,9 @@ This module may be used under the same terms as perl itself.
|
||||
|
||||
$ID: $
|
||||
|
||||
$LastChangedDate: 2007-09-10 18:19:23 +0200 (Mo, 10 Sep 2007) $
|
||||
$LastChangedRevision: 218 $
|
||||
$LastChangedDate: 2007-10-03 20:46:56 +0200 (Mit, 03 Okt 2007) $
|
||||
$LastChangedRevision: 305 $
|
||||
$LastChangedBy: kutterma $
|
||||
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageParser.pm $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageParser.pm $
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use base qw(SOAP::WSDL::Expat::MessageParser);
|
||||
|
||||
sub parse_start {
|
||||
my $self = shift;
|
||||
$self->{ parser } = $_[0]->_initialize( XML::Parser::ExpatNB->new() );
|
||||
$self->{ parser } = $_[0]->_initialize( XML::Parser::ExpatNB->new( Namespaces => 1 ) );
|
||||
}
|
||||
sub init;
|
||||
*init = \&parse_start;
|
||||
@@ -19,6 +19,7 @@ sub parse_more {
|
||||
|
||||
sub parse_done {
|
||||
$_[0]->{ parser }->parse_done();
|
||||
$_[0]->{ parser }->release();
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -67,9 +68,9 @@ This module may be used under the same terms as perl itself.
|
||||
|
||||
$ID: $
|
||||
|
||||
$LastChangedDate: 2007-09-10 17:54:52 +0200 (Mo, 10 Sep 2007) $
|
||||
$LastChangedRevision: 214 $
|
||||
$LastChangedDate: 2007-10-03 20:46:56 +0200 (Mit, 03 Okt 2007) $
|
||||
$LastChangedRevision: 305 $
|
||||
$LastChangedBy: kutterma $
|
||||
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageStreamParser.pm $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageStreamParser.pm $
|
||||
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
package SOAP::WSDL::Expat::MessageSubParser;
|
||||
use strict;
|
||||
use warnings;
|
||||
use SOAP::WSDL::XSD::Typelib::Builtin;
|
||||
use XML::Parser::Expat;
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
# create handlers via currying - XML::Compiled is a good teacher...
|
||||
#
|
||||
# A handler has to know
|
||||
# - the order of it's child elements
|
||||
# - the classes for these child elements
|
||||
# - the handlers for these child elements (sub refs)
|
||||
|
||||
# order is checked if provided
|
||||
|
||||
sub start_tag {
|
||||
my $self = shift;
|
||||
my $arg_ref = shift;
|
||||
|
||||
my $CHILD_ORDER = $arg_ref->{ order } || [];
|
||||
my $CHILD_CLASS = $arg_ref->{ class_of } || {};
|
||||
my $CHILD_HANDLER = $arg_ref->{ handler_of };
|
||||
my $CHILD_OCCURS = $arg_ref->{ occurs_of } || {};
|
||||
|
||||
my $CHILD_INDEX = 0;
|
||||
|
||||
|
||||
return sub {
|
||||
# parser, element, attrs
|
||||
my ($prefix, $localname) = split m{:}xms , $_[1];
|
||||
$localname ||= $_[1];
|
||||
|
||||
=pod
|
||||
|
||||
# # implement better checks...
|
||||
# if (@{ $CHILD_ORDER }) {
|
||||
# if ($CHILD_ORDER->[$CHILD_INDEX] ne $localname) {
|
||||
# if (! $CHILD_ORDER->[++$CHILD_INDEX]
|
||||
# || $CHILD_ORDER->[$CHILD_INDEX] ne $localname) {
|
||||
# die "misplaced xml element " . $parser->recognized_string()
|
||||
# . " at line "
|
||||
# . $parser->current_line()
|
||||
# . " column " . $parser->current_column() , "\n"
|
||||
# , "Element order: " . join(',' , @{ $CHILD_ORDER }), "\n"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# if (%{ $CHILD_OCCURS }) {
|
||||
# die "too many occurances of $localname at line "
|
||||
# . $parser->current_line()
|
||||
# . " column " . $parser->current_column() , "\n"
|
||||
# if (not --$CHILD_OCCURS->{ $localname }->{ max });
|
||||
#
|
||||
# # min must be checked in end_element !
|
||||
# $CHILD_OCCURS->{ $localname }->{ min }--
|
||||
# if ($CHILD_OCCURS->{ $localname }->{ min });
|
||||
# }
|
||||
|
||||
=cut
|
||||
|
||||
# remove this some day
|
||||
return if ($localname eq 'Envelope');
|
||||
return if ($localname eq 'Body');
|
||||
|
||||
# step down in tree (remember current)
|
||||
push @{ $self->{ list } }, $self->{ current };
|
||||
$self->{ current } = $CHILD_CLASS->{ $localname }->new({ @_[2..$#_] });
|
||||
|
||||
# Set (and remember) next state
|
||||
push @{ $self->{ handlers } }, $CHILD_HANDLER->{ $localname };
|
||||
$_[0]->setHandlers( %{ $CHILD_HANDLER->{ $localname } } );
|
||||
};
|
||||
}
|
||||
|
||||
# characters is a good candidate for replacement when not needed -
|
||||
# expat calls it for those whitespaces in non-mixed-content-elements, too
|
||||
sub characters {
|
||||
my $self = shift;
|
||||
return sub { $self->{ characters } .= $_[1] };
|
||||
}
|
||||
|
||||
# end_tag is a somewhat generic thingy - don't know whether we should
|
||||
# curry it, and whether this will speed us up...
|
||||
sub end_tag {
|
||||
my $self = shift;
|
||||
|
||||
return sub {
|
||||
# step down handler hierarchy
|
||||
pop @{ $self->{ handlers } };
|
||||
|
||||
# restore state: set handler to last handler
|
||||
$_[0]->setHandlers( %{ $self->{ handlers }->[ -1 ] } );
|
||||
|
||||
my ($prefix, $localname) = split m{:}xms , $_[1];
|
||||
$localname ||= $_[1]; # for non-prefixed elements
|
||||
|
||||
# we only have characters if we need them - if not Char handler
|
||||
# has to be set to undef
|
||||
$self->{ current }->set_value( $self->{ characters } )
|
||||
if ($self->{ characters });
|
||||
|
||||
# empty temp characters
|
||||
undef $self->{ characters };
|
||||
|
||||
# return if we're top node
|
||||
# This one easily handles ignores for us, too...
|
||||
#
|
||||
# Hmm... could be replaced by something else, maybe ???
|
||||
# Maybe by defining an empty end_tag handler for the top node ?
|
||||
# Can we do this ???
|
||||
return if not defined $self->{ list }->[-1];
|
||||
|
||||
# set appropriate attribute in last element
|
||||
# multiple values must be implemented in base class
|
||||
my $method = "add_$localname";
|
||||
$self->{ list }->[-1]->$method( $self->{ current } );
|
||||
|
||||
# step up in object hierarchy...
|
||||
$self->{ current } = pop @{ $self->{ list } };
|
||||
};
|
||||
}
|
||||
|
||||
sub end_top_tag {
|
||||
my $self = shift;
|
||||
return sub {};
|
||||
}
|
||||
|
||||
sub initialize {
|
||||
my ($self, $handler_of_ref, $parser ) = @_;
|
||||
$parser ||= XML::Parser::Expat->new();
|
||||
$self->{ list } = undef;
|
||||
$self->{ current } = undef;
|
||||
$self->{ characters } = q{}; # empty characters
|
||||
$self->{ handlers } = [ $handler_of_ref ];
|
||||
$parser->setHandlers( %$handler_of_ref );
|
||||
return $parser;
|
||||
}
|
||||
|
||||
sub get_data {
|
||||
return $_[0]->{ current };
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Expat::MessageParser - Convert SOAP messages to custom object trees
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $parser = SOAP::WSDL::Expat::MessageParser->new({
|
||||
class_resolver => 'My::Resolver'
|
||||
});
|
||||
$parser->parse( $xml );
|
||||
my $obj = $parser->get_data();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Real fast expat based SOAP message parser.
|
||||
|
||||
See L<SOAP::WSDL::Parser> for details.
|
||||
|
||||
=head2 Skipping unwanted items
|
||||
|
||||
Sometimes there's unneccessary information transported in SOAP messages.
|
||||
|
||||
To skip XML nodes (including all child nodes), just edit the type map for
|
||||
the message and set the type map entry to '__SKIP__'.
|
||||
|
||||
=head1 Bugs and Limitations
|
||||
|
||||
=over
|
||||
|
||||
=item * Ignores all namespaces
|
||||
|
||||
=item * Does not handle mixed content
|
||||
|
||||
=item * The SOAP header is ignored
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Replace the whitespace by @ for E-Mail Address.
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 COPYING
|
||||
|
||||
This module may be used under the same terms as perl itself.
|
||||
|
||||
=head1 Repository information
|
||||
|
||||
$ID: $
|
||||
|
||||
$LastChangedDate: 2007-09-10 17:54:52 +0200 (Mo, 10 Sep 2007) $
|
||||
$LastChangedRevision: 214 $
|
||||
$LastChangedBy: kutterma $
|
||||
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageSubParser.pm $
|
||||
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
package SOAP::WSDL::Expat::MessageSubParser;
|
||||
use strict;
|
||||
use warnings;
|
||||
use SOAP::WSDL::XSD::Typelib::Builtin;
|
||||
use XML::Parser::Expat;
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = {
|
||||
class_resolver => $args->{ class_resolver }
|
||||
};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub class_resolver {
|
||||
my $self = shift;
|
||||
$self->{ class_resolver } = shift;
|
||||
}
|
||||
|
||||
sub _start;
|
||||
|
||||
sub _initialize {
|
||||
my ($self, $parser) = @_;
|
||||
|
||||
delete $self->{ data };
|
||||
|
||||
my $characters;
|
||||
my $current = undef;
|
||||
my $ignore = [ 'Envelope', 'Body' ]; # top level elements to ignore
|
||||
my $list = []; # node list
|
||||
my $path = []; # current path (without
|
||||
# number)
|
||||
my $skip = 0; # skip elements
|
||||
|
||||
# use "globals" for speed
|
||||
my ($_prefix, $_localname, $_element, $_method,
|
||||
$_class, $_parser, %_attrs) = ();
|
||||
|
||||
no strict qw(refs);
|
||||
|
||||
my $start_sub = sub {
|
||||
($_parser, $_element, %_attrs) = @_;
|
||||
($_prefix, $_localname) = split m{:}xms , $_element;
|
||||
|
||||
# $parser->setHandlers( Start => \&_start );
|
||||
|
||||
$_localname ||= $_element; # for non-prefixed elements
|
||||
|
||||
# ignore top level elements
|
||||
if (@{ $ignore } && $_localname eq $ignore->[0]) {
|
||||
shift @{ $ignore };
|
||||
return;
|
||||
}
|
||||
|
||||
push @{ $path }, $_localname; # step down in path
|
||||
return if $skip; # skip inside __SKIP__
|
||||
|
||||
# resolve class of this element
|
||||
$_class = $self->{ class_resolver }->get_class( $path )
|
||||
or die "Cannot resolve class for "
|
||||
. join('/', @{ $path }) . " via $self->{ class_resolver }";
|
||||
|
||||
# maybe write as "return $skip = join ... if (...)" ?
|
||||
# would save a BLOCK...
|
||||
return $skip = join('/', @{ $path }) if ($_class eq '__SKIP__');
|
||||
|
||||
push @$list, $current; # step down in tree ()remember current)
|
||||
|
||||
$characters = q{}; # empty characters
|
||||
|
||||
# Check whether we have a primitive - we implement them as classes
|
||||
# We could replace this with UNIVERSAL->isa() - but it's slow...
|
||||
# match is a bit faster if the string does not match, but WAY slower
|
||||
# if $class matches...
|
||||
|
||||
if (index $_class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
|
||||
# check wheter there is a CODE reference for $class::new.
|
||||
# If not, require it - all classes required here MUST
|
||||
# define new()
|
||||
# This is the same as $class->can('new'), but it's way faster
|
||||
*{ "$_class\::new" }{ CODE }
|
||||
or eval "require $_class" ## no critic qw(ProhibitStringyEval)
|
||||
or die $@;
|
||||
}
|
||||
|
||||
$current = $_class->new({ %_attrs }); # set new current object
|
||||
|
||||
# remember top level element
|
||||
defined $self->{ data }
|
||||
or ($self->{ data } = $current);
|
||||
};
|
||||
|
||||
my $char_sub = sub {
|
||||
return if $skip;
|
||||
$characters .= $_[1];
|
||||
};
|
||||
|
||||
my $end_sub = sub {
|
||||
$_element = $_[1];
|
||||
|
||||
($_prefix, $_localname) = split m{:}xms , $_element;
|
||||
$_localname ||= $_element; # for non-prefixed elements
|
||||
|
||||
pop @{ $path }; # step up in path
|
||||
|
||||
if ($skip) {
|
||||
return if $skip ne join '/', @{ $path }, $_localname;
|
||||
$skip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
# This one easily handles ignores for us, too...
|
||||
return if not ref $$list[-1];
|
||||
|
||||
# set characters in current if we are a simple type
|
||||
# we may have characters in complexTypes with simpleContent,
|
||||
# too - maybe we should rely on the presence of characters ?
|
||||
# may get a speedup by defining a ident method in anySimpleType
|
||||
# and looking it up via exists &$class::ident;
|
||||
if ( $current->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') ) {
|
||||
$current->set_value( $characters );
|
||||
}
|
||||
|
||||
# set appropriate attribute in last element
|
||||
# multiple values must be implemented in base class
|
||||
$_method = "add_$_localname";
|
||||
$$list[-1]->$_method( $current );
|
||||
|
||||
$current = pop @$list; # step up in object hierarchy...
|
||||
};
|
||||
|
||||
$parser->setHandlers(
|
||||
Start => sub {
|
||||
$_[0]->setHandlers( Start => $start_sub );
|
||||
$start_sub->(@_) },
|
||||
Char => $char_sub,
|
||||
End => $end_sub,
|
||||
);
|
||||
return $parser;
|
||||
}
|
||||
|
||||
sub parse {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new() )->parse( $_[1] );
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
sub parsefile {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new() )->parsefile( $_[1] );
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
sub get_data {
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Expat::MessageParser - Convert SOAP messages to custom object trees
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $parser = SOAP::WSDL::Expat::MessageParser->new({
|
||||
class_resolver => 'My::Resolver'
|
||||
});
|
||||
$parser->parse( $xml );
|
||||
my $obj = $parser->get_data();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Real fast expat based SOAP message parser.
|
||||
|
||||
See L<SOAP::WSDL::Parser> for details.
|
||||
|
||||
=head2 Skipping unwanted items
|
||||
|
||||
Sometimes there's unneccessary information transported in SOAP messages.
|
||||
|
||||
To skip XML nodes (including all child nodes), just edit the type map for
|
||||
the message and set the type map entry to '__SKIP__'.
|
||||
|
||||
=head1 Bugs and Limitations
|
||||
|
||||
=over
|
||||
|
||||
=item * Ignores all namespaces
|
||||
|
||||
=item * Does not handle mixed content
|
||||
|
||||
=item * The SOAP header is ignored
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Replace the whitespace by @ for E-Mail Address.
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 COPYING
|
||||
|
||||
This module may be used under the same terms as perl itself.
|
||||
|
||||
=head1 Repository information
|
||||
|
||||
$ID: $
|
||||
|
||||
$LastChangedDate: 2007-09-10 17:54:52 +0200 (Mo, 10 Sep 2007) $
|
||||
$LastChangedRevision: 214 $
|
||||
$LastChangedBy: kutterma $
|
||||
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/SubParser.pm $
|
||||
|
||||
|
||||
@@ -3,14 +3,7 @@ use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
use SOAP::WSDL::TypeLookup;
|
||||
use XML::Parser::Expat;
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
use base qw(SOAP::WSDL::Expat::Base);
|
||||
|
||||
sub _initialize {
|
||||
my ($self, $parser) = @_;
|
||||
@@ -28,13 +21,13 @@ sub _initialize {
|
||||
$parser->setHandlers(
|
||||
Start => sub {
|
||||
my ($parser, $localname, %attrs) = @_;
|
||||
|
||||
$characters = q{};
|
||||
|
||||
my $action = SOAP::WSDL::TypeLookup->lookup(
|
||||
$parser->namespace($localname),
|
||||
$localname
|
||||
);
|
||||
|
||||
return if not $action;
|
||||
|
||||
if ($action->{ type } eq 'CLASS') {
|
||||
@@ -84,9 +77,11 @@ sub _initialize {
|
||||
: _fixup_attrs($parser, %attrs)
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
Char => sub { $characters .= $_[1] },
|
||||
Char => sub { $characters .= $_[1]; return; },
|
||||
|
||||
End => sub {
|
||||
my ($parser, $localname) = @_;
|
||||
@@ -110,6 +105,7 @@ sub _initialize {
|
||||
no strict qw(refs);
|
||||
$current->$method( $characters );
|
||||
}
|
||||
return;
|
||||
}
|
||||
);
|
||||
return $parser;
|
||||
@@ -143,33 +139,5 @@ sub _fixup_attrs {
|
||||
return @attrs_from;
|
||||
}
|
||||
|
||||
sub parse {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new(
|
||||
Namespaces => 1
|
||||
) )->parse( $_[1] );
|
||||
$_[0]->{ parser }->release();
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
sub parsefile {
|
||||
$_[0]->_initialize( XML::Parser::Expat->new(
|
||||
Namespaces => 1
|
||||
) )->parsefile( $_[1] );
|
||||
$_[0]->{ parser }->release();
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
# aliases to make it more SAX-like
|
||||
sub parse_file;
|
||||
*parse_file = \&parsefile;
|
||||
|
||||
sub parse_string;
|
||||
*parse_string = \&parse;
|
||||
|
||||
|
||||
sub get_data {
|
||||
return $_[0]->{ data };
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
@@ -14,7 +14,15 @@ sub register {
|
||||
|
||||
sub get_deserializer {
|
||||
my ($self, $args_of_ref) = @_;
|
||||
eval "require $DESERIALIZER{ $args_of_ref->{ soap_version } }" or die $@;
|
||||
|
||||
# sanity check
|
||||
die "no deserializer registered for SOAP version $args_of_ref->{ soap_version }"
|
||||
if not exists ($DESERIALIZER{ $args_of_ref->{ soap_version } });
|
||||
|
||||
# load module
|
||||
eval "require $DESERIALIZER{ $args_of_ref->{ soap_version } }"
|
||||
or die "Cannot load serializer $DESERIALIZER{ $args_of_ref->{ soap_version } }", $@;
|
||||
|
||||
return $DESERIALIZER{ $args_of_ref->{ soap_version } }->new($args_of_ref);
|
||||
}
|
||||
|
||||
@@ -24,21 +32,21 @@ sub get_deserializer {
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Factory::Deserializer - factory for retrieving Deserializer objects
|
||||
SOAP::WSDL::Factory::Deserializer - Factory for retrieving Deserializer objects
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# from SOAP::WSDL::Client:
|
||||
$deserializer = SOAP::WSDL::Factory::Serializer->get_deserializer({
|
||||
$deserializer = SOAP::WSDL::Factory::Deserializer->get_deserializer({
|
||||
soap_version => $soap_version,
|
||||
class_resolver => $class_resolver,
|
||||
});
|
||||
|
||||
# in serializer class:
|
||||
package MyWickedSerializer;
|
||||
# in deserializer class:
|
||||
package MyWickedDeserializer;
|
||||
use SOAP::WSDL::Factory::Deserializer;
|
||||
|
||||
# u don't know the SOAP 1.2 recommendation? poor boy...
|
||||
# register class as deserializer for SOAP1.2 messages
|
||||
SOAP::WSDL::Factory::Deserializer->register( '1.2' , __PACKAGE__ );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@@ -50,15 +58,22 @@ The actual work is done by specific deserializer classes.
|
||||
|
||||
SOAP::WSDL::Deserializer tries to load one of the following classes:
|
||||
|
||||
a) the class registered for the scheme via register()
|
||||
=over
|
||||
|
||||
=item * The class registered for the scheme via register()
|
||||
|
||||
=back
|
||||
|
||||
By default, L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>
|
||||
is registered for SOAP1.1 messages.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 register
|
||||
|
||||
SOAP::WSDL::Serializer->register('1.1', 'MyWickedSerializer');
|
||||
SOAP::WSDL::Deserializer->register('1.1', 'MyWickedDeserializer');
|
||||
|
||||
Globally registers a class for use as serializer class.
|
||||
Globally registers a class for use as deserializer class.
|
||||
|
||||
=head2 get_deserializer
|
||||
|
||||
@@ -66,23 +81,25 @@ Returns an object of the deserializer class for this endpoint.
|
||||
|
||||
=head1 WRITING YOUR OWN DESERIALIZER CLASS
|
||||
|
||||
Deserializer classes may register with
|
||||
SOAP::WSDL::Factory::Deserializer.
|
||||
Deserializer classes may register with SOAP::WSDL::Factory::Deserializer.
|
||||
|
||||
Registering a deserializer class with
|
||||
SOAP::WSDL::Factory::Deserializer is done by executing the
|
||||
following code where $version is the SOAP version the class should
|
||||
be used for, and $class is the class
|
||||
name.
|
||||
=head2 Registering a deserializer
|
||||
|
||||
Registering a deserializer class with SOAP::WSDL::Factory::Deserializer
|
||||
is done by executing the following code where $version is the SOAP version
|
||||
the class should be used for, and $class is the class name.
|
||||
|
||||
SOAP::WSDL::Factory::Deserializer->register( $version, $class);
|
||||
|
||||
To auto-register your transport class on loading, execute register()
|
||||
in your tranport class (see L<SYNOPSIS|SYNOPSIS> above).
|
||||
|
||||
Deserializer modules must be named equal to the deserializer
|
||||
class they contain. There can only be one deserializer class per
|
||||
deserializer module.
|
||||
=head2 Deserializer package layout
|
||||
|
||||
Deserializer modules must be named equal to the deserializer class they
|
||||
contain. There can only be one deserializer class per deserializer module.
|
||||
|
||||
=head2 Methods to implement
|
||||
|
||||
Deserializer classes must implement the following methods:
|
||||
|
||||
@@ -96,19 +113,17 @@ Constructor.
|
||||
|
||||
Deserialize data from XML to arbitrary formats.
|
||||
|
||||
deserialize() must return a fault indicating that deserializing
|
||||
failed if any error is encountered during the process of
|
||||
deserializing the XML message.
|
||||
deserialize() must return a fault indicating that deserializing failed if
|
||||
any error is encountered during the process of deserializing the XML message.
|
||||
|
||||
The following
|
||||
positional parameters are passed to the deserialize method:
|
||||
The following positional parameters are passed to the deserialize method:
|
||||
|
||||
$content - the xml message
|
||||
|
||||
=item * generate_fault
|
||||
|
||||
Generate a fault in the supported format. The following named
|
||||
parameters are passed as a single hash ref:
|
||||
Generate a fault in the supported format. The following named parameters are
|
||||
passed as a single hash ref:
|
||||
|
||||
code - The fault code, e.g. 'soap:Server' or the like
|
||||
role - The fault role (actor in SOAP1.1)
|
||||
|
||||
@@ -2,6 +2,8 @@ package SOAP::WSDL::Factory::Serializer;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %SERIALIZER = (
|
||||
'1.1' => 'SOAP::WSDL::Serializer::SOAP11',
|
||||
);
|
||||
@@ -14,7 +16,15 @@ sub register {
|
||||
|
||||
sub get_serializer {
|
||||
my ($self, $args_of_ref) = @_;
|
||||
eval "require $SERIALIZER{ $args_of_ref->{ soap_version } }" or die $@;
|
||||
|
||||
# sanity check
|
||||
die "no serializer registered for SOAP version $args_of_ref->{ soap_version }"
|
||||
if not exists ($SERIALIZER{ $args_of_ref->{ soap_version } });
|
||||
|
||||
# load module
|
||||
eval "require $SERIALIZER{ $args_of_ref->{ soap_version } }"
|
||||
or die "Cannot load serializer $SERIALIZER{ $args_of_ref->{ soap_version } }", $@;
|
||||
|
||||
return $SERIALIZER{ $args_of_ref->{ soap_version } }->new();
|
||||
}
|
||||
|
||||
@@ -24,7 +34,7 @@ sub get_serializer {
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Factory::Serializer - factory for retrieving serializer objects
|
||||
SOAP::WSDL::Factory::Serializer - Factory for retrieving serializer objects
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@@ -37,7 +47,7 @@ SOAP::WSDL::Factory::Serializer - factory for retrieving serializer objects
|
||||
package MyWickedSerializer;
|
||||
use SOAP::WSDL::Factory::Serializer;
|
||||
|
||||
# u don't know the SOAP 1.2 recommendation? poor boy...
|
||||
# register as serializer for SOAP1.2 messages
|
||||
SOAP::WSDL::Factory::Serializer->register( '1.2' , __PACKAGE__ );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@@ -49,7 +59,11 @@ The actual work is done by specific serializer classes.
|
||||
|
||||
SOAP::WSDL::Serializer tries to load one of the following classes:
|
||||
|
||||
a) the class registered for the scheme via register()
|
||||
=over
|
||||
|
||||
=item * the class registered for the scheme via register()
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
@@ -65,28 +79,32 @@ Returns an object of the serializer class for this endpoint.
|
||||
|
||||
=head1 WRITING YOUR OWN SERIALIZER CLASS
|
||||
|
||||
=head2 Registering a deserializer
|
||||
|
||||
Serializer classes may register with SOAP::WSDL::Factory::Serializer.
|
||||
|
||||
Serializer objects may also be passed directly to SOAP::WSDL::Client
|
||||
by using the set_serializer method. Note that serializers objects set
|
||||
via SOAP::WSDL::Client's set_serializer method are discarded when the
|
||||
SOAP version is changed via set_soap_version.
|
||||
Serializer objects may also be passed directly to SOAP::WSDL::Client by
|
||||
using the set_serializer method. Note that serializers objects set via
|
||||
SOAP::WSDL::Client's set_serializer method are discarded when the SOAP
|
||||
version is changed via set_soap_version.
|
||||
|
||||
Registering a serializer class with SOAP::WSDL::Factory::Serializer
|
||||
is done by executing the following code where $version is the
|
||||
SOAP version the class should be used for, and $class is the class
|
||||
name.
|
||||
Registering a serializer class with SOAP::WSDL::Factory::Serializer is done
|
||||
by executing the following code where $version is the SOAP version the
|
||||
class should be used for, and $class is the class name.
|
||||
|
||||
SOAP::WSDL::Factory::Serializer->register( $version, $class);
|
||||
|
||||
To auto-register your transport class on loading, execute register()
|
||||
in your tranport class (see L<SYNOPSIS|SYNOPSIS> above).
|
||||
To auto-register your transport class on loading, execute register() in
|
||||
your tranport class (see L<SYNOPSIS|SYNOPSIS> above).
|
||||
|
||||
Serializer modules must be named equal to the serializer
|
||||
class they contain. There can only be one serializer class per
|
||||
serializer module.
|
||||
=head2 Serializer package layout
|
||||
|
||||
Serializer class must implement the following methods:
|
||||
Serializer modules must be named equal to the serializer class they contain.
|
||||
There can only be one serializer class per serializer module.
|
||||
|
||||
=head2 Methods to implement
|
||||
|
||||
Serializer classes must implement the following methods:
|
||||
|
||||
=over
|
||||
|
||||
@@ -96,8 +114,8 @@ Constructor.
|
||||
|
||||
=item * serialize
|
||||
|
||||
Serializes data to XML. The following named parameters are passed to
|
||||
the serialize method in a anonymous hash ref:
|
||||
Serializes data to XML. The following named parameters are passed to the
|
||||
serialize method in a anonymous hash ref:
|
||||
|
||||
{
|
||||
method => $operation_name,
|
||||
@@ -120,9 +138,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$Rev: 302 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: Serializer.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
|
||||
$Id: Serializer.pm 302 2007-09-30 19:25:25Z kutterma $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
|
||||
|
||||
=cut
|
||||
|
||||
@@ -2,6 +2,8 @@ package SOAP::WSDL::Factory::Transport;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
# class data
|
||||
my %registered_transport_of = ();
|
||||
|
||||
@@ -34,8 +36,9 @@ sub get_transport {
|
||||
|
||||
$scheme =~s{ \A ([^\:]+) \: .+ }{$1}smx;
|
||||
|
||||
if (exists $registered_transport_of{ $scheme }) {
|
||||
eval "require $registered_transport_of{ $scheme }" or die $@;
|
||||
if ($registered_transport_of{ $scheme }) {
|
||||
eval "require $registered_transport_of{ $scheme }"
|
||||
or die "Cannot load transport class $registered_transport_of{ $scheme } : $@";
|
||||
|
||||
# try "foo::Client" class first - SOAP::Tranport always requires
|
||||
# a package withoug the ::Client appended, and then
|
||||
@@ -45,12 +48,12 @@ sub get_transport {
|
||||
# sparse resource ...
|
||||
# ... but we've decided to mimic SOAP::Lite...
|
||||
|
||||
my $protocol_class = $SOAP_LITE_TRANSPORT_OF{ $scheme } . '::Client';
|
||||
my $transport;
|
||||
eval {
|
||||
$transport = $protocol_class->new( %attrs );
|
||||
};
|
||||
return $transport if not $@;
|
||||
# my $protocol_class = $SOAP_LITE_TRANSPORT_OF{ $scheme } . '::Client';
|
||||
# my $transport;
|
||||
# eval {
|
||||
# $transport = $protocol_class->new( %attrs );
|
||||
# };
|
||||
# return $transport if not $@;
|
||||
return $registered_transport_of{ $scheme }->new( %attrs );
|
||||
}
|
||||
|
||||
@@ -65,7 +68,8 @@ sub get_transport {
|
||||
}
|
||||
|
||||
if (exists $SOAP_WSDL_TRANSPORT_OF{ $scheme }) {
|
||||
eval "require $SOAP_WSDL_TRANSPORT_OF{ $scheme }" or die $@;
|
||||
eval "require $SOAP_WSDL_TRANSPORT_OF{ $scheme }"
|
||||
or die "Cannot load transport class $SOAP_WSDL_TRANSPORT_OF{ $scheme } : $@";
|
||||
return $SOAP_WSDL_TRANSPORT_OF{ $scheme }->new( %attrs );
|
||||
}
|
||||
|
||||
@@ -78,7 +82,7 @@ sub get_transport {
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Factory::Transport - factory for retrieving transport objects
|
||||
SOAP::WSDL::Factory::Transport - Factory for retrieving transport objects
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@@ -89,22 +93,29 @@ SOAP::WSDL::Factory::Transport - factory for retrieving transport objects
|
||||
package MyWickedTransport;
|
||||
use SOAP::WSDL::Factory::Transport;
|
||||
|
||||
# u don't know the httpr protocol? poor boy...
|
||||
# register class as transport module for httpr and https
|
||||
# (httpr is "reliable http", a protocol developed by IBM).
|
||||
SOAP::WSDL::Factory::Transport->register( 'httpr' , __PACKAGE__ );
|
||||
SOAP::WSDL::Factory::Transport->register( 'https' , __PACKAGE__ );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SOAP::WSDL::Transport serves as factory for retrieving
|
||||
transport objects for SOAP::WSDL.
|
||||
SOAP::WSDL::Transport serves as factory for retrieving transport objects for
|
||||
SOAP::WSDL.
|
||||
|
||||
The actual work is done by specific transport classes.
|
||||
|
||||
SOAP::WSDL::Transport tries to load one of the following classes:
|
||||
|
||||
a) the class registered for the scheme via register()
|
||||
b) the SOAP::Lite class matching the scheme
|
||||
c) the SOAP::WSDL class matching the scheme
|
||||
=over
|
||||
|
||||
=item * the class registered for the scheme via register()
|
||||
|
||||
=item * the SOAP::Lite class matching the scheme
|
||||
|
||||
=item * the SOAP::WSDL class matching the scheme
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
@@ -132,31 +143,34 @@ Gets the current transport object.
|
||||
|
||||
=head1 WRITING YOUR OWN TRANSPORT CLASS
|
||||
|
||||
=head2 Registering a transport class
|
||||
|
||||
Transport classes must be registered with SOAP::WSDL::Factory::Transport.
|
||||
|
||||
This is done by executing the following code where $scheme is the
|
||||
URL scheme the class should be used for, and $module is the class'
|
||||
module name.
|
||||
This is done by executing the following code where $scheme is the URL scheme
|
||||
the class should be used for, and $module is the class' module name.
|
||||
|
||||
SOAP::WSDL::Factory::Transport->register( $scheme, $module);
|
||||
|
||||
To auto-register your transport class on loading, execute register()
|
||||
in your tranport class (see L<SYNOPSIS|SYNOPSIS> above).
|
||||
To auto-register your transport class on loading, execute register() in your
|
||||
tranport class (see L<SYNOPSIS|SYNOPSIS> above).
|
||||
|
||||
Multiple protocols ore multiple classes are registered by multiple calls to
|
||||
register().
|
||||
|
||||
=head2 Transport plugin package layout
|
||||
|
||||
You may only use transport classes whose name is either
|
||||
the module name or the module name with '::Client' appended.
|
||||
|
||||
Transport classes must implement the interface required for
|
||||
SOAP::Lite transport classes.
|
||||
=head2 Methods to implement
|
||||
|
||||
See L<SOAP::Lite::Transport> for details,
|
||||
L<SOAP::WSDL::Transport::HTTP|SOAP::WSDL::Transport::HTTP>
|
||||
for an example.
|
||||
Transport classes must implement the interface required for SOAP::Lite
|
||||
transport classes (see L<SOAP::Lite::Transport> for details,
|
||||
L<SOAP::WSDL::Transport::HTTP|SOAP::WSDL::Transport::HTTP> for an example).
|
||||
|
||||
Transport modules must implement the following methods:
|
||||
To provide this interface, transport modules must implement the following
|
||||
methods:
|
||||
|
||||
=over
|
||||
|
||||
@@ -200,15 +214,14 @@ SOAP::WSDL does not require you to follow these restrictions.
|
||||
|
||||
There is only one restriction in SOAP::WSDL:
|
||||
|
||||
You may only use transport classes whose name is either
|
||||
the module name or the module name with '::Client' appended.
|
||||
You may only use transport classes whose name is either the module name or
|
||||
the module name with '::Client' appended.
|
||||
|
||||
SOAP::WSDL will try to instantiate an object of your
|
||||
transport class with '::Client' appended to allow using transport
|
||||
classes written for SOAP::Lite.
|
||||
SOAP::WSDL will try to instantiate an object of your transport class with
|
||||
'::Client' appended to allow using transport classes written for SOAP::Lite.
|
||||
|
||||
This may lead to errors when a different module with the name
|
||||
of your transport module suffixed with ::Client is also loaded.
|
||||
This may lead to errors when a different module with the name of your
|
||||
transport module suffixed with ::Client is also loaded.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
@@ -223,9 +236,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$Rev: 304 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: Transport.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Transport.pm $
|
||||
$Id: Transport.pm 304 2007-10-02 20:07:21Z kutterma $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Transport.pm $
|
||||
|
||||
=cut
|
||||
|
||||
49
lib/SOAP/WSDL/Generator/Template.pm
Normal file
49
lib/SOAP/WSDL/Generator/Template.pm
Normal file
@@ -0,0 +1,49 @@
|
||||
package SOAP::WSDL::Generator::Template;
|
||||
use strict;
|
||||
use Template;
|
||||
use Class::Std::Storable;
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %tt_of :ATTR(:get<tt>);
|
||||
my %definitions_of :ATTR(:name<definitions> :default<()>);
|
||||
my %interface_prefix_of :ATTR(:name<interface_prefix> :default<MyInterfaces>);
|
||||
my %typemap_prefix_of :ATTR(:name<typemap_prefix> :default<MyTypemaps>);
|
||||
my %type_prefix_of :ATTR(:name<type_prefix> :default<MyTypes>);
|
||||
my %element_prefix_of :ATTR(:name<element_prefix> :default<MyElements>);
|
||||
my %INCLUDE_PATH_of :ATTR(:name<INCLUDE_PATH> :default<()>);
|
||||
my %EVAL_PERL_of :ATTR(:name<EVAL_PERL> :default<0>);
|
||||
my %RECURSION_of :ATTR(:name<RECURSION> :default<0>);
|
||||
my %OUTPUT_PATH_of :ATTR(:name<OUTPUT_PATH> :default<.>);
|
||||
|
||||
sub START {
|
||||
my ($self, $ident, $arg_ref) = @_;
|
||||
$tt_of{$ident} = Template->new(
|
||||
DEBUG => 1,
|
||||
EVAL_PERL => $EVAL_PERL_of{ $ident },
|
||||
RECURSION => $RECURSION_of{ $ident },
|
||||
INCLUDE_PATH => $INCLUDE_PATH_of{ $ident },
|
||||
OUTPUT_PATH => $OUTPUT_PATH_of{ $ident },
|
||||
);
|
||||
}
|
||||
|
||||
sub _process :PROTECTED {
|
||||
my ($self, $template, $arg_ref, $output) = @_;
|
||||
my $tt = $self->get_tt();
|
||||
$tt->process( $template,
|
||||
{
|
||||
definitions => $self->get_definitions,
|
||||
interface_prefix => $self->get_interface_prefix,
|
||||
type_prefix => $self->get_type_prefix,
|
||||
typemap_prefix => $self->get_typemap_prefix,
|
||||
TYPE_PREFIX => $self->get_type_prefix,
|
||||
element_prefix => $self->get_element_prefix,
|
||||
NO_POD => delete $arg_ref->{ NO_POD } ? 1 : 0 ,
|
||||
%{ $arg_ref }
|
||||
},
|
||||
$output)
|
||||
or die $tt->error();
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
126
lib/SOAP/WSDL/Generator/Template/XSD.pm
Normal file
126
lib/SOAP/WSDL/Generator/Template/XSD.pm
Normal file
@@ -0,0 +1,126 @@
|
||||
package SOAP::WSDL::Generator::Template::XSD;
|
||||
use strict;
|
||||
use Template;
|
||||
use Class::Std::Storable;
|
||||
use File::Basename;
|
||||
use File::Spec;
|
||||
|
||||
use SOAP::WSDL::Generator::Visitor::Typemap;
|
||||
use SOAP::WSDL::Generator::Visitor::Typelib;
|
||||
use base qw(SOAP::WSDL::Generator::Template);
|
||||
|
||||
my %output_of :ATTR(:name<output> :default<()>);
|
||||
|
||||
sub BUILD {
|
||||
my ($self, $ident, $arg_ref) = @_;
|
||||
$self->set_EVAL_PERL(1);
|
||||
$self->set_RECURSION(1);
|
||||
$self->set_INCLUDE_PATH( exists $arg_ref->{INCLUDE_PATH}
|
||||
? $arg_ref->{INCLUDE_PATH}
|
||||
: File::Spec->rel2abs( dirname __FILE__ ). '/XSD/'
|
||||
);
|
||||
}
|
||||
|
||||
sub generate_typelib {
|
||||
my ($self) = @_;
|
||||
|
||||
# $output_of{ ident $self } = "";
|
||||
|
||||
my @schema = @{ $self->get_definitions()->first_types()->get_schema() };
|
||||
for my $type (map { @{ $_->get_type() } , @{ $_->get_element() } } @schema[1..$#schema] ) {
|
||||
$type->_accept( $self );
|
||||
}
|
||||
|
||||
# return $output_of{ ident $self };
|
||||
|
||||
}
|
||||
|
||||
sub generate_interface {
|
||||
my $self = shift;
|
||||
my $ident = ident $self;
|
||||
my $arg_ref = shift;
|
||||
my $tt = $self->get_tt();
|
||||
for my $service (@{ $self->get_definitions->get_service }) {
|
||||
for my $port (@{ $service->get_port() }) {
|
||||
# Skip ports without (known) address
|
||||
next if not $port->first_address;
|
||||
next if not $port->first_address->isa('SOAP::WSDL::SOAP::Address');
|
||||
|
||||
my $output = $arg_ref->{ output }
|
||||
? $arg_ref->{ output }
|
||||
: $self->_generate_filename( $self->get_interface_prefix(), $service->get_name(), $port->get_name );
|
||||
|
||||
$self->_process('Interface.tt',
|
||||
{
|
||||
service => $service,
|
||||
port => $port,
|
||||
NO_POD => $arg_ref->{ NO_POD } ? 1 : 0 ,
|
||||
},
|
||||
$output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub generate_typemap {
|
||||
my ($self, $arg_ref) = @_;
|
||||
|
||||
my $visitor = SOAP::WSDL::Generator::Visitor::Typemap->new({
|
||||
type_prefix => $self->get_type_prefix(),
|
||||
element_prefix => $self->get_element_prefix(),
|
||||
definitions => $self->get_definitions(),
|
||||
typemap => {
|
||||
'Fault' => 'SOAP::WSDL::SOAP::Typelib::Fault11',
|
||||
'Fault/faultcode' => 'SOAP::WSDL::XSD::Typelib::Builtin::anyURI',
|
||||
'Fault/faultactor' => 'SOAP::WSDL::XSD::Typelib::Builtin::TOKEN',
|
||||
'Fault/faultstring' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
'Fault/detail' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
}
|
||||
});
|
||||
for my $service (@{ $self->get_definitions->get_service }) {
|
||||
$visitor->visit_Service( $service );
|
||||
my $output = $arg_ref->{ output }
|
||||
? $arg_ref->{ output }
|
||||
: $self->_generate_filename( $self->get_typemap_prefix(), $service->get_name() );
|
||||
$self->_process('Typemap.tt',
|
||||
{
|
||||
service => $service,
|
||||
typemap => $visitor->get_typemap(),
|
||||
NO_POD => $arg_ref->{ NO_POD } ? 1 : 0 ,
|
||||
},
|
||||
$output);
|
||||
}
|
||||
}
|
||||
|
||||
sub _generate_filename :PRIVATE {
|
||||
my ($self, @parts) = @_;
|
||||
my $name = join '::', @parts;
|
||||
$name =~s{ \. }{::}xmsg;
|
||||
$name =~s{ :: }{/}xmsg;
|
||||
return "$name.pm";
|
||||
}
|
||||
|
||||
sub visit_XSD_Element {
|
||||
my ($self, $element) = @_;
|
||||
my $output = defined $output_of{ ident $self }
|
||||
? $output_of{ ident $self }
|
||||
: $self->_generate_filename( $self->get_element_prefix(), $element->get_name() );
|
||||
$self->_process('element.tt', { element => $element } , $output);
|
||||
}
|
||||
|
||||
sub visit_XSD_SimpleType {
|
||||
my ($self, $type) = @_;
|
||||
my $output = defined $output_of{ ident $self }
|
||||
? $output_of{ ident $self }
|
||||
: $self->_generate_filename( $self->get_type_prefix(), $type->get_name() );
|
||||
$self->_process('simpleType.tt', { simpleType => $type } , $output);
|
||||
}
|
||||
|
||||
sub visit_XSD_ComplexType {
|
||||
my ($self, $type) = @_;
|
||||
my $output = defined $output_of{ ident $self }
|
||||
? $output_of{ ident $self }
|
||||
: $self->_generate_filename( $self->get_type_prefix(), $type->get_name() );
|
||||
$self->_process('complexType.tt', { complexType => $type } , $output);
|
||||
}
|
||||
|
||||
1;
|
||||
69
lib/SOAP/WSDL/Generator/Template/XSD/Interface.tt
Normal file
69
lib/SOAP/WSDL/Generator/Template/XSD/Interface.tt
Normal file
@@ -0,0 +1,69 @@
|
||||
package [% interface_prefix %]::[% service.get_name %]::[% port.get_name %];
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Client::Base);
|
||||
|
||||
sub START {
|
||||
$_[0]->set_proxy('[% port.first_address.get_location %]') if not $_[2]->{proxy};
|
||||
$_[0]->set_class_resolver('[% typemap_prefix %]::[% service.get_name %]')
|
||||
if not $_[2]->{class_resolver};
|
||||
}
|
||||
|
||||
[% binding = definitions.find_binding( port.expand( port.get_binding ) );
|
||||
FOREACH operation = binding.get_operation;
|
||||
%][% INCLUDE Interface/Operation.tt %]
|
||||
[%
|
||||
END;
|
||||
%]
|
||||
|
||||
1;
|
||||
|
||||
[% IF NO_POD; STOP; END %]
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
||||
[% interface_prefix %]::[% service.get_name %]::[% port.get_name %] - SOAP Interface for the [% service.get_name %] Web Service
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SOAP Interface for the [% service.get_name %] web service
|
||||
located at [% port.first_address.get_location %].
|
||||
|
||||
=head1 SERVICE [% service.get_name %]
|
||||
|
||||
[% service.get_documentation %]
|
||||
|
||||
=head2 Port [% port.get_name %]
|
||||
|
||||
[% port.get_documentation %]
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 General methods
|
||||
|
||||
=head3 new
|
||||
|
||||
Constructor.
|
||||
|
||||
All arguments are forwarded to L<SOAP::WSDL::Client|SOAP::WSDL::Client>.
|
||||
|
||||
=head2 SOAP Service methods
|
||||
|
||||
[% INCLUDE Interface/POD/method_info.tt %]
|
||||
|
||||
|
||||
[% FOREACH operation = binding.get_operation;
|
||||
%][% INCLUDE Interface/POD/Operation.tt %]
|
||||
[% END %]
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Generated by SOAP::WSDL on [% PERL %]print scalar localtime() [% END %]
|
||||
|
||||
=pod
|
||||
65
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Body.tt
Normal file
65
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Body.tt
Normal file
@@ -0,0 +1,65 @@
|
||||
[% RETURN IF NOT item;
|
||||
type = definitions.find_portType( binding.expand( binding.get_type ) );
|
||||
port_op = type.find_operation( definitions.get_targetNamespace, operation.get_name );
|
||||
message = definitions.find_message( port_op.first_input.expand( port_op.first_input.get_message ) );
|
||||
part_from = message.get_part;
|
||||
PERL %]
|
||||
my $item = $stash->{ item };
|
||||
my $def = $stash->{ definitions };
|
||||
my $part_from = $stash->{ part_from };
|
||||
my $type_prefix = $stash->{ type_prefix };
|
||||
my $element_prefix = $stash->{ element_prefix };
|
||||
|
||||
my @body_part_from = split m{\s}, $item->get_parts;
|
||||
|
||||
my @parts;
|
||||
if (@body_part_from) {
|
||||
@parts = map {
|
||||
my $part = $_;
|
||||
(grep {
|
||||
my ($ns, $lname) = $def->expand( $_ );
|
||||
($lname eq $part->get_name)
|
||||
} @body_part_from
|
||||
)
|
||||
? do {
|
||||
my $name;
|
||||
($name = $part->get_element)
|
||||
? do {
|
||||
$name =~s{ ^[^:]+: }{}xms;
|
||||
$element_prefix . '::' . $name;
|
||||
}
|
||||
: ($name = $part->get_type)
|
||||
? do {
|
||||
$name =~s{ ^[^:]+: }{}xms;
|
||||
$type_prefix . '::' . $name;
|
||||
}
|
||||
: die "input must have either type or element"
|
||||
}
|
||||
: ()
|
||||
} @{ $part_from };
|
||||
}
|
||||
else {
|
||||
@parts = map {
|
||||
my $part = $_;
|
||||
my $name;
|
||||
($name = $part->get_element)
|
||||
? do {
|
||||
$name =~s{ ^[^:]+: }{}xms;
|
||||
"$element_prefix\::$name"
|
||||
}
|
||||
: ($name = $part->get_type)
|
||||
? do {
|
||||
$name =~s{ ^[^:]+: }{}xms;
|
||||
"$type_prefix\::$name"
|
||||
}
|
||||
: die "input must have either type or element";
|
||||
} @{ $part_from };
|
||||
}
|
||||
$stash->{ parts } = \@parts;
|
||||
|
||||
[% END;
|
||||
%]
|
||||
'use' => '[% item.get_use %]',
|
||||
namespace => '[% item.get_namespace %]',
|
||||
encodingStyle => '[% item.get_encodingStyle %]',
|
||||
parts => [qw( [% parts.join(' ') %] )],
|
||||
38
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Header.tt
Normal file
38
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Header.tt
Normal file
@@ -0,0 +1,38 @@
|
||||
[%
|
||||
RETURN IF NOT item;
|
||||
message_name = item.get_message;
|
||||
IF NOT message_name;
|
||||
THROW BAD_WSDL "missing <message> attribute in header for operation ${operation.get_name}";
|
||||
END;
|
||||
message = definitions.find_message( item.expand( message_name ) );
|
||||
PERL %]
|
||||
my $message = $stash->{ message };
|
||||
my $item = $stash->{ item };
|
||||
my $def = $stash->{ definitions };
|
||||
my $type_prefix = $stash->{ type_prefix };
|
||||
my $element_prefix = $stash->{ element_prefix };
|
||||
my ($ns, $lname) = $def->expand( $item->get_part() );
|
||||
my ($part) = grep {
|
||||
$_->get_name eq $lname
|
||||
&& $_->get_targetNamespace eq $ns } @{ $message->get_part( ) };
|
||||
my $part_class = do {
|
||||
my $name;
|
||||
($name = $part->get_element)
|
||||
? do {
|
||||
$name =~s{ ^[^:]+: }{}xms;
|
||||
$element_prefix . '::' . $name;
|
||||
}
|
||||
: ($name = $part->get_type)
|
||||
? do {
|
||||
$name =~s{ ^[^:]+: }{}xms;
|
||||
$type_prefix . '::' . $name;
|
||||
}
|
||||
: die "input must have either type or element"
|
||||
};
|
||||
$stash->{ part_class } = $part_class;
|
||||
[% END;
|
||||
%]
|
||||
'use' => '[% item.get_use %]',
|
||||
namespace => '[% item.get_namespace %]',
|
||||
encodingStyle => '[% item.get_encodingStyle %]',
|
||||
parts => [qw( [% part_class %] )],
|
||||
17
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Operation.tt
Normal file
17
lib/SOAP/WSDL/Generator/Template/XSD/Interface/Operation.tt
Normal file
@@ -0,0 +1,17 @@
|
||||
sub [% operation.get_name %] {
|
||||
my ($self, $body, $header) = @_;
|
||||
return $self->SUPER::call({
|
||||
operation => '[% operation.get_name %]',
|
||||
soap_action => '[% operation.first_operation.get_soapAction %]',
|
||||
style => '[% operation.get_style || binding.get_style %]',
|
||||
body => {
|
||||
[% INCLUDE Interface/Body.tt( item = operation.first_input.first_body ); %]
|
||||
},
|
||||
header => {
|
||||
[% INCLUDE Interface/Header.tt( item = operation.first_input.first_header ); %]
|
||||
},
|
||||
headerfault => {
|
||||
[% INCLUDE Interface/Header.tt( item = operation.first_input.first_headerfault ); %]
|
||||
}
|
||||
}, $body, $header);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
[% INDENT; %][% element.get_name %] => [%-
|
||||
IF (element.get_ref);
|
||||
element = element.get_ref();
|
||||
END;
|
||||
IF (type_name = element.get_type);
|
||||
INCLUDE Interface/POD/Type.tt(type = definitions.first_types.find_type( element.expand(type_name) ) );
|
||||
ELSIF (type = element.first_complexType);
|
||||
INCLUDE Interface/POD/Type.tt(type = type );
|
||||
ELSIF (type = element.first_simpleType);
|
||||
INCLUDE Interface/POD/Type.tt(type = type );
|
||||
END;
|
||||
%]
|
||||
@@ -0,0 +1,9 @@
|
||||
[%
|
||||
message_name = port_op.first_input.get_message();
|
||||
# message_name;
|
||||
|
||||
part_from = definitions.find_message( port_op.first_input.expand( message_name ) ).get_part;
|
||||
FOREACH part = part_from;
|
||||
INCLUDE Interface/POD/Part.tt(part = part);
|
||||
END;
|
||||
%]
|
||||
@@ -0,0 +1,8 @@
|
||||
=head3 [% operation.get_name %]
|
||||
|
||||
[% type = definitions.find_portType( binding.expand( binding.get_type ) );
|
||||
port_op = type.find_operation( definitions.get_targetNamespace, operation.get_name );
|
||||
port_op.get_documentation %]
|
||||
|
||||
$interface->[% operation.get_name %]([% INCLUDE Interface/POD/Message.tt %] );
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[% element = definitions.first_types.find_element( part.expand( part.get_element ) );
|
||||
#element.get_name();
|
||||
#element;
|
||||
#STOP;
|
||||
type = element.first_complexType || element.first_simpleType || definitions.first_types.find_type(
|
||||
element.expand( element.get_type ) );
|
||||
INCLUDE Interface/POD/Type.tt;%],
|
||||
@@ -0,0 +1,7 @@
|
||||
[%- indent = ' ';
|
||||
IF type.isa('SOAP::WSDL::XSD::ComplexType');
|
||||
INCLUDE complexType/POD/structure.tt(complexType = type);
|
||||
ELSE;
|
||||
INCLUDE simpleType/POD/structure.tt(simpleType = type);
|
||||
END;
|
||||
indent.replace('\s{2}$',''); %]
|
||||
@@ -0,0 +1,7 @@
|
||||
Method synopsis is displayed with hash refs as parameters.
|
||||
|
||||
The commented class names in the method's parameters denote that objects
|
||||
of the corresponding class can be passed instead of the marked hash ref.
|
||||
|
||||
You may pass any combination of objects, hash and list refs to these
|
||||
methods, as long as you meet the structure.
|
||||
28
lib/SOAP/WSDL/Generator/Template/XSD/Typemap.tt
Normal file
28
lib/SOAP/WSDL/Generator/Template/XSD/Typemap.tt
Normal file
@@ -0,0 +1,28 @@
|
||||
package [% typemap_prefix %]::[% service.get_name.replace('\.','::') %];
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our [% USE Dumper(varname = 'typemap_'); Dumper.dump( typemap ) %];
|
||||
|
||||
sub get_class {
|
||||
my $name = join '/', @{ $_[1] };
|
||||
exists $typemap_1->{ $name } or die "Cannot resolve $name via " . __PACKAGE__;
|
||||
return $typemap_1->{ $name };
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
[% typemap_prefix %]::[% service.get_name.replace('\.','::') %]; - typemap for ::[% service.get_name %];
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Typemap created by SOAP::WSDL for map-based SOAP message parsers.
|
||||
|
||||
=cut
|
||||
|
||||
6
lib/SOAP/WSDL/Generator/Template/XSD/_type_class.tt
Normal file
6
lib/SOAP/WSDL/Generator/Template/XSD/_type_class.tt
Normal file
@@ -0,0 +1,6 @@
|
||||
[% type_name = node.expand( type );
|
||||
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
|
||||
[% ELSE -%]
|
||||
[% type_prefix %]::[% type_name.1 %]
|
||||
[% END -%]
|
||||
44
lib/SOAP/WSDL/Generator/Template/XSD/complexType.tt
Normal file
44
lib/SOAP/WSDL/Generator/Template/XSD/complexType.tt
Normal file
@@ -0,0 +1,44 @@
|
||||
package [% type_prefix %]::[% complexType.get_name %];
|
||||
use strict;
|
||||
use warnings;
|
||||
[% INCLUDE complexType/contentModel.tt %]
|
||||
[%#
|
||||
# Don't include any perl source here - there may be sub-packages...
|
||||
#-%]
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
[% type_prefix %]::[% complexType.get_name %]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Perl data type class for the XML Schema defined complextype
|
||||
[% complexType.get_name %] from the namespace [% complexType.get_targetNamespace %].
|
||||
|
||||
=head2 PROPERTIES
|
||||
|
||||
The following properties may be accessed using get_PROPERTY / set_PROPERTY
|
||||
methods:
|
||||
|
||||
[% FOREACH element = complexType.get_element -%]
|
||||
[% element.get_name %]
|
||||
[% END %]
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 new
|
||||
|
||||
Constructor. The following data structure may be passed to new():
|
||||
|
||||
[% indent = ' '; INCLUDE complexType/POD/structure.tt %]
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Generated by SOAP::WSDL
|
||||
|
||||
=cut
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[% indent %]{
|
||||
[%- IF complexType.get_name %] # [% type_prefix %]::[% complexType.get_name %][% END %]
|
||||
[%- indent = indent _ ' ';
|
||||
FOREACH element = complexType.get_element %]
|
||||
[% indent %][% element.get_name %] => [% INCLUDE element/POD/structure.tt -%]
|
||||
[% END %]
|
||||
[% indent.replace('\s{2}$', ''); %]}
|
||||
@@ -0,0 +1,9 @@
|
||||
[% indent %]{
|
||||
[%- IF complexType.get_name %] # [% type_prefix %]::[% complexType.get_name %][% END %]
|
||||
[%- indent = indent _ ' ' %]
|
||||
[% indent %]# One of the following elements.
|
||||
[% indent %]# No occurance checks yet, so be sure to pass just one...
|
||||
[%- FOREACH element = complexType.get_element %]
|
||||
[% indent %][% element.get_name %] => [% INCLUDE element/POD/structure.tt -%]
|
||||
[% END %]
|
||||
[% indent.replace('\s{2}$', ''); %]}
|
||||
@@ -0,0 +1,9 @@
|
||||
[% IF (complexType.get_variety == 'restriction');
|
||||
INCLUDE complexType/POD/restriction.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_variety == 'sequence');
|
||||
THROW NOT_IMPLEMENTED, "${ complexType.get_name } - complexType complexContent extension not implemented yet";
|
||||
ELSE;
|
||||
THROW UNKNOWN, "unknown variety ${ complexType.get_variety }";
|
||||
END;
|
||||
|
||||
%]
|
||||
@@ -0,0 +1,7 @@
|
||||
[% indent %]{
|
||||
[%- IF complexType.get_name %] # [% type_prefix %]::[% complexType.get_name %][% END %]
|
||||
[%- indent = indent _ ' ';
|
||||
FOREACH element = complexType.get_element %]
|
||||
[% indent %][% element.get_name %] => [% INCLUDE element/POD/structure.tt -%]
|
||||
[% END %]
|
||||
[% indent.replace('\s{2}$', ''); %]}
|
||||
@@ -0,0 +1,13 @@
|
||||
[% IF (complexType.get_variety == 'all');
|
||||
INCLUDE complexType/POD/all.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_variety == 'sequence');
|
||||
INCLUDE complexType/POD/all.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_variety == 'group');
|
||||
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType group not implemented yet";
|
||||
ELSIF (complexType.get_variety == 'choice');
|
||||
INCLUDE complexType/POD/choice.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_contentModel == 'simpleContent');
|
||||
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType simpleContent not implemented yet";
|
||||
ELSIF (complexType.get_contentModel == 'complexContent');
|
||||
INCLUDE complexType/POD/complexContent.tt(complexType = complexType);
|
||||
END %]
|
||||
46
lib/SOAP/WSDL/Generator/Template/XSD/complexType/all.tt
Normal file
46
lib/SOAP/WSDL/Generator/Template/XSD/complexType/all.tt
Normal file
@@ -0,0 +1,46 @@
|
||||
use base qw(SOAP::WSDL::XSD::Typelib::ComplexType);
|
||||
|
||||
{ # BLOCK to scope variables
|
||||
[%
|
||||
atomic_types = [];
|
||||
|
||||
FOREACH element = complexType.get_element %]
|
||||
my %[% element.get_name %]_of :ATTR(:get<[% element.get_name %]>);
|
||||
[%- END %]
|
||||
|
||||
__PACKAGE__->_factory(
|
||||
[ qw([% FOREACH element = complexType.get_element %]
|
||||
[% element.get_name -%]
|
||||
[% END %]
|
||||
) ],
|
||||
{
|
||||
[% FOREACH element = complexType.get_element -%]
|
||||
[% element.get_name %] => \%[% element.get_name %]_of,
|
||||
[% END -%]
|
||||
},
|
||||
{
|
||||
[% FOREACH element = complexType.get_element;
|
||||
IF (type = element.get_type);
|
||||
element_type = complexType.expand( type );
|
||||
IF (element_type.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% element_type.1 %]',
|
||||
[% ELSE -%]
|
||||
[% element.get_name %] => '[% type_prefix %]::[% element_type.1 %]',
|
||||
[% END;
|
||||
ELSE;
|
||||
IF (element.first_simpleType);
|
||||
atomic_types.push( element.first_simpleType );
|
||||
ELSIF (element.first_simpleType);
|
||||
atomic_types.push( element.first_simpleType );
|
||||
ELSE;
|
||||
THROW NOT_IMPLEMENTED , "atomic types in complexType elements not supported yet";
|
||||
END; %]
|
||||
[% element.get_name %] => '[% type_prefix %]::[% complexType.get_name %]::_[% element.get_name %]',
|
||||
[% END;
|
||||
END -%]
|
||||
}
|
||||
);
|
||||
|
||||
} # end BLOCK
|
||||
|
||||
[% INCLUDE complexType/atomicTypes.tt(atomic_types = atomic_types) %]
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
[% FOREACH type = atomic_types; %]
|
||||
|
||||
package [% type_prefix %]::[% complexType.get_name %]::_[% element.get_name %];
|
||||
use strict;
|
||||
use warnings;
|
||||
{
|
||||
[% IF ( type.isa('SOAP::WSDL::XSD::ComplexType') );
|
||||
INCLUDE complexType/contentModel.tt(complexType = type );
|
||||
ELSIF ( type.isa('SOAP::WSDL::XSD::SimpleType') );
|
||||
INCLUDE simpleType/contentModel.tt(simpleType = type );
|
||||
ELSE;
|
||||
PERL; %] die $stash->{ type }->_DUMP [% END;
|
||||
THROW UNKNOWN, "neither complex nor simple type - don't know what to do";
|
||||
END
|
||||
%]
|
||||
}
|
||||
|
||||
[% END %]
|
||||
@@ -0,0 +1,8 @@
|
||||
[% IF (complexType.get_variety == 'restriction');
|
||||
INCLUDE complexType/restriction.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_variety == 'sequence');
|
||||
THROW NOT_IMPLEMENTED, "${ complexType.get_name } - complexType complexContent extension not implemented yet";
|
||||
ELSE;
|
||||
THROW UNKNOWN, "unknown variety ${ complexType.get_variety }";
|
||||
END;
|
||||
%]
|
||||
@@ -0,0 +1,15 @@
|
||||
[% IF (complexType.get_variety == 'all');
|
||||
INCLUDE complexType/all.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_variety == 'sequence');
|
||||
INCLUDE complexType/all.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_variety == 'group');
|
||||
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType group not implemented yet";
|
||||
ELSIF (complexType.get_variety == 'choice');
|
||||
INCLUDE complexType/all.tt(complexType = complexType);
|
||||
ELSIF (complexType.get_contentModel == 'simpleContent');
|
||||
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType simpleContent not implemented yet";
|
||||
ELSIF (complexType.get_contentModel == 'complexContent');
|
||||
INCLUDE complexType/complexContent.tt(complexType = complexType);
|
||||
ELSE;
|
||||
THROW NOT_IMPLEMENTED, "Unknown content model ${ complexType.get_contentModel }";
|
||||
END %]
|
||||
@@ -0,0 +1,8 @@
|
||||
[% IF (base=complexType.get_base);
|
||||
base_name=complexType.expand(base);
|
||||
-%]
|
||||
use base qw([% type_prefix %]::[% base_name.1 %]);
|
||||
[%
|
||||
ELSE;
|
||||
THROW NOT_IMPLEMENTED, "restriction without base not supported";
|
||||
END %]
|
||||
71
lib/SOAP/WSDL/Generator/Template/XSD/element.tt
Normal file
71
lib/SOAP/WSDL/Generator/Template/XSD/element.tt
Normal file
@@ -0,0 +1,71 @@
|
||||
package [% element_prefix %]::[% element.get_name %];
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
{ # BLOCK to scope variables
|
||||
|
||||
sub get_xmlns { '[% element.get_targetNamespace %]' }
|
||||
|
||||
__PACKAGE__->__set_name('[% element.get_name %]');
|
||||
__PACKAGE__->__set_nillable([% element.get_nillable %]);
|
||||
__PACKAGE__->__set_minOccurs([% element.get_minOccurs %]);
|
||||
__PACKAGE__->__set_maxOccurs([% element.get_maxOccurs %]);
|
||||
__PACKAGE__->__set_ref([% IF element.get_ref; %]'[% element.get_ref %]'[% END %]);
|
||||
|
||||
[%- IF (type = element.get_type); -%]
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Element
|
||||
[% INCLUDE _type_class.tt( type = type, node = element ) %]
|
||||
);
|
||||
[%- ELSIF (ref = element.get_ref); -%]
|
||||
# element ref="[% ref %]"
|
||||
use base qw(
|
||||
[% element_prefix %]::[% ref.split(':').1 %]
|
||||
);
|
||||
[%- ELSIF (simpleType = element.first_simpleType) %]
|
||||
# atomic simpleType: <element><simpleType
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Element
|
||||
);
|
||||
[% INCLUDE simpleType/contentModel.tt %]
|
||||
[% ELSIF (complexType = element.first_complexType) %]
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Element
|
||||
SOAP::WSDL::XSD::Typelib::ComplexType
|
||||
);
|
||||
[% INCLUDE complexType/contentModel.tt;
|
||||
END %]
|
||||
|
||||
|
||||
} # end of BLOCK
|
||||
1;
|
||||
|
||||
# __END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
[% element_prefix %]::[% element.get_name %]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Perl data type class for the XML Schema defined element
|
||||
[% element.get_name %] from the namespace [% element.get_targetNamespace %].
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 new
|
||||
|
||||
my $element = [% element_prefix %]::[% element.get_name %]->new($data);
|
||||
|
||||
Constructor. The following data structure may be passed to new():
|
||||
|
||||
[% indent = ' '; INCLUDE element/POD/structure.tt; %]
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Generated by SOAP::WSDL
|
||||
|
||||
=cut
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
[%- IF (name = element.get_type);
|
||||
type_name = element.expand(name);
|
||||
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
|
||||
$some_value, # [% type_name.1 %]
|
||||
[%-
|
||||
RETURN;
|
||||
ELSIF (type = definitions.first_types.find_type( type_name ));
|
||||
IF (type.isa('SOAP::WSDL::XSD::ComplexType') );
|
||||
INCLUDE complexType/POD/structure.tt(complexType = type);
|
||||
RETURN;
|
||||
ELSE;
|
||||
INCLUDE simpleType/POD/structure.tt(simpleType = type);
|
||||
END;
|
||||
RETURN;
|
||||
END;
|
||||
THROW NOT_FOUND, "no type found for {${type_name.0}}${type_name.1}";
|
||||
ELSIF (ref = element.get_ref);
|
||||
ref_element = definitions.first_types.find_element( element.expand( ref ) );
|
||||
INCLUDE element/POD/structure.tt(element = ref_element);
|
||||
RETURN;
|
||||
ELSIF (type = element.first_simpleType);
|
||||
INCLUDE simpleType/POD/structure.tt(simpleType = type);
|
||||
RETURN;
|
||||
ELSIF (type = element.first_complexType);
|
||||
INCLUDE complexType/POD/structure.tt(complexType = type);
|
||||
ELSE;
|
||||
THROW NOT_FOUND, "no type found for ${element.get_name}";
|
||||
%]
|
||||
NO TYPE FOUND FOR ELEMENT [% element.get_name %]
|
||||
[% END -%]
|
||||
56
lib/SOAP/WSDL/Generator/Template/XSD/simpleType.tt
Normal file
56
lib/SOAP/WSDL/Generator/Template/XSD/simpleType.tt
Normal file
@@ -0,0 +1,56 @@
|
||||
package [% type_prefix %]::[% simpleType.get_name %];
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub get_xmlns { '[% simpleType.get_targetNamespace %]'};
|
||||
|
||||
[% INCLUDE simpleType/contentModel.tt %]
|
||||
[%#
|
||||
# Don't include any perl source here - there may be sub-packages...
|
||||
#-%]
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 [% type_prefix %]::[% simpleType.get_name %]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Perl data type class for the XML Schema defined simpleType
|
||||
[% simpleType.get_name %] from the namespace [% simpleType.get_targetNamespace %].
|
||||
|
||||
[% IF (simpleType.get_variety == 'list');
|
||||
INCLUDE simpleType/POD/list.tt;
|
||||
ELSIF (simpleType.get_variety == 'restriction');
|
||||
INCLUDE simpleType/POD/restriction.tt;
|
||||
ELSE;
|
||||
THROW NOT_IMPLEMENTED "simpleType union not implemented yet in $simpleType.get_name";
|
||||
END %]
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 new
|
||||
|
||||
Constructor.
|
||||
|
||||
=head2 get_value / set_value
|
||||
|
||||
Getter and setter for the simpleType's value.
|
||||
|
||||
=head1 OVERLOADING
|
||||
|
||||
Depending on the simple type's base type, the following operations are overloaded
|
||||
|
||||
Stringification
|
||||
Numerification
|
||||
Boolification
|
||||
|
||||
Check L<SOAP::WSDL::XSD::Typelib::Builtin> for more information.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Generated by SOAP::WSDL
|
||||
|
||||
=cut
|
||||
|
||||
20
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/POD/list.tt
Normal file
20
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/POD/list.tt
Normal file
@@ -0,0 +1,20 @@
|
||||
This clase is derived from
|
||||
[%-
|
||||
IF (name = simpleType.get_itemType);
|
||||
type_name = simpleType.expand( name );
|
||||
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
|
||||
[% ELSE -%]
|
||||
[% type_prefix %]::[% type_name.1 %]
|
||||
[% END;
|
||||
ELSE;
|
||||
# THROW NOT_IMPLEMENTED "atomic simpleType list not implemented yet in $simpleType.get_name";
|
||||
%] a atomic base type. Unfortunately there's no documenatation generation for atomic base types yet. [%
|
||||
END -%].
|
||||
|
||||
You may pass the following structure to new():
|
||||
|
||||
[ $value_1, .. $value_n ]
|
||||
|
||||
All elements of the list must be of the class' base type (or
|
||||
valid arguments to it's constructor).
|
||||
@@ -0,0 +1,17 @@
|
||||
This clase is derived from
|
||||
[%-
|
||||
IF (name = simpleType.get_base);
|
||||
type_name = simpleType.expand( name );
|
||||
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
|
||||
[% ELSE -%]
|
||||
[% type_prefix %]::[% type_name.1 %]
|
||||
[% END;
|
||||
ELSE;
|
||||
# THROW NOT_IMPLEMENTED "atomic simpleType restriction not implemented yet in $simpleType.get_name";
|
||||
%] a atomic base type. Unfortunately there's no documenatation generation for atomic base types yet. [%
|
||||
END -%]
|
||||
. SOAP::WSDL's schema implementation does not validate data, so you can use it exactly
|
||||
like it's base type.
|
||||
|
||||
# Description of restrictions not implemented yet.
|
||||
@@ -0,0 +1 @@
|
||||
$some_value, # [% IF (simpleType.get_name); simpleType.get_name; ELSE %]atomic[% END %]
|
||||
@@ -0,0 +1,3 @@
|
||||
# atomic simple type.
|
||||
|
||||
[% INCLUDE simpleType/contentModel.tt(simpleType = type ); %]
|
||||
@@ -0,0 +1,7 @@
|
||||
[% IF (simpleType.get_variety == 'list');
|
||||
INCLUDE simpleType/list.tt(simpleType = simpleType);
|
||||
ELSIF (simpleType.get_variety == 'restriction');
|
||||
INCLUDE simpleType/restriction.tt(type = simpleType);
|
||||
ELSE;
|
||||
THROW NOT_IMPLEMENTED "${ element.get_name } - ${ simpleType.get_variety } not supported yet";
|
||||
END %]
|
||||
21
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/list.tt
Normal file
21
lib/SOAP/WSDL/Generator/Template/XSD/simpleType/list.tt
Normal file
@@ -0,0 +1,21 @@
|
||||
# list derivation
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::list
|
||||
[%
|
||||
IF (name = simpleType.get_itemType);
|
||||
type_name = simpleType.expand( name );
|
||||
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
|
||||
);
|
||||
[% ELSE -%]
|
||||
[% type_prefix %]::[% type_name.1 %]
|
||||
);
|
||||
[% END;
|
||||
ELSIF (type = simpleType.first_simpleType); %]
|
||||
);
|
||||
|
||||
[% INCLUDE simpleType/atomicType.tt(type = type);
|
||||
ELSE; PERL %]die $stash->{simpleType}._DUMP [% END;
|
||||
THROW UNKNOWN , "No list itemTape and no atomic simpleType - don't know what to do";
|
||||
END %]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# derivation by restriction
|
||||
[% IF (base = simpleType.get_base) -%]
|
||||
use base qw(
|
||||
[% INCLUDE _type_class.tt(type = base, node=simpleType) %]);
|
||||
[% ELSIF (type = simpleType.first_simpleType() );
|
||||
INCLUDE simpleType/atomicType.tt(type = type);
|
||||
ELSE;
|
||||
THROW "neither base nor atomic type - don't know what to do" %]
|
||||
[% END %]
|
||||
315
lib/SOAP/WSDL/Generator/Visitor.pm
Normal file
315
lib/SOAP/WSDL/Generator/Visitor.pm
Normal file
@@ -0,0 +1,315 @@
|
||||
package SOAP::WSDL::Generator::Visitor;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
|
||||
our $VERSION = '2.00_17';
|
||||
|
||||
my %definitions_of :ATTR(:name<definitions> :default<()>);
|
||||
my %type_prefix_of :ATTR(:name<type_prefix> :default<()>);
|
||||
my %element_prefix_of :ATTR(:name<element_prefix> :default<()>);
|
||||
|
||||
sub START {
|
||||
my ($self, $ident, $arg_ref) = @_;
|
||||
$type_prefix_of{ $ident } = 'MyType' if not exists
|
||||
$arg_ref->{ 'type_prefix' };
|
||||
$element_prefix_of{ $ident } = 'MyElement' if not exists
|
||||
$arg_ref->{ 'element_prefix' };
|
||||
|
||||
}
|
||||
|
||||
|
||||
# WSDL stuff
|
||||
sub visit_Definitions {}
|
||||
sub visit_Binding {}
|
||||
sub visit_Message {}
|
||||
sub visit_Operation {}
|
||||
sub visit_OpMessage {}
|
||||
sub visit_Part {}
|
||||
sub visit_Port {}
|
||||
sub visit_PortType {}
|
||||
sub visit_Service {}
|
||||
sub visit_SoapOperation {}
|
||||
sub visit_Types {}
|
||||
|
||||
# XML Schema stuff
|
||||
sub visit_XSD_Schema {}
|
||||
sub visit_XSD_ComplexType {}
|
||||
sub visit_XSD_Element {}
|
||||
sub visit_XSD_SimpleType {}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Generator::Visitor - SOAP::WSDL's Visitor-based Code Generator
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SOAP::WSDL featores a code generating facility. This code generation facility
|
||||
(in fact there are several of them) is implemented as Visitor to
|
||||
SOAP::WSDL::Base-derived objects.
|
||||
|
||||
=head2 The Visitor Pattern
|
||||
|
||||
The Visitor design pattern is one of the object oriented design pattern
|
||||
described by [GHJV1995].
|
||||
|
||||
A Visitor is an object implementing some behaviour for a fixed set of classes,
|
||||
whose implementation would otherwise need to be scattered accross those
|
||||
classes' implementations.
|
||||
|
||||
Visitors are usually combined with Iterators for traversing either a list or
|
||||
tree of objects.
|
||||
|
||||
A Visitor's methods are called using the so-called double dispatch technique.
|
||||
To allow double dispatching, the Visitor implements one method for every class
|
||||
ro be handled, whereas every class implements just one method (commonly named
|
||||
"access"), which does nothing more than calling a method on the reference
|
||||
given, with the self object as parameter.
|
||||
|
||||
If all this sounds strange, maybe an example helps. Imagine you had a list of
|
||||
person objects and wanted to print out a list of their names (or address
|
||||
stamps or everything elseyou like). This can easily be implemented with a
|
||||
Visitor:
|
||||
|
||||
package PersonVisitor;
|
||||
use Class::Std; # handles all basic stuff like constructors etc.
|
||||
|
||||
sub visit_Person {
|
||||
my ( $self, $object ) = @_;
|
||||
print "Person name is ", $object->get_name(), "\n";
|
||||
}
|
||||
|
||||
package Person;
|
||||
use Class::Std;
|
||||
my %name : ATTR(:name<name> :default<anonymous>);
|
||||
|
||||
sub accept { $_[1]->visit_Person( $_[0] ) }
|
||||
|
||||
package main;
|
||||
my @person_from = ();
|
||||
for (qw(Gamma Helm Johnson Vlissides)) {
|
||||
push @person_from, Person->new( { name => $_ } );
|
||||
}
|
||||
|
||||
my $visitor = PersonVisitor->new();
|
||||
for (@person_from) {
|
||||
$_->accept($visitor);
|
||||
}
|
||||
|
||||
# will print
|
||||
Person name is Gamma
|
||||
Person name is Helm
|
||||
Person name is Johnson
|
||||
Person name is Vlissides
|
||||
|
||||
While using this pattern for just printing a list may look a bit over-sized,
|
||||
but it may become handy if you need multiple output formats and different
|
||||
classes to operate on.
|
||||
|
||||
The main benefits using visitors are:
|
||||
|
||||
=over
|
||||
|
||||
=item * Grouping related behaviour in one class
|
||||
|
||||
Related behaviour for several classes can be grouped together in the Visitor
|
||||
class. The behaviour can easily be changed by changing the code in one class,
|
||||
instead of having to change all the visited classes.
|
||||
|
||||
=item * Cleaning up the data classes' implementations
|
||||
|
||||
If classes holding data also implement several different output formats or
|
||||
other (otherwise unrelated) behaviour, they tend to get bloated.
|
||||
|
||||
=item * Adding behaviour is easy
|
||||
|
||||
Swapping out the visitor class allows easy alterations of behaviour. So on a
|
||||
list of Persons, one Visitor may print address stamps, while another one prints
|
||||
out a phone number list.
|
||||
|
||||
=back
|
||||
|
||||
Of course, there are also drawbacks in the visitor pattern:
|
||||
|
||||
=over
|
||||
|
||||
=item * Changes in the visited classes are expensive
|
||||
|
||||
If one of the visited classes changes (or is added), all visitors must be
|
||||
updated to reflect this change. This may be rather expensive if classes change
|
||||
often.
|
||||
|
||||
=item * The visited classes must expose all data required
|
||||
|
||||
Visitors may need to use the internals of a class. This may result in fidelling
|
||||
with a object's internals, or a bloated interface in the visited class.
|
||||
|
||||
=back
|
||||
|
||||
Visitors are usually accompanied by a Iterator. The Iterator may be implemented
|
||||
in the visited classes, in the Visitor, or somewhere else (in the example it
|
||||
was somewhere else).
|
||||
|
||||
The Iterator decides which object to visit next.
|
||||
|
||||
=head2 Why SOAP::WSDL uses the Visitor pattern for Code Generation
|
||||
|
||||
Code generation in SOAP::WSDL means generating various artefacts:
|
||||
|
||||
=over
|
||||
|
||||
=item * Typemaps
|
||||
|
||||
For every WSDL definition, a Typemap is created. The Typemap is used later as
|
||||
an aid in parsing the SOAP XML messages.
|
||||
|
||||
=item * Type Classes
|
||||
|
||||
For every type defined in the WSDL's schema, a Type Class is generated.
|
||||
|
||||
These classes are instantiated later as a result of parsing SOAP XML messages.
|
||||
|
||||
=item * Interface Classes
|
||||
|
||||
For every service, a interface class is generated. This class is later used by
|
||||
programmers accessing the service
|
||||
|
||||
=item * Documentation
|
||||
|
||||
Both Type Classes and Interface Classes include documentation. Additional
|
||||
documentation may be generated as a hint for programmers, or later for
|
||||
mimicing .NET's .asmx example pages.
|
||||
|
||||
=back
|
||||
|
||||
All these behaviours could well (and has historically been) implemented in the
|
||||
classes holding the WSDL data. This made these classes rather bloated, and
|
||||
made it hard to change behaviour (like, supporting SOAP Headers,
|
||||
supporting atomic types and other features which were missing from early
|
||||
versions of SOAP::WSDL).
|
||||
|
||||
Implementing these behaviours in Visitor classes eases adding new behaviours,
|
||||
and reducing the incompletenesses still inherent in SOAP::WSDL's WSDL and XML
|
||||
schema implementation.
|
||||
|
||||
=head2 Implementation
|
||||
|
||||
=head3 accept
|
||||
|
||||
SOAP::WSDL::Base defines an accept method which expects a Visitor as only
|
||||
parameter.
|
||||
|
||||
The method visit_Foo_Bar is called on the visitor, whith the self object as
|
||||
parameter.
|
||||
|
||||
The actual method name is constructed this way:
|
||||
|
||||
=over
|
||||
|
||||
=item * SOAP::WSDL is stripped from the class name
|
||||
|
||||
=item * All remaining :: s are replaced by _
|
||||
|
||||
=back
|
||||
|
||||
Example:
|
||||
|
||||
When visiting a SOAP::WSDL::XSD::ComplexType object, the method
|
||||
visit_XSD_ComplexType is called on the visitor.
|
||||
|
||||
=head2 Writing your own visitor
|
||||
|
||||
SOAP::WSDL eases writing your own visitor. This might be required if you need
|
||||
some special output format from a WSDL file, or want to feed your own
|
||||
serializer/deserializer pair with custom configuration data. Or maybe you want
|
||||
to generate C# code from it...
|
||||
|
||||
To write your own code generating visitor, you should subclass
|
||||
SOAP::WSDL::Generator::Visitor. It implements (empty) default methods for all
|
||||
SOAP::WSDL data classes:
|
||||
|
||||
=over
|
||||
|
||||
=item * visit_Definitions
|
||||
|
||||
=item * visit_Binding
|
||||
|
||||
=item * visit_Message
|
||||
|
||||
=item * visit_Operation
|
||||
|
||||
=item * visit_OpMessage
|
||||
|
||||
=item * visit_Part
|
||||
|
||||
=item * visit_Port
|
||||
|
||||
=item * visit_PortType
|
||||
|
||||
=item * visit_Service
|
||||
|
||||
=item * visit_SoapOperation
|
||||
|
||||
=item * visit_Types
|
||||
|
||||
=item * visit_XSD_Schema
|
||||
|
||||
=item * visit_XSD_ComplexType
|
||||
|
||||
=item * visit_XSD_Element
|
||||
|
||||
=item * visit_XSD_SimpleType
|
||||
|
||||
=back
|
||||
|
||||
In your Visitor, you must implement visit_Foo methods for all classes you wish
|
||||
to visit.
|
||||
|
||||
Currently, all SOAP::WSDL::Generator::Visitor implementations include their own
|
||||
Iterator (which means they know how to find the next objects to visit). You
|
||||
may or may not choose to implement a separate Iterator.
|
||||
|
||||
Letting a visitor implementing it's own Iterator visit a WSDL definition is as
|
||||
easy as writing something like this:
|
||||
|
||||
my $visitor = MyVisitor->new();
|
||||
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
|
||||
my $definitions = $parser->parse_file('my.wsdl'):
|
||||
|
||||
$definitions->_accept( $visitor );
|
||||
|
||||
=head1 REFERENCES
|
||||
|
||||
=over
|
||||
|
||||
=item * [GHJV1995]
|
||||
|
||||
Erich Gamma, Richard Helm, Ralph E. Johnson, John Vlissides, (1995):
|
||||
Design Patterns. Elements of Reusable Object-Oriented Software.
|
||||
Addison-Wesley Longman, Amsterdam.
|
||||
|
||||
=back
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2004-2007 Martin Kutter.
|
||||
|
||||
This file is part of SOAP-WSDL. You may distribute/modify it under
|
||||
the same terms as perl itself
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 239 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: Client.pm 239 2007-09-11 09:45:42Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client.pm $
|
||||
|
||||
=cut
|
||||
10
lib/SOAP/WSDL/Generator/Visitor/Typelib.pm
Normal file
10
lib/SOAP/WSDL/Generator/Visitor/Typelib.pm
Normal file
@@ -0,0 +1,10 @@
|
||||
package SOAP::WSDL::Generator::Visitor::Typelib;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(SOAP::WSDL::Generator::Visitor
|
||||
SOAP::WSDL::Generator::Template
|
||||
);
|
||||
|
||||
|
||||
1;
|
||||
|
||||
227
lib/SOAP/WSDL/Generator/Visitor/Typemap.pm
Normal file
227
lib/SOAP/WSDL/Generator/Visitor/Typemap.pm
Normal file
@@ -0,0 +1,227 @@
|
||||
package SOAP::WSDL::Generator::Visitor::Typemap;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
|
||||
use base qw(SOAP::WSDL::Generator::Visitor);
|
||||
|
||||
my %path_of :ATTR(:name<path> :default<[]>);
|
||||
my %typemap_of :ATTR(:name<typemap> :default<()>);
|
||||
my %type_prefix_of :ATTR(:name<type_prefix> :default<()>);
|
||||
my %element_prefix_of :ATTR(:name<element_prefix> :default<()>);
|
||||
|
||||
sub START {
|
||||
my ($self, $ident, $arg_ref) = @_;
|
||||
$type_prefix_of{ $ident } ||= 'MyTypes';
|
||||
$element_prefix_of{ $ident } ||= 'MyElements';
|
||||
}
|
||||
|
||||
sub set_typemap_entry {
|
||||
my ($self, $value) = @_;
|
||||
$typemap_of{ ident $self }->{
|
||||
join( q{/}, @{ $path_of{ ident $self } } )
|
||||
} = $value;
|
||||
}
|
||||
|
||||
sub add_element_path {
|
||||
my ($self, $element) = @_;
|
||||
|
||||
# Swapping out this lines against the ones below generates
|
||||
# a namespace-sensitive typemap.
|
||||
# Well almost: Class names are not constructed in a namespace-sensitive
|
||||
# manner, yet - there should be some facility to allow binding a (perl)
|
||||
# prefix to a namespace...
|
||||
push @{ $path_of{ ident $self } }, $element->get_name();
|
||||
|
||||
# push @{ $path_of{ ident $self } },
|
||||
# "{". $element->get_targetNamespace . "}"
|
||||
# . $element->get_name();
|
||||
}
|
||||
|
||||
sub visit_Definitions {
|
||||
my ( $self, $ident, $definitions ) = ( $_[0], ident $_[0], $_[1] );
|
||||
|
||||
$self->set_definitions( $definitions );
|
||||
|
||||
for ( @{ $definitions->get_service() } ) {
|
||||
$_->_accept($self);
|
||||
}
|
||||
}
|
||||
|
||||
sub visit_Service {
|
||||
my ( $self, $service ) = ( $_[0], $_[1] );
|
||||
|
||||
for ( @{ $service->get_port() } ) { $_->_accept($self); }
|
||||
}
|
||||
|
||||
sub visit_Port {
|
||||
my ( $self, $ident, $port ) = ( $_[0], ident $_[0], $_[1] );
|
||||
|
||||
# This is a false assumption - typemaps may be valid for non-soap
|
||||
# bindings as well.
|
||||
# TODO check and correct
|
||||
return if not $port->first_address();
|
||||
return if not $port->first_address()->isa('SOAP::WSDL::SOAP::Address');
|
||||
|
||||
my $binding = $self->get_definitions()
|
||||
->find_binding( $port->expand( $port->get_binding() ) )
|
||||
or die 'binding ' . $port->get_binding() . ' not found!';
|
||||
|
||||
$binding->_accept($self);
|
||||
}
|
||||
|
||||
sub visit_Binding {
|
||||
my ( $self, $ident, $binding ) = ( $_[0], ident $_[0], $_[1] );
|
||||
|
||||
my $portType = $self->get_definitions()
|
||||
->find_portType( $binding->expand( $binding->get_type ) )
|
||||
or die 'portType not found: ' . $binding->binding_type;
|
||||
|
||||
for my $operation ( @{ $binding->get_operation() } ) {
|
||||
my $name = $operation->get_name();
|
||||
|
||||
# get the equally named operation from the portType
|
||||
my ($op) = grep { $_->get_name eq $name }
|
||||
@{ $portType->get_operation() }
|
||||
or die "operation <$name> not found";
|
||||
|
||||
# visit every input, output and fault message...
|
||||
for ( @{ $op->get_input }, @{ $op->get_output }, @{ $op->get_fault } ) {
|
||||
$_->_accept($self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub visit_OpMessage {
|
||||
my ( $self, $ident, $operation_message ) = ( $_[0], ident $_[0], $_[1] );
|
||||
return if not( $operation_message->get_message() ); # we're in binding
|
||||
|
||||
# TODO maybe allow more messages && overloading by specifying name
|
||||
|
||||
# find message referenced in operation
|
||||
my $message = $self->get_definitions()->find_message(
|
||||
$operation_message->expand( $operation_message->get_message() ) );
|
||||
|
||||
for my $part ( @{ $message->get_part() } ) {
|
||||
$part->_accept($self);
|
||||
}
|
||||
}
|
||||
|
||||
sub visit_Part {
|
||||
my ( $self, $ident, $part ) = ( $_[0], ident $_[0], $_[1] );
|
||||
|
||||
my $types_ref = $self->get_definitions()->first_types()
|
||||
or warn "Empty part" . $part->get_name();
|
||||
|
||||
# resolve type
|
||||
# If we have a type, this type is to be used in document/literal
|
||||
# as global type. However this is forbidden, at least by WS-I.
|
||||
# We should store the style/encoding somewhere, and regard it.
|
||||
# TODO: auto-generate element for RPC bindings
|
||||
if ( my $type_name = $part->get_type ) {
|
||||
# FIXME support RPC-style calls
|
||||
die "unsupported global type <$type_name> found in part";
|
||||
}
|
||||
|
||||
# TODO factor out iterator or replace by lookup (probably better)
|
||||
if ( my $element_name = $part->get_element() ) {
|
||||
my $element = $types_ref->find_element(
|
||||
$part->expand($element_name) )
|
||||
|| die "no element $element_name found for part " . $part->get_name();
|
||||
$element->_accept($self);
|
||||
return;
|
||||
}
|
||||
|
||||
warn 'neither type nor element - do not know what to do for part '
|
||||
. $part->get_name();
|
||||
return;
|
||||
}
|
||||
|
||||
sub process_referenced_type {
|
||||
my ( $self, $ns, $localname ) = @_;
|
||||
return if not $localname;
|
||||
my $ident = ident $self;
|
||||
|
||||
# get type's class name
|
||||
# Caveat: visits type if it's a referenced type from the
|
||||
# a ? b : c operation.
|
||||
my $typeclass =
|
||||
( $ns eq 'http://www.w3.org/2001/XMLSchema' )
|
||||
? "SOAP::WSDL::XSD::Typelib::Builtin::$localname"
|
||||
: do {
|
||||
my $type =
|
||||
$self->get_definitions()->first_types()->find_type( $ns, $localname );
|
||||
$type->_accept($self);
|
||||
join( q{::}, $type_prefix_of{$ident}, $type->get_name() );
|
||||
};
|
||||
|
||||
$self->set_typemap_entry($typeclass);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub process_atomic_type {
|
||||
my ( $self, $type, $callback ) = @_;
|
||||
return if not $type;
|
||||
|
||||
my $ident = ident $self;
|
||||
$callback->( $self, $type ) if $callback;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub visit_XSD_Element {
|
||||
my ( $self, $ident, $element ) = ( $_[0], ident $_[0], $_[1] );
|
||||
|
||||
# TODO: what about element ref="" ?
|
||||
# when we're hopping from one element to the next one...
|
||||
|
||||
# step down in tree
|
||||
$self->add_element_path( $element );
|
||||
|
||||
# now call all possible variants.
|
||||
# They all just return if no argument is given,
|
||||
# and return $self on success.
|
||||
SWITCH: {
|
||||
if ($element->get_type) {
|
||||
$self->process_referenced_type( $element->expand( $element->get_type() ) )
|
||||
&& last;
|
||||
}
|
||||
# for atomic simple and comples types , and ref elements
|
||||
my $typeclass = join q{::}, $element_prefix_of{$ident}, $element->get_name();
|
||||
|
||||
$self->set_typemap_entry($typeclass);
|
||||
|
||||
# kind of double-dispatch: returns true on success, but does nothing
|
||||
$self->process_atomic_type( $element->first_simpleType() )
|
||||
&& last;
|
||||
|
||||
$self->process_atomic_type( $element->first_complexType()
|
||||
, sub { $_[1]->_accept($_[0]) } )
|
||||
&& last;
|
||||
|
||||
# TODO: add element ref handling
|
||||
};
|
||||
# step up in hierarchy
|
||||
pop @{ $path_of{$ident} };
|
||||
}
|
||||
|
||||
sub visit_XSD_ComplexType {
|
||||
my ($self, $ident, $type) = ($_[0], ident $_[0], $_[1] );
|
||||
my $content_model = $type->get_flavor();
|
||||
# TODO is this allowed ? or should we better die ?
|
||||
return if not $content_model; # empty complexType
|
||||
|
||||
if ( grep { $_ eq $content_model} qw(all sequence choice) )
|
||||
{
|
||||
# visit child elements
|
||||
for (@{ $type->get_element() }) {
|
||||
$_->_accept( $self );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
warn "unsupported content model $content_model found in "
|
||||
. "complex type " . $type->get_name()
|
||||
. " - typemap may be incomplete";
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Manual - accessing WSDL based web services
|
||||
SOAP::WSDL::Manual - Accessing WSDL based web services
|
||||
|
||||
=head1 Accessing a WSDL-based web service
|
||||
|
||||
@@ -17,26 +17,28 @@ SOAP::WSDL::Manual - accessing WSDL based web services
|
||||
=item * Look what has been generated
|
||||
|
||||
Check the results of the generator. There should be one
|
||||
MyInterface/SERVICE_NAME.pm file per service.
|
||||
MyInterfaces/SERVICE_NAME/PORT_NAME.pm file per port (and one directory per
|
||||
service).
|
||||
|
||||
=item * Write script
|
||||
|
||||
use MyInterface::SERVICE_NAME;
|
||||
my $service = MyInterface::SERVICE_NAME->new();
|
||||
use MyInterface::SERVICE_NAME::PORT_NAME;
|
||||
my $service = MyInterface::SERVICE_NAME::PORT_NAME->new();
|
||||
|
||||
my $result = $service->SERVICE_METHOD();
|
||||
die $result if not $result;
|
||||
|
||||
print $result;
|
||||
|
||||
C<perldoc MyInterface::SERVICE_NAME> should give you some overview about
|
||||
the service's interface structure.
|
||||
C<perldoc MyInterface::SERVICE_NAME::PORT_NAME> should give you some overview
|
||||
about the service's interface structure.
|
||||
|
||||
The results of all calls to your service object's methods (except new)
|
||||
are objects based on SOAP::WSDL's XML schema implementation.
|
||||
The results of all calls to your service object's methods (except new) are
|
||||
objects based on SOAP::WSDL's XML schema implementation.
|
||||
|
||||
To access the object's properties use get_NAME / set_NAME getter/setter
|
||||
methods whith NAME corresponding to the XML tag name.
|
||||
To access the object's properties use get_NAME / set_NAME getter/setter
|
||||
methods whith NAME corresponding to the XML tag name / the hash structure as
|
||||
showed in the generated pod.
|
||||
|
||||
=item * Run script
|
||||
|
||||
@@ -68,11 +70,11 @@ The steps to instrument a web service with SOAP::WSDL perl bindings
|
||||
|
||||
=item * Gather web service information
|
||||
|
||||
You'll need to know at least a URL pointing to the web service's WSDL
|
||||
You'll need to know at least a URL pointing to the web service's WSDL
|
||||
definition.
|
||||
|
||||
If you already know more - like which methods the service provides, or
|
||||
how the XML messages look like, that's fine. All these things will help you
|
||||
If you already know more - like which methods the service provides, or how
|
||||
the XML messages look like, that's fine. All these things will help you
|
||||
later.
|
||||
|
||||
=item * Create WSDL bindings
|
||||
@@ -81,24 +83,24 @@ later.
|
||||
|
||||
This will generate the perl bindings in the directory specified by base_dir.
|
||||
|
||||
For more options, see L<wsdl2perl.pl> - you may want to specify class
|
||||
For more options, see L<wsdl2perl.pl> - you may want to specify class
|
||||
prefixes for XML type and element classes, type maps and interface classes,
|
||||
and you may even want to add custom typemap elements.
|
||||
|
||||
=item * Check the result
|
||||
|
||||
There should be a bunch of classes for types (in the MyTypes:: namespace by
|
||||
default), elements (in MyElements::), and at least one typemap
|
||||
(in MyTypemaps::) and one interface class (in MyInterfaces::).
|
||||
default), elements (in MyElements::), and at least one typemap (in
|
||||
MyTypemaps::) and one ore more interface classes (in MyInterfaces::).
|
||||
|
||||
If you don't already know the details of the web service you're going to
|
||||
instrument, it's now time to read the perldoc of the generated interface
|
||||
classes. It will tell you what methods each service provides, and which
|
||||
parameters they take.
|
||||
|
||||
If the WSDL definition is informative about what these methods do,
|
||||
the included perldoc will be, too.
|
||||
|
||||
If the WSDL definition is informative about what these methods do, the
|
||||
included perldoc will be, too - if not, blame the web service author.
|
||||
|
||||
=item * Write a perl script (or module) accessing the web service.
|
||||
|
||||
use MyInterface::SERVICE_NAME;
|
||||
@@ -113,8 +115,8 @@ strange - it is due to the nature of
|
||||
L<SOAP::WSDL::SOAP::Typelib::Fault11|SOAP::WSDL::SOAP::Typelib::Fault11>
|
||||
objects SOAP::WSDL uses for signalling failure.
|
||||
|
||||
These objects are false in boolean context, but serialize to their XML structure
|
||||
on stringification.
|
||||
These objects are false in boolean context, but serialize to their XML
|
||||
structure on stringification.
|
||||
|
||||
You may, of course, access individual fault properties, too. To get a list of
|
||||
fault properties, see L<SOAP::WSDL::SOAP::Typelib::Fault11>
|
||||
@@ -126,7 +128,7 @@ fault properties, see L<SOAP::WSDL::SOAP::Typelib::Fault11>
|
||||
Sometimes, WSDL definitions are incomplete. In most of these cases, proper
|
||||
fault definitions are missing. This means that though the specification sais
|
||||
nothing about it, Fault messages include extra elements in the
|
||||
E<lt>detailE<gt> section, or faults are even indicated by non-fault messages.
|
||||
E<lt>detailE<gt> section, or errors are even indicated by non-fault messages.
|
||||
|
||||
There are two steps you need to perform for adding additional information.
|
||||
|
||||
@@ -139,66 +141,145 @@ created.
|
||||
|
||||
It is strongly discouraged to use the same namespace for hand-written and
|
||||
generated classes - while generated classes may be many, you probably will
|
||||
only implement a few by hand. These (precious) few classes may get lost
|
||||
in the mass of (cheap) generated ones. Just imagine one of your co-workers
|
||||
(or even yourself) deleting the whole bunch and re-generating everything
|
||||
- oops - almost everything. You got the point.
|
||||
only implement a few by hand. These (precious) few classes may get lost in
|
||||
the mass of (cheap) generated ones. Just imagine one of your co-workers (or
|
||||
even yourself) deleting the whole bunch and re-generating everything - oops
|
||||
- almost everything. You got the point.
|
||||
|
||||
For simplicity, you probably just want to use builtin types wherever
|
||||
possible - you are probably not interested in whether a fault detail's
|
||||
error code is presented to you as a simpleType ranging from 1 to 10
|
||||
(which you have to write) or as a int (which is a builtin type ready
|
||||
to use).
|
||||
For simplicity, you probably just want to use builtin types wherever possible
|
||||
- you are probably not interested in whether a fault detail's error code is
|
||||
presented to you as a simpleType ranging from 1 to 10 (which you have to
|
||||
write) or as a int (which is a builtin type ready to use).
|
||||
|
||||
Using builtin types for simpleType definitions may greatly reduce the
|
||||
number of additional classes you need to implement.
|
||||
Using builtin types for simpleType definitions may greatly reduce the number
|
||||
of additional classes you need to implement.
|
||||
|
||||
If the extra type classes you need include E<lt>complexType E<gt>
|
||||
or E<lt>element /E<gt> definitions, see
|
||||
L<SOAP::WSDL::SOAP::Typelib::ComplexType> and
|
||||
L<SOAP::WSDL::SOAP::Typelib::Element> on how to create ComplexType
|
||||
and Element type classes.
|
||||
If the extra type classes you need include E<lt>complexType E<gt> or
|
||||
E<lt>element /E<gt> definitions, see L<SOAP::WSDL::SOAP::Typelib::ComplexType>
|
||||
and L<SOAP::WSDL::SOAP::Typelib::Element> on how to create ComplexType and
|
||||
Element type classes.
|
||||
|
||||
=item * Provide a typemap snippet to wsdl2perl.pl
|
||||
|
||||
SOAP::WSDL uses typemaps for finding out into which class' object
|
||||
a XML node should be transformed.
|
||||
SOAP::WSDL uses typemaps for finding out into which class' object a XML node
|
||||
should be transformed.
|
||||
|
||||
Typemaps basically map the path of every XML element inside the Body
|
||||
tag to a perl class.
|
||||
Typemaps basically map the path of every XML element inside the Body tag to a
|
||||
perl class.
|
||||
|
||||
Typemap snippets have to look like this (which is actually the
|
||||
default Fault typemap included in every generated one):
|
||||
Typemap snippets have to look like this (which is actually the default Fault
|
||||
typemap included in every generated one):
|
||||
|
||||
(
|
||||
'Fault' => 'SOAP::WSDL::SOAP::Typelib::Fault11',
|
||||
'Fault/faultcode' => 'SOAP::WSDL::XSD::Typelib::Builtin::anyURI',
|
||||
'Fault/faultactor' => 'SOAP::WSDL::XSD::Typelib::Builtin::anyURI',
|
||||
'Fault/faultstring' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
|
||||
'Fault/detail' => 'SOAP::WSDL::XSD::Typelib::Builtin::anyType',
|
||||
);
|
||||
|
||||
The lines are hash key - value pairs. The keys are the XPath
|
||||
expression relative to the Body element.
|
||||
The lines are hash key - value pairs. The keys are the XPath expressions
|
||||
without occurence numbers (like [1]) relative to the Body element.
|
||||
Namespaces are ignored.
|
||||
|
||||
If you don't know about XPath: They are just the names of the XML
|
||||
tags, starting from the one inside E<lt>BodyE<gt> up to the current
|
||||
one joined by /.
|
||||
If you don't know about XPath: They are just the names of the XML tags,
|
||||
starting from the one inside E<lt>BodyE<gt> up to the current one joined by /.
|
||||
|
||||
One line for every XML node is required.
|
||||
|
||||
You may use all builtin, generated or custom type class names as
|
||||
values.
|
||||
You may use all builtin, generated or custom type class names as values.
|
||||
|
||||
Use wsdl2perl.pl -mi=FILE to include custom typemap snippets.
|
||||
|
||||
Your extra statements are included last, so they override potential
|
||||
typemap statements with the same keys.
|
||||
Note that typemap include files for wsdl2perl.pl must evaluate to a valid
|
||||
perl hash - it will be imported via eval (OK, to be honest: via I<do $file>,
|
||||
but that's almost the same...).
|
||||
|
||||
Your extra statements are included last, so they override potential typemap
|
||||
statements with the same keys.
|
||||
|
||||
=back
|
||||
|
||||
=head1 Accessing a web service without a WSDL definition
|
||||
|
||||
Accessing a web service without a WSDL definition is more cumbersome. There
|
||||
are two ways to go:
|
||||
|
||||
=over
|
||||
|
||||
=item * Write a WSDL definition and generate interface
|
||||
|
||||
This is the way to go if you already are experienced in writing WSDL files.
|
||||
If you are not, be warned: Writing a correct WSDL is not an easy task, and
|
||||
writing correct WSDL files with only a text editor is almost impossible.
|
||||
|
||||
You should definitely use a WSDL editor. The WSDL editor should support
|
||||
conformance checks for the WS-I Basic Profile (1.0 is preferred by
|
||||
SOAP::WSDL)
|
||||
|
||||
=item * Write a typemap and class library from scratch
|
||||
|
||||
If the web service is relatively simple, this is probably easier than first
|
||||
writing a WSDL definition. Besides, it can be done in perl, a language you
|
||||
are probably more familiar with than WSDL.
|
||||
|
||||
L<SOAP::WSDL::XSD::Typelib::ComplexType>, L<SOAP::WSDL::XSD::Typelib::SimpleType> and
|
||||
L<SOAP::WSDL::XSD::Typelib::Element> tell you how to create subclasses of XML schema
|
||||
types.
|
||||
|
||||
L<SOAP::WSDL::Parser> will tell you how to create a typemap class.
|
||||
|
||||
=back
|
||||
|
||||
=head1 Troubleshooting
|
||||
|
||||
=head2 Accessing HTTPS webservices
|
||||
|
||||
You need Crypt::SSLeay installed to access HTTPS webservices.
|
||||
|
||||
=head2 Accessing protected web services
|
||||
|
||||
Passing a userndame and password, or a client certificate and key, to the
|
||||
transport layer is highly dependent on the transport backend.
|
||||
|
||||
=head3 Accessing HTTP(S) webservices with basic/digest authentication
|
||||
|
||||
When using SOAP::WSDL::Transport::HTTP (SOAP::Lite not installed), add a
|
||||
method called "get_basic_credentials" to SOAP::WSDL::Transport::HTTP:
|
||||
|
||||
*SOAP::WSDL::Transport::HTTP::get_basic_credentials = sub {
|
||||
return ($user, $password);
|
||||
};
|
||||
|
||||
When using SOAP::Transport::HTTP (SOAP::Lite is installed), do the same to
|
||||
this backend:
|
||||
|
||||
*SOAP::Transport::HTTP::get_basic_credentials = sub {
|
||||
return ($user, $password);
|
||||
};
|
||||
|
||||
=head3 Accessing HTTP(S) webservices protected by NTLM authentication
|
||||
|
||||
Besides passing user credentials as when accessing a web service protected
|
||||
by basic or digest authentication, you also need to enforce connection
|
||||
keep_alive on the transport backens.
|
||||
|
||||
To do so, pass a I<proxy> argument to the new() method of the generated
|
||||
class. This unfortunately means that you have to set the endpoint URL, too:
|
||||
|
||||
my $interface = MyInterfaces::SERVICE_NAME::PORT_NAME->new({
|
||||
proxy => [ $url, keep_alive => 1 ]
|
||||
});
|
||||
|
||||
You may, of course, decide to just hack the generated class. Be advised that
|
||||
subclassing might be a more appropriate solution - re-generating overwrites
|
||||
your changes.
|
||||
|
||||
=head3 Accessing HTTPS webservices protected by certificate authentication
|
||||
|
||||
You need Crypt::SSLeay installed to access HTTPS webservices.
|
||||
|
||||
See L<Crypt::SSLeay> on how to configure client certificate authentication.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ SOAP::WSDL obeys the part order.
|
||||
global element declaration referenced by the corresponding wsdl:message
|
||||
part.
|
||||
|
||||
If defined accordinglyin tehe DESCRIPTION, SOAP::WSDL issues
|
||||
If defined accordingly in the DESCRIPTION, SOAP::WSDL issues
|
||||
document-literal binding operation MESSAGES conforming to this rule.
|
||||
|
||||
=head2 R2748
|
||||
@@ -306,8 +306,6 @@ element, yet.
|
||||
|
||||
=head1 RULES NOT CONFIRMED
|
||||
|
||||
|
||||
|
||||
=head2 R4001
|
||||
|
||||
A RECEIVER MUST accept messages that include the Unicode Byte Order Mark
|
||||
@@ -432,12 +430,8 @@ be used.
|
||||
|
||||
TODO become "minimal conformant".
|
||||
|
||||
|
||||
|
||||
=head1 RULES NOT APPLICABLE
|
||||
|
||||
|
||||
|
||||
=head2 R0004
|
||||
|
||||
A MESSAGE MAY contain conformance claims, as specified in the conformance claim schema.
|
||||
|
||||
249
lib/SOAP/WSDL/Manual/XSD.pod
Normal file
249
lib/SOAP/WSDL/Manual/XSD.pod
Normal file
@@ -0,0 +1,249 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::XSD - SOAP::WSDL's XML Schema implementation
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SOAP::WSDL's XML Schema implementation translates XML Schema definitions into
|
||||
perl classes.
|
||||
|
||||
Every top-level type or element in a XML schema is translated into a perl
|
||||
class (usually in it's own file).
|
||||
|
||||
Atomic types are either directly included in the class of their parent's
|
||||
node, or as sub-package in their parent class' file.
|
||||
|
||||
=head2 Base classes
|
||||
|
||||
SOAP::WSDL::XSD provides a set of base classes for the construction of XML
|
||||
schema defined type classes.
|
||||
|
||||
=head3 Builtin types
|
||||
|
||||
SOAP::WSDL::XSD provides classes for all builtin XML Schema datatypes.
|
||||
|
||||
For a list and reference on these classes, see
|
||||
SOAP::WSDL::XSD::Typelib::Builtin.
|
||||
|
||||
=head3 Derivation classes
|
||||
|
||||
For derivation by list, the list derivation class
|
||||
SOAP::WSDL::XSD::Typelib::Builtin::list exists.
|
||||
|
||||
Derivation by restriction is handled without the help of additional classes.
|
||||
|
||||
=head3 Element construction class
|
||||
|
||||
For the construction of element classes, the element superclass
|
||||
SOAP::WSDL::XSD::Typelib::Element exists. All elements are ultimately derived
|
||||
from this class. Elements may inherit from type classes, too - see
|
||||
L</TRANSLATION RULES> for details.
|
||||
|
||||
=head3 complexType construction class
|
||||
|
||||
For the construction of complexType classes, the
|
||||
|
||||
=head1 TRANSLATION RULES
|
||||
|
||||
=head2 element
|
||||
|
||||
TODO add more elaborate description
|
||||
|
||||
=head3 element with type attribute
|
||||
|
||||
Elements defined by referencing a builtin or user defined type inherit
|
||||
from SOAP::WSDL::XSD::Typelib::Element and from the corresponding type class.
|
||||
|
||||
Element Type
|
||||
base class class
|
||||
^ ^
|
||||
| |
|
||||
------------
|
||||
|
|
||||
Element type="" class
|
||||
|
||||
=head3 element with ref attribute
|
||||
|
||||
Elements defined by referencing another element inherit from the
|
||||
corresponding element class.
|
||||
|
||||
referenced Element class
|
||||
^
|
||||
|
|
||||
Element ref="" class
|
||||
|
||||
=head3 element with atomic simpleType
|
||||
|
||||
Elements defined by a atomic simpleType from
|
||||
SOAP::WSDL::XSD::Typelib::Element and from the base type of the atomic type.
|
||||
|
||||
Element atomic Type
|
||||
base class base class
|
||||
^ ^
|
||||
| |
|
||||
-------------
|
||||
|
|
||||
element simpleType class
|
||||
|
||||
=head3 element with atomic complexType
|
||||
|
||||
Elements defined with a atomic complexType inherit from
|
||||
SOAP::WSDL::XSD::Typelib::Element and from
|
||||
SOAP::WSDL::XSD::Typelib::ComplexType.
|
||||
|
||||
Element complexType
|
||||
base class base class
|
||||
^ ^
|
||||
| |
|
||||
-------------
|
||||
|
|
||||
element complexType class
|
||||
|
||||
=head2 complexType
|
||||
|
||||
TODO add more elaborate description
|
||||
|
||||
Some content models are not implemented yet. The content models
|
||||
implemented are described below.
|
||||
|
||||
=head3 complexType with "sequence" variety
|
||||
|
||||
=head3 complexType with "all" variety
|
||||
|
||||
The implementation for all does enforce the order of elements as described
|
||||
in the WSDL, even though this is not required by the XML Schema
|
||||
specification.
|
||||
|
||||
=head3 complexType with "choice" variety
|
||||
|
||||
The implementation for choice currently is the same as for all - which means,
|
||||
no check for occurence are made.
|
||||
|
||||
=head3 complexType with complexContent content model
|
||||
|
||||
=over
|
||||
|
||||
=item * restriction variety
|
||||
|
||||
ComplexType classes with restriction variety inherit from their base type.
|
||||
No additional processing or content checking is performed yet.
|
||||
|
||||
Note that complexType with restriction variety classes don't exhibit their
|
||||
type via the xsi:type attribute yet, so they currently cannot be used as
|
||||
a replacement for their base type.
|
||||
|
||||
=item * extension variety
|
||||
|
||||
=back
|
||||
|
||||
=head2 SimpleType
|
||||
|
||||
TODO add more elaborate description
|
||||
|
||||
Some derivation methods are not implemented yet. The derivation methods
|
||||
implemented are described below.
|
||||
|
||||
=head3 Derivation by list
|
||||
|
||||
Derivation by list is implemented by inheriting from both the base type and
|
||||
SOAP::WSDL::XSD::Typelib::XSD::list.
|
||||
|
||||
=head3 Derivation by restriction
|
||||
|
||||
Derivation by restriction is implemented by inheriting from a base type and
|
||||
applying the required restrictions.
|
||||
|
||||
=head2 Complex Types
|
||||
|
||||
=head1 FACETS
|
||||
|
||||
XML Schema facets are not implemented yet.
|
||||
|
||||
They will probably implemented some day by putting constant methods into
|
||||
the correspondent classes.
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
XML attributes are not implemented yet. If you have a good idea on how to
|
||||
implement them, feel free to email me a proposal.
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
The following XML Schema declaration elements are not supported yet:
|
||||
|
||||
=over
|
||||
|
||||
=item * Declaration elements
|
||||
|
||||
attribute
|
||||
notation
|
||||
|
||||
=item * Type definition elements
|
||||
|
||||
complexContent - only restriction supported
|
||||
simpleContent
|
||||
union
|
||||
|
||||
=item * Content model definition elements
|
||||
|
||||
any
|
||||
anyAttribute
|
||||
attributeGroup
|
||||
group
|
||||
|
||||
=item * Identity definition elements
|
||||
|
||||
field
|
||||
key
|
||||
keyref
|
||||
selector
|
||||
unique
|
||||
|
||||
=item * Inclusion elements
|
||||
|
||||
import
|
||||
include
|
||||
redefine
|
||||
|
||||
=back
|
||||
|
||||
The following XML Schema declaration elements are supported, but have no
|
||||
effect yet:
|
||||
|
||||
=over
|
||||
|
||||
=item * Factes
|
||||
|
||||
enumeration
|
||||
fractionDigits
|
||||
lenght
|
||||
maxExclusive
|
||||
maxInclusiove
|
||||
maxLength
|
||||
minExclusive
|
||||
minInclusive
|
||||
minLength
|
||||
pattern
|
||||
totalDigits
|
||||
whitespace
|
||||
|
||||
=item * Documentation elements
|
||||
|
||||
appinfo
|
||||
|
||||
=back
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2007 Martin Kutter.
|
||||
|
||||
This file is part of SOAP-WSDL. You may distribute/modify it under
|
||||
the same terms as perl itself
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=cut
|
||||
@@ -4,61 +4,9 @@ use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
my %body_of :ATTR(:name<body> :default<()>);
|
||||
my %message_of :ATTR(:name<message> :default<()>);
|
||||
my %use_of :ATTR(:name<use> :default<()>);
|
||||
my %namespace :ATTR(:name<namespace> :default<()>);
|
||||
my %encodingStyle_of :ATTR(:name<encodingStyle> :default<()>);
|
||||
|
||||
sub explain
|
||||
{
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $name = shift;
|
||||
my $txt = '';
|
||||
|
||||
my %ns_map = reverse %{ $opt->{ wsdl }->get_xmlns() };
|
||||
|
||||
if ( $self->get_message() ) {
|
||||
|
||||
my ($prefix, $localname) = split /:/ , $self->get_message();
|
||||
|
||||
# TODO allow more messages && overloading by specifying name
|
||||
my $message = $opt->{ wsdl }->get_message(
|
||||
$ns_map{ $prefix }, $localname
|
||||
);
|
||||
|
||||
for my $part(@{ $message->[0]->get_part() }) {
|
||||
$txt .= $part->explain($opt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($self->use())
|
||||
{
|
||||
$txt .= " $name use: " . $self->use(). "\n";
|
||||
}
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
|
||||
my ($self, $opt) = @_;
|
||||
my $txt = q{};
|
||||
return q{} if not ( $self->get_message() ); # we're in binding
|
||||
my %ns_map = reverse %{ $opt->{ wsdl }->get_xmlns() };
|
||||
my ($prefix, $localname) = split /:/ , $self->get_message();
|
||||
|
||||
# TODO allow more messages && overloading by specifying name
|
||||
my $message = $opt->{ wsdl }->find_message(
|
||||
$ns_map{ $prefix }, $localname
|
||||
);
|
||||
|
||||
for my $part(@{ $message->get_part() }) {
|
||||
$txt .= $part->to_typemap($opt);
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
my %body_of :ATTR(:name<body> :default<[]>);
|
||||
my %header_of :ATTR(:name<header> :default<[]>);
|
||||
my %headerfault_of :ATTR(:name<headerfault> :default<[]>);
|
||||
my %message_of :ATTR(:name<message> :default<()>);
|
||||
|
||||
1;
|
||||
|
||||
@@ -4,18 +4,13 @@ use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw/SOAP::WSDL::Base/;
|
||||
|
||||
# this class may be used for both soap::operation and wsdl::operation.
|
||||
# which one it is depends on context...
|
||||
|
||||
my %operation_of :ATTR(:name<operation> :default<()>);
|
||||
my %input_of :ATTR(:name<input> :default<()>);
|
||||
my %output_of :ATTR(:name<output> :default<()>);
|
||||
my %fault_of :ATTR(:name<fault> :default<()>);
|
||||
my %input_of :ATTR(:name<input> :default<[]>);
|
||||
my %output_of :ATTR(:name<output> :default<[]>);
|
||||
my %fault_of :ATTR(:name<fault> :default<[]>);
|
||||
my %type_of :ATTR(:name<type> :default<()>);
|
||||
my %style_of :ATTR(:name<style> :default<()>);
|
||||
my %transport_of :ATTR(:name<transport> :default<()>);
|
||||
my %parameterOrder_of :ATTR(:name<parameterOrder> :default<()>);
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ SOAP::WSDL::Parser - How SOAP::WSDL parses XML messages
|
||||
|
||||
=head1 Which XML message does SOAP::WSDL parse ?
|
||||
|
||||
Naturally, there are two kinds of XML documents (or messages)
|
||||
SOAP::WSDL has to parse:
|
||||
Naturally, there are two kinds of XML documents (or messages) SOAP::WSDL has
|
||||
to parse:
|
||||
|
||||
=over
|
||||
|
||||
@@ -19,15 +19,15 @@ SOAP::WSDL has to parse:
|
||||
|
||||
=head1 Parser implementations
|
||||
|
||||
There are different parser implementations available for SOAP messages
|
||||
and WSDL definitions.
|
||||
There are different parser implementations available for SOAP messages and
|
||||
WSDL definitions.
|
||||
|
||||
Historically, SOAP::WSDL used SAX for parsing XML. The SAX handlers
|
||||
were implemented as L<XML::LibXML|XML::LibXML> handlers, which
|
||||
also worked with L<XML::SAX::ParserFactory|XML::SAX::ParserFactory>.
|
||||
Historically, SOAP::WSDL used SAX for parsing XML. The SAX handlers were
|
||||
implemented as L<XML::LibXML|XML::LibXML> handlers, which also worked with
|
||||
L<XML::SAX::ParserFactory|XML::SAX::ParserFactory>.
|
||||
|
||||
The use of SAX and L<XML::LibXML|XML::LibXML> in SOAP::WSDL is
|
||||
deprecated for the following reasons:
|
||||
Support for SAX and L<XML::LibXML|XML::LibXML> in SOAP::WSDL is discontinued
|
||||
for the following reasons:
|
||||
|
||||
=over
|
||||
|
||||
@@ -36,10 +36,13 @@ deprecated for the following reasons:
|
||||
L<XML::Parser::Expat|XML::Parser::Expat> is faster than
|
||||
L<XML::LibXML|XML::LibXML> - at least when optimized for speed.
|
||||
|
||||
High parsing speed is one of the key requirements for a SOAP toolkit - if XML
|
||||
serializing and (more important) deserializing are not fast enough, the whole
|
||||
toolkit is unusable.
|
||||
|
||||
=item * Availability
|
||||
|
||||
L<XML::Parser|XML::Parser> is more popular than
|
||||
L<XML::LibXML|XML::LibXML>.
|
||||
L<XML::Parser|XML::Parser> is more popular than L<XML::LibXML|XML::LibXML>.
|
||||
|
||||
=item * Stability
|
||||
|
||||
@@ -49,6 +52,9 @@ often several versions of libxml2 installed on one system. This may
|
||||
lead to problems on operating systems which cannot load more than
|
||||
one version of a shared library simultaneously.
|
||||
|
||||
XML::LibXML is also still under development, while XML::Parser has had time
|
||||
to stabilize.
|
||||
|
||||
=item * SOAP::Lite uses XML::Parser
|
||||
|
||||
L<SOAP::Lite|SOAP::Lite> uses L<XML::Parser|XML::Parser> if available.
|
||||
@@ -68,32 +74,6 @@ A parser for WSDL definitions based on L<XML::Parser::Expat|XML::Parser::Expat>.
|
||||
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
|
||||
my $wsdl = $parser->parse_file( $filename );
|
||||
|
||||
=item * SOAP::WSDL::SAX::WSDLHandler
|
||||
|
||||
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
|
||||
works with.
|
||||
|
||||
It's built as a native handler for XML::LibXML, but will also work with
|
||||
XML::SAX::ParserFactory.
|
||||
|
||||
To parse a WSDL file, use one of the following variants:
|
||||
|
||||
my $parser = XML::LibXML->new();
|
||||
my $handler = SOAP::WSDL::SAX::WSDLHandler->new();
|
||||
$parser->set_handler( $handler );
|
||||
$parser->parse( $xml );
|
||||
my $data = $handler->get_data();
|
||||
|
||||
|
||||
my $handler = SOAP::WSDL::SAX::WSDLHandler->new({
|
||||
base => 'XML::SAX::Base'
|
||||
});
|
||||
my $parser = XML::SAX::ParserFactor->parser(
|
||||
Handler => $handler
|
||||
);
|
||||
$parser->parse( $xml );
|
||||
my $data = $handler->get_data();
|
||||
|
||||
=back
|
||||
|
||||
=head2 SOAP messages parser
|
||||
@@ -187,18 +167,6 @@ as you don't need to keep everything in memory.
|
||||
See L<SOAP::WSDL::Expat::MessageStreamParser|SOAP::WSDL::Expat::MessageStreamParser>
|
||||
for details.
|
||||
|
||||
=item * SOAP::WSDL::SAX::MessageHandler
|
||||
|
||||
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
|
||||
works with.
|
||||
|
||||
It's built as a native handler for XML::LibXML, but will also work with
|
||||
XML::SAX::ParserFactory.
|
||||
|
||||
Can be used for parsing both streams (chunks) and documents.
|
||||
|
||||
See L<SOAP::WSDL::SAX::MessageHandler> for details.
|
||||
|
||||
=back
|
||||
|
||||
=head3 Performance
|
||||
@@ -241,4 +209,56 @@ to a response size of around 500k:
|
||||
|
||||
Response size: 344330 bytes
|
||||
|
||||
=head1 OLD SAX HANDLER
|
||||
|
||||
The old SAX handler historically used in SOAP::WSDL are not included in
|
||||
the SOAP::WSDL package any more.
|
||||
|
||||
However, they may be obtained from the "attic" directory in
|
||||
SOAP::WSDL's SVN repository at
|
||||
|
||||
https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/attic
|
||||
|
||||
=over
|
||||
|
||||
=item * SOAP::WSDL::SAX::WSDLHandler
|
||||
|
||||
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
|
||||
works with.
|
||||
|
||||
It's built as a native handler for XML::LibXML, but will also work with
|
||||
XML::SAX::ParserFactory.
|
||||
|
||||
To parse a WSDL file, use one of the following variants:
|
||||
|
||||
my $parser = XML::LibXML->new();
|
||||
my $handler = SOAP::WSDL::SAX::WSDLHandler->new();
|
||||
$parser->set_handler( $handler );
|
||||
$parser->parse( $xml );
|
||||
my $data = $handler->get_data();
|
||||
|
||||
|
||||
my $handler = SOAP::WSDL::SAX::WSDLHandler->new({
|
||||
base => 'XML::SAX::Base'
|
||||
});
|
||||
my $parser = XML::SAX::ParserFactor->parser(
|
||||
Handler => $handler
|
||||
);
|
||||
$parser->parse( $xml );
|
||||
my $data = $handler->get_data();
|
||||
|
||||
|
||||
=item * SOAP::WSDL::SAX::MessageHandler
|
||||
|
||||
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
|
||||
works with.
|
||||
|
||||
It's built as a native handler for XML::LibXML, but will also work with
|
||||
XML::SAX::ParserFactory.
|
||||
|
||||
Can be used for parsing both streams (chunks) and documents.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=cut
|
||||
@@ -41,49 +41,4 @@ sub serialize
|
||||
die "Neither type nor element - don't know what to do";
|
||||
}
|
||||
|
||||
sub explain {
|
||||
my ($self, $opt, $name ) = @_;
|
||||
my $typelib = $opt->{ wsdl }->first_types() || die "No typelib";
|
||||
my $element = $self->get_type() || $self->get_element();
|
||||
|
||||
# resolve type
|
||||
my $type = $typelib->find_type( $opt->{ wsdl }->_expand( $element ) )
|
||||
|| $typelib->find_element( $opt->{ wsdl }->_expand( $element ) );
|
||||
|
||||
if (not $type)
|
||||
{
|
||||
warn "no type/element $element found for part " . $self->get_name();
|
||||
return q{};
|
||||
}
|
||||
return " {\n" . $type->explain( $opt, $self->get_name() ) . " }\n";
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
my ($self, $opt, $name ) = @_;
|
||||
my $txt = q{};
|
||||
my $wsdl = $opt->{ wsdl };
|
||||
my $typelib = $opt->{ wsdl }->first_types()
|
||||
|| die "No typelib";
|
||||
|
||||
# resolve type
|
||||
my $type;
|
||||
if (my $type_name = $self->get_type()) {
|
||||
$type = $typelib->find_type( $wsdl->_expand( $type_name ) )
|
||||
|| croak "no type/element $type_name found for part " . $self->get_name();
|
||||
$txt .= "q{} => " . $type->get_name() . "\n";
|
||||
}
|
||||
elsif ( my $element_name = $self->get_element() ) {
|
||||
$type = $typelib->find_element( $wsdl->_expand( $element_name ) )
|
||||
|| croak "no type/element $element_name found for part " . $self->get_name();
|
||||
}
|
||||
else {
|
||||
warn 'neither type nor element - do not know what to do for part '
|
||||
. $self->get_name();
|
||||
return q{};
|
||||
}
|
||||
$opt->{ path } = [];
|
||||
$txt .= $type->to_typemap( $opt, $self->get_name() );
|
||||
return $txt;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -5,39 +5,6 @@ use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
my %binding_of :ATTR(:name<binding> :default<()>);
|
||||
my %location_of :ATTR(:name<location> :default<()>);
|
||||
my %address_of :ATTR(:name<address> :default<()>);
|
||||
|
||||
sub explain {
|
||||
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
$opt->{ wsdl } || die 'required attribute wsdl missing';
|
||||
|
||||
my $binding = $opt->{ wsdl }->find_binding(
|
||||
$opt->{ wsdl }->_expand( $self->get_binding() )
|
||||
) or die 'binding ' . $self->get_binding() . ' not found !';
|
||||
|
||||
|
||||
my $txt = "=head2 Service information:\n\n"
|
||||
. " Port name: " . $self->get_name() . "\n"
|
||||
. " Binding: " . $self->get_binding() ."\n"
|
||||
. " Location: " . $self->get_location() ."\n"
|
||||
. $binding->explain($opt);
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
|
||||
# skip non-SOAP ports (could be http, email or whatever...)
|
||||
return q{} if not $location_of{ ident $self };
|
||||
|
||||
my $binding = $opt->{ wsdl }->find_binding(
|
||||
$opt->{wsdl}->_expand( $binding_of{ ident $self } )
|
||||
) or die 'binding ' . $binding_of{ ident $self } .' not found!';
|
||||
|
||||
return $binding->to_typemap($opt);
|
||||
}
|
||||
1;
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
package SOAP::WSDL::SAX::MessageHandler;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Scalar::Util qw(blessed);
|
||||
use Class::Std::Storable;
|
||||
use SOAP::WSDL::XSD::Typelib::Builtin;
|
||||
|
||||
my %characters_of :ATTR(:default<()>);
|
||||
my %class_resolver_of :ATTR(:default<()> :name<class_resolver>);
|
||||
my %current_of :ATTR(:default<()>);
|
||||
my %ignore_of :ATTR(:default<()>);
|
||||
my %list_of :ATTR(:default<()>);
|
||||
my %namespace_of :ATTR(:default<()>);
|
||||
my %path_of :ATTR(:default<()>);
|
||||
my %data_of :ATTR(:default<()>);
|
||||
|
||||
{
|
||||
# we have to implement our own new - we need a blessed Hash ref as $self
|
||||
# for being able to inherit from XML::SAX::Base...
|
||||
no warnings qw(redefine);
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = {}; # $class->SUPER::new(@_);
|
||||
my $args = shift || {};
|
||||
|
||||
die "arguments to new must be single hash ref"
|
||||
if @_ or ! ref $args eq 'HASH';
|
||||
|
||||
# nasty, but for those who want to use XML::SAX::Base or similar
|
||||
# as parser factory
|
||||
if ($args->{base}) {
|
||||
# yup, naughty string eval
|
||||
eval "use base qw($args->{base})"; ## no critic qw(ProhibitStringyEval)
|
||||
}
|
||||
else {
|
||||
# create all those SAX methods...
|
||||
# ...we ignore em all...
|
||||
no strict qw(refs);
|
||||
foreach my $method ( qw(
|
||||
processing_instruction
|
||||
ignorable_whitespace
|
||||
set_document_locator
|
||||
start_prefix_mapping
|
||||
end_prefix_mapping
|
||||
skipped_entity
|
||||
start_cdata
|
||||
end_cdata
|
||||
comment
|
||||
entity_reference
|
||||
notation_decl
|
||||
unparsed_entity_decl
|
||||
element_decl
|
||||
attlist_decl
|
||||
doctype_decl
|
||||
xml_decl
|
||||
entity_decl
|
||||
attribute_decl
|
||||
internal_entity_decl
|
||||
external_entity_decl
|
||||
resolve_entity
|
||||
start_dtd
|
||||
end_dtd
|
||||
start_entity
|
||||
end_entity
|
||||
warning
|
||||
) ) {
|
||||
*{ "$method" } = sub {};
|
||||
}
|
||||
}
|
||||
|
||||
$class_resolver_of{ ident $self } = $args->{ class_resolver }
|
||||
if $args->{ class_resolver };
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
}
|
||||
|
||||
sub class_resolver {
|
||||
my $self = shift;
|
||||
$class_resolver_of{ ident $self } = shift;
|
||||
}
|
||||
|
||||
sub start_document {
|
||||
my $ident = ident $_[0];
|
||||
$list_of{ $ident } = [];
|
||||
$current_of{ $ident } = '__STOP__'; # use as marker
|
||||
$namespace_of{ $ident } = {};
|
||||
$ignore_of{ $ident } = [ qw(Envelope Body) ]; # SOAP elements
|
||||
$path_of{ $ident } = [];
|
||||
$data_of{ $ident } = undef;
|
||||
}
|
||||
|
||||
sub start_element {
|
||||
# use $_[n] for performance
|
||||
my ($ident, $element) = (ident $_[0], $_[1]);
|
||||
|
||||
# ignore top level elements
|
||||
if (@{ $ignore_of{ $ident } }
|
||||
&& $element->{ LocalName } eq $ignore_of{ $ident }->[0]) {
|
||||
shift @{ $ignore_of{ $ident } };
|
||||
return;
|
||||
}
|
||||
|
||||
# empty characters
|
||||
$characters_of{ $ident } = q{};
|
||||
|
||||
push @{ $path_of{ $ident } }, $element->{ LocalName }; # step down...
|
||||
push @{ $list_of{ $ident } }, $current_of{ $ident }; # remember current
|
||||
|
||||
# resolve class of this element
|
||||
my $class = $class_resolver_of{ $ident }->get_class( $path_of{ $ident } )
|
||||
or die "Cannot resolve class for "
|
||||
. join('/', @{ $path_of{ $ident } })
|
||||
. " via "
|
||||
. $class_resolver_of{ $ident };
|
||||
|
||||
# Check whether we have a primitive - we implement them as classes
|
||||
# TODO replace with UNIVERSAL->isa()
|
||||
# match is a bit faster if the string does not match, but WAY slower
|
||||
# if $class matches...
|
||||
# if (not $class=~m{^SOAP::WSDL::XSD::Typelib::Builtin}xms) {
|
||||
if (index $class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
|
||||
|
||||
# check wheter there is a CODE reference for $class::new.
|
||||
# If not, require it - all classes required here MUST
|
||||
# define new()
|
||||
# This is the same as $class->can('new'), but it's way faster
|
||||
no strict qw(refs);
|
||||
*{ "$class\::new" }{ CODE }
|
||||
or eval "require $class" ## no critic qw(ProhibitStringyEval)
|
||||
or die $@;
|
||||
}
|
||||
# create object
|
||||
# set current object
|
||||
$current_of{ $ident } = $class->new({
|
||||
map { $_->{ Name } => $_->{ Value } }
|
||||
values %{ $element->{ Attributes } }
|
||||
});
|
||||
|
||||
# remember top level element
|
||||
defined $data_of{ $ident }
|
||||
or ($data_of{ $ident } = $current_of{ $ident });
|
||||
}
|
||||
|
||||
sub characters {
|
||||
$characters_of{ ident $_[0] } .= $_[1]->{ Data };
|
||||
}
|
||||
|
||||
sub end_element {
|
||||
# $_[n] used for performance
|
||||
my ($ident, $element) = (ident $_[0], $_[1]);
|
||||
|
||||
# This one easily handles ignores for us, too...
|
||||
return if not ref $list_of{ $ident }->[-1];
|
||||
|
||||
if ( $current_of{ $ident }
|
||||
->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') ) {
|
||||
$current_of{ $ident }->set_value( $characters_of{ $ident } );
|
||||
}
|
||||
|
||||
# set appropriate attribute in last element
|
||||
# multiple values must be implemented in base class
|
||||
my $method = "add_$element->{ LocalName }";
|
||||
|
||||
$list_of{ $ident }->[-1]->$method( $current_of{ $ident } );
|
||||
|
||||
# step up in path
|
||||
pop @{ $path_of{ $ident } };
|
||||
|
||||
# step up in object hierarchy...
|
||||
$current_of{ $ident } = pop @{ $list_of{ $ident } };
|
||||
}
|
||||
|
||||
sub end_document {
|
||||
my $self = shift;
|
||||
my $ident = ident $self;
|
||||
|
||||
# destroy all remains except data_of
|
||||
$list_of{ $ident } = ();
|
||||
$namespace_of{ $ident } = ();
|
||||
$ignore_of{ $ident } = ();
|
||||
$path_of{ $ident } = ();
|
||||
$characters_of{ $ident } = ();
|
||||
}
|
||||
|
||||
sub get_data {
|
||||
my $self = shift;
|
||||
return $data_of{ ident $self };
|
||||
}
|
||||
|
||||
sub fatal_error {
|
||||
my $self = shift;
|
||||
die "Fatal error parsing document: " , @_;
|
||||
}
|
||||
|
||||
sub error {
|
||||
my $self = shift;
|
||||
die "Error parsing document: " , @_;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::SAX::MessageHandler - Convert SOAP messages to custom object trees
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# 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::SAX::ParserFactor->parser(
|
||||
Handler => $handler
|
||||
);
|
||||
$parser->parse_string( $soap_message );
|
||||
|
||||
my $object_tree = $filter->get_data();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SAX handler for parsing SOAP messages.
|
||||
|
||||
See L<SOAP::WSDL::Parser> for details.
|
||||
|
||||
=head1 Bugs and Limitations
|
||||
|
||||
=over
|
||||
|
||||
=item * Ignores all namespaces
|
||||
|
||||
=item * Does not handle mixed content
|
||||
|
||||
=item * The SOAP header is ignored
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Replace the whitespace by @ for E-Mail Address.
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 COPYING
|
||||
|
||||
This module may be used under the same terms as perl itself.
|
||||
|
||||
=head1 Repository information
|
||||
|
||||
$ID: $
|
||||
|
||||
$LastChangedDate: 2007-09-10 17:54:52 +0200 (Mo, 10 Sep 2007) $
|
||||
$LastChangedRevision: 214 $
|
||||
$LastChangedBy: kutterma $
|
||||
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/SAX/MessageHandler.pm $
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
package SOAP::WSDL::SAX::WSDLHandler;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
use Class::Std::Storable;
|
||||
use SOAP::WSDL::TypeLookup;
|
||||
|
||||
my %tree_of :ATTR(:name<tree> :default<{}>);
|
||||
my %order_of :ATTR(:name<order> :default<[]>);
|
||||
my %targetNamespace_of :ATTR(:name<targetNamespace> :default<()>);
|
||||
my %current_of :ATTR(:name<current> :default<()>);
|
||||
my %characters_of :ATTR();
|
||||
|
||||
{
|
||||
# we have to implement our own new - we need a blessed Hash ref as $self
|
||||
# for being able to inherit from XML::SAX::Base...
|
||||
no warnings qw(redefine);
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = {}; # $class->SUPER::new(@_);
|
||||
my $args = shift || {};
|
||||
|
||||
die "arguments to new must be single hash ref"
|
||||
if @_ or ! ref $args eq 'HASH';
|
||||
|
||||
# nasty, but for those who want to use XML::SAX::Base or similar
|
||||
# as parser factory
|
||||
if ($args->{base}) {
|
||||
# yup, naughty string eval
|
||||
eval "use base qw($args->{base})"; ## no critic qw(ProhibitStringyEval)
|
||||
}
|
||||
else {
|
||||
# create all those SAX methods...
|
||||
# ...we ignore em all...
|
||||
no strict qw(refs);
|
||||
foreach my $method ( qw(
|
||||
processing_instruction
|
||||
ignorable_whitespace
|
||||
set_document_locator
|
||||
start_prefix_mapping
|
||||
end_prefix_mapping
|
||||
skipped_entity
|
||||
start_cdata
|
||||
end_cdata
|
||||
comment
|
||||
entity_reference
|
||||
notation_decl
|
||||
unparsed_entity_decl
|
||||
element_decl
|
||||
attlist_decl
|
||||
doctype_decl
|
||||
xml_decl
|
||||
entity_decl
|
||||
attribute_decl
|
||||
internal_entity_decl
|
||||
external_entity_decl
|
||||
resolve_entity
|
||||
start_dtd
|
||||
end_dtd
|
||||
start_entity
|
||||
end_entity
|
||||
warning
|
||||
error
|
||||
) ) {
|
||||
*{ "$method" } = sub {};
|
||||
}
|
||||
}
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
};
|
||||
|
||||
sub start_document {
|
||||
my $ident = ident $_[0];
|
||||
$tree_of{ $ident } = {};
|
||||
$order_of{ $ident } = [];
|
||||
$targetNamespace_of{ $ident } = undef;
|
||||
$current_of{ $ident } = undef;
|
||||
}
|
||||
|
||||
sub start_element {
|
||||
my ($self, $element) = @_;
|
||||
my $ident = ident $self;
|
||||
|
||||
my $action = SOAP::WSDL::TypeLookup->lookup(
|
||||
$element->{ NamespaceURI },
|
||||
$element->{ LocalName }
|
||||
);
|
||||
|
||||
$characters_of{ $ident } = q{};
|
||||
return if not $action;
|
||||
|
||||
if ($action->{ type } eq 'CLASS') {
|
||||
eval "require $action->{ class }";
|
||||
croak $@, $tree_of{ $ident } if ($@);
|
||||
|
||||
my $class = $action->{ class };
|
||||
my $obj = $class->new({ parent => $current_of{ $ident } })->init(
|
||||
values %{ $element->{ Attributes } }
|
||||
);
|
||||
|
||||
# set element in parent
|
||||
if ($current_of{ $ident }) {
|
||||
# inherit namespace, but don't override
|
||||
$obj->set_targetNamespace(
|
||||
$current_of{ $ident }->get_targetNamespace() )
|
||||
if not $obj->get_targetNamespace();
|
||||
|
||||
# push on name list
|
||||
my $method = "push_$element->{ LocalName }";
|
||||
no strict qw(refs);
|
||||
$current_of{ $ident }->$method( $obj );
|
||||
|
||||
# remember element for stepping back
|
||||
push @{ $order_of{ $ident } }, $current_of{ $ident };
|
||||
}
|
||||
else {
|
||||
$tree_of{ $ident } = $obj;
|
||||
}
|
||||
# set new element (step down)
|
||||
$current_of{ $ident } = $obj;
|
||||
}
|
||||
elsif ($action->{ type } eq 'PARENT') {
|
||||
$current_of{ $ident }->init( values %{ $element->{ Attributes } } );
|
||||
}
|
||||
elsif ($action->{ type } eq 'METHOD') {
|
||||
my $method = $action->{ method } || $element->{ LocalName };
|
||||
|
||||
no strict qw(refs);
|
||||
# call method with
|
||||
# - default value ($action->{ value } if defined,
|
||||
# dereferencing lists
|
||||
# - the values of the elements Attributes hash
|
||||
$current_of{ $ident }->$method( defined $action->{ value }
|
||||
? ref $action->{ value }
|
||||
? @{ $action->{ value } }
|
||||
: ($action->{ value })
|
||||
: values %{ $element->{ Attributes } } );
|
||||
}
|
||||
}
|
||||
|
||||
sub characters {
|
||||
$characters_of{ ident $_[0] } .= $_[1]->{ Data };
|
||||
}
|
||||
|
||||
sub end_element {
|
||||
my ($self, $element) = @_;
|
||||
my $ident = ident $self;
|
||||
|
||||
my $action = SOAP::WSDL::TypeLookup->lookup(
|
||||
$element->{ NamespaceURI },
|
||||
$element->{ LocalName }
|
||||
) || {};
|
||||
|
||||
return if not ($action->{ type });
|
||||
if ( $action->{ type } eq 'CLASS' ) {
|
||||
$current_of{ $ident } = pop @{ $order_of{ $ident } };
|
||||
}
|
||||
elsif ($action->{ type } eq 'CONTENT' ) {
|
||||
my $method = $action->{ method };
|
||||
no strict qw(refs);
|
||||
# strip of leading and trailing whitespace
|
||||
$characters_of{ $ident } =~s{ ^ \s+ (.+) \s+ $ }{$1}xms;
|
||||
# replace multi whitespace by one
|
||||
$characters_of{ $ident } =~s{ \s+ }{ }xmsg;
|
||||
$current_of{ $ident }->$method( $characters_of{ $ident } );
|
||||
}
|
||||
}
|
||||
|
||||
sub fatal_error {
|
||||
die @_;
|
||||
}
|
||||
|
||||
sub get_data {
|
||||
my $self = shift;
|
||||
return $tree_of{ ident $self };
|
||||
}
|
||||
1;
|
||||
9
lib/SOAP/WSDL/SOAP/Address.pm
Normal file
9
lib/SOAP/WSDL/SOAP/Address.pm
Normal file
@@ -0,0 +1,9 @@
|
||||
package SOAP::WSDL::SOAP::Address;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
|
||||
my %location :ATTR(:name<location> :default<()>);
|
||||
1;
|
||||
11
lib/SOAP/WSDL/SOAP/Body.pm
Normal file
11
lib/SOAP/WSDL/SOAP/Body.pm
Normal file
@@ -0,0 +1,11 @@
|
||||
package SOAP::WSDL::SOAP::Body;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
my %use_of :ATTR(:name<use> :default<q{}>);
|
||||
my %namespace_of :ATTR(:name<namespace> :default<q{}>);
|
||||
my %encodingStyle_of :ATTR(:name<encodingStyle> :default<q{}>);
|
||||
my %parts_of :ATTR(:name<parts> :default<q{}>);
|
||||
|
||||
1;
|
||||
12
lib/SOAP/WSDL/SOAP/Header.pm
Normal file
12
lib/SOAP/WSDL/SOAP/Header.pm
Normal file
@@ -0,0 +1,12 @@
|
||||
package SOAP::WSDL::SOAP::Header;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
my %use_of :ATTR(:name<use> :default<q{}>);
|
||||
my %namespace_of :ATTR(:name<namespace> :default<q{}>);
|
||||
my %encodingStyle_of :ATTR(:name<encodingStyle> :default<q{}>);
|
||||
my %message_of :ATTR(:name<message> :default<()>);
|
||||
my %part_of :ATTR(:name<part> :default<q{}>);
|
||||
|
||||
1;
|
||||
6
lib/SOAP/WSDL/SOAP/HeaderFault.pm
Normal file
6
lib/SOAP/WSDL/SOAP/HeaderFault.pm
Normal file
@@ -0,0 +1,6 @@
|
||||
package SOAP::WSDL::SOAP::HeaderFault;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(SOAP::WSDL::Header);
|
||||
|
||||
1;
|
||||
12
lib/SOAP/WSDL/SOAP/Operation.pm
Normal file
12
lib/SOAP/WSDL/SOAP/Operation.pm
Normal file
@@ -0,0 +1,12 @@
|
||||
package SOAP::WSDL::SOAP::Operation;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %style_of :ATTR(:name<style> :default<()>);
|
||||
my %soapAction_of :ATTR(:name<soapAction> :default<()>);
|
||||
|
||||
1;
|
||||
@@ -2,7 +2,8 @@ package SOAP::WSDL::SOAP::Typelib::Fault11;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use Data::Dumper;
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
use SOAP::WSDL::XSD::Typelib::ComplexType;
|
||||
use SOAP::WSDL::XSD::Typelib::Element;
|
||||
@@ -17,9 +18,6 @@ my %faultstring_of :ATTR(:get<faultstring>);
|
||||
my %faultactor_of :ATTR(:get<faultactor>);
|
||||
my %detail_of :ATTR(:get<detail>);
|
||||
|
||||
# always return false in boolean context - a fault is never true...
|
||||
sub as_bool :BOOLIFY { return; }
|
||||
|
||||
__PACKAGE__->_factory(
|
||||
[ qw(faultcode faultstring faultactor detail) ],
|
||||
{
|
||||
@@ -44,6 +42,10 @@ __PACKAGE__->__set_minOccurs();
|
||||
__PACKAGE__->__set_maxOccurs();
|
||||
__PACKAGE__->__set_ref('');
|
||||
|
||||
# always return false in boolean context - a fault is never true...
|
||||
sub as_bool : BOOLIFY { return; }
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/perl -w
|
||||
# TODO rename to ::XSD
|
||||
package SOAP::WSDL::Serializer::SOAP11;
|
||||
use strict;
|
||||
use warnings;
|
||||
@@ -31,18 +32,14 @@ sub serialize {
|
||||
|
||||
while (my ($uri, $prefix) = each %{ $opt->{ namespace } })
|
||||
{
|
||||
$xml .= "\n\t" if ($opt->{'readable'});
|
||||
$xml .= "xmlns:$prefix=\"$uri\" ";
|
||||
}
|
||||
|
||||
# TODO insert encoding
|
||||
$xml.='>';
|
||||
$xml .= $self->serialize_header($args_of_ref->{ method }, $args_of_ref->{ header }, $opt);
|
||||
$xml .= "\n" if ($opt->{ readable });
|
||||
$xml .= $self->serialize_body($args_of_ref->{ method }, $args_of_ref->{ body }, $opt);
|
||||
$xml .= "\n" if ($opt->{ readable });
|
||||
$xml .= '</' . $soap_prefix .':Envelope>';
|
||||
$xml .= "\n" if ($opt->{ readable });
|
||||
return $xml;
|
||||
}
|
||||
|
||||
@@ -51,7 +48,7 @@ sub serialize_header {
|
||||
|
||||
# header is optional. Leave out if there's no header data
|
||||
return q{} if not $data;
|
||||
return join ( ($opt->{ readable }) ? "\n" : q{},
|
||||
return join ( q{},
|
||||
"<$opt->{ namespace }->{ $SOAP_NS }\:Header>",
|
||||
"$data",
|
||||
"</$opt->{ namespace }->{ $SOAP_NS }\:Header>",
|
||||
@@ -63,7 +60,7 @@ sub serialize_body {
|
||||
|
||||
# Body is NOT optional. Serialize to empty body
|
||||
# if we have no data.
|
||||
return join ( ($opt->{ readable }) ? "\n" : q{},
|
||||
return join ( q{},
|
||||
"<$opt->{ namespace }->{ $SOAP_NS }\:Body>",
|
||||
defined $data ? "$data" : (),
|
||||
"</$opt->{ namespace }->{ $SOAP_NS }\:Body>",
|
||||
|
||||
@@ -6,27 +6,4 @@ use base qw(SOAP::WSDL::Base);
|
||||
|
||||
my %port_of :ATTR(:name<port> :default<()>);
|
||||
|
||||
sub explain {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $txt ="=head1 Service " . $self->get_name() . "\n\n";
|
||||
foreach my $port (@{ $self->get_port() } )
|
||||
{
|
||||
$txt .= $port->explain( $opt );
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
return join "\n",
|
||||
map { $_->to_typemap( $opt ) } @{ $port_of{ ident $self } };
|
||||
}
|
||||
|
||||
# TODO implement to_class as class generator for a (complete) interface
|
||||
sub to_class {
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package SOAP::WSDL::SoapOperation;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
|
||||
my %input_of :ATTR(:name<input> :default<()>);
|
||||
my %output_of :ATTR(:name<output> :default<()>);
|
||||
my %fault_of :ATTR(:name<fault> :default<()>);
|
||||
my %style_of :ATTR(:name<style> :default<()>);
|
||||
my %soapAction_of :ATTR(:name<soapAction> :default<()>);
|
||||
|
||||
sub explain {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
my $txt = '';
|
||||
$opt->{ indent } ||= '';
|
||||
|
||||
$txt .= $opt->{ indent } . "soapAction: " . $self->soapAction() . "\n"
|
||||
if ( $self->soapAction() );
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -23,9 +23,6 @@ sub send_receive {
|
||||
? 'utf8'
|
||||
: lc($encoding);
|
||||
|
||||
# TODO check whether we need this with current LWP::UserAgent - we're
|
||||
# not here to fix LWP::UserAgent bugs...
|
||||
#
|
||||
# what's this all about?
|
||||
# unfortunately combination of LWP and Perl 5.6.1 and later has bug
|
||||
# in sending multibyte characters. LWP uses length() to calculate
|
||||
@@ -46,8 +43,6 @@ sub send_receive {
|
||||
$envelope = pack('C0A*', $envelope)
|
||||
if length($envelope) != $bytelength;
|
||||
|
||||
# END TODO
|
||||
|
||||
my $request = HTTP::Request->new( 'POST',
|
||||
$endpoint,
|
||||
[ 'Content-Type', "$content_type; charset=$encoding",
|
||||
@@ -92,10 +87,10 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$Rev: 288 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: HTTP.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Transport/HTTP.pm $
|
||||
$Id: HTTP.pm 288 2007-09-29 19:34:20Z kutterma $
|
||||
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Transport/HTTP.pm $
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
81
lib/SOAP/WSDL/Transport/Loopback.pm
Normal file
81
lib/SOAP/WSDL/Transport/Loopback.pm
Normal file
@@ -0,0 +1,81 @@
|
||||
package SOAP::WSDL::Transport::Loopback;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use SOAP::WSDL::Factory::Transport;
|
||||
|
||||
our $VERSION = '2.00_17';
|
||||
|
||||
SOAP::WSDL::Factory::Transport->register( http => __PACKAGE__ );
|
||||
SOAP::WSDL::Factory::Transport->register( https => __PACKAGE__ );
|
||||
|
||||
my %code_of :ATTR(:name<code> :default<()>);
|
||||
my %status_of :ATTR(:name<status> :default<()>);
|
||||
my %message_of :ATTR(:name<message> :default<()>);
|
||||
my %is_success_of :ATTR(:name<is_success> :default<()>);
|
||||
|
||||
{
|
||||
no warnings qw(redefine);
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
return bless \my ($o), $class;
|
||||
}
|
||||
}
|
||||
|
||||
# create methods normally inherited from SOAP::Client
|
||||
SUBFACTORY: {
|
||||
no strict qw(refs);
|
||||
foreach my $method ( qw(code message status is_success) ) {
|
||||
*{ $method } = *{ "get_$method" };
|
||||
}
|
||||
}
|
||||
|
||||
sub send_receive {
|
||||
my ($self, %parameters) = @_;
|
||||
return $parameters{envelope};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Transport::Test - Loopback transport class for SOAP::WSDL
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use SOAP::WSDL::Client;
|
||||
use SOAP::WSDL::Transport::Loopback;
|
||||
|
||||
my $soap = SOAP::WSDL::Client->new()
|
||||
$soap->get_transport->set_base_dir('.');
|
||||
$soap->call('method', \%body, \%header);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SOAP::WSDL::Transport::Loopback is a loopback test transport backend for
|
||||
SOAP::WSDL.
|
||||
|
||||
When SOAP::WSDL::Transport::Loopback is used as transport backend, the
|
||||
request is returned as response. No data ever goes over the wire.
|
||||
This is particularly useful for testing SOAP::WSDL plugins and applications.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2004-2007 Martin Kutter.
|
||||
|
||||
This file is part of SOAP-WSDL. You may distribute/modify it under
|
||||
the same terms as perl itself
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: HTTP.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Transport/HTTP.pm $
|
||||
|
||||
=cut
|
||||
129
lib/SOAP/WSDL/Transport/Test.pm
Normal file
129
lib/SOAP/WSDL/Transport/Test.pm
Normal file
@@ -0,0 +1,129 @@
|
||||
package SOAP::WSDL::Transport::Test;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use SOAP::WSDL::Factory::Transport;
|
||||
|
||||
our $VERSION = '2.00_14';
|
||||
|
||||
SOAP::WSDL::Factory::Transport->register( http => __PACKAGE__ );
|
||||
SOAP::WSDL::Factory::Transport->register( https => __PACKAGE__ );
|
||||
|
||||
my %code_of :ATTR(:name<code> :default<()>);
|
||||
my %status_of :ATTR(:name<status> :default<()>);
|
||||
my %message_of :ATTR(:name<message> :default<()>);
|
||||
my %is_success_of :ATTR(:name<is_success> :default<()>);
|
||||
my %base_dir_of :ATTR(:name<base_dir> :init_arg<base_dir> :default<.>);
|
||||
|
||||
# create methods normally inherited from SOAP::Client
|
||||
SUBFACTORY: {
|
||||
no strict qw(refs);
|
||||
foreach my $method ( qw(code message status is_success) ) {
|
||||
*{ $method } = *{ "get_$method" };
|
||||
}
|
||||
}
|
||||
|
||||
sub send_receive {
|
||||
my ($self, %parameters) = @_;
|
||||
my ($envelope, $soap_action, $endpoint, $encoding, $content_type) =
|
||||
@parameters{qw(envelope action endpoint encoding content_type)};
|
||||
|
||||
my $filename = $soap_action;
|
||||
$filename =~s{ \A(:?'|") }{}xms;
|
||||
$filename =~s{ (:?'|")\z }{}xms;
|
||||
$filename =~s{ \A [^:]+ : (:? /{2})? }{}xms;
|
||||
|
||||
$filename = join '/', $base_dir_of{ ident $self }, "$filename.xml";
|
||||
|
||||
if (not -r $filename) {
|
||||
warn "cannot access $filename";
|
||||
$self->set_code( 500 );
|
||||
$self->set_message( "Failed" );
|
||||
$self->set_is_success(0);
|
||||
$self->set_status("500 Failed");
|
||||
return;
|
||||
}
|
||||
|
||||
open my $fh, '<', $filename or die "cannot open $filename: $!";
|
||||
binmode $fh;
|
||||
my $response = <$fh>;
|
||||
close $fh or die "cannot close $filename: $!";
|
||||
|
||||
$self->set_code( 200 );
|
||||
$self->set_message( "OK" );
|
||||
$self->set_is_success(1);
|
||||
$self->set_status("200 OK");
|
||||
return $response;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SOAP::WSDL::Transport::Test - Test transport class for SOAP::WSDL
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use SOAP::WSDL::Client;
|
||||
use SOAP::WSDL::Transport::Test;
|
||||
|
||||
my $soap = SOAP::WSDL::Client->new()
|
||||
$soap->get_transport->set_base_dir('.');
|
||||
$soap->call('method', \%body, \%header);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
SOAP::WSDL::Transport::Test is a file-based test transport backend for
|
||||
SOAP::WSDL.
|
||||
|
||||
When SOAP::WSDL::Transport::Test is used as transport backend, the reponse is
|
||||
read from a XML file and the request message is discarded. This is particularly
|
||||
useful for testing SOAP::WSDL plugins.
|
||||
|
||||
=head2 Filename resolution
|
||||
|
||||
SOAP::WSDL::Transport makes up the response XML file name from the SOAPAction
|
||||
of the request. The following filename is used:
|
||||
|
||||
base_dir / soap_action .xml
|
||||
|
||||
The protocol scheme (e.g. http:) and two heading slashes (//) are stripped from
|
||||
the soap_action.
|
||||
|
||||
base_dir defaults to '.'
|
||||
|
||||
Examples:
|
||||
|
||||
SOAPAction: http://somewhere.over.the.rainbow/webservice/webservice.asmx
|
||||
Filename: ./somewhere.over.the.rainbow/webservice/webservice.asmx.xml
|
||||
|
||||
SOAPAction: uri:MyWickedService/test
|
||||
Filename: ./MyWickedService/test.xml
|
||||
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 set_base_dir
|
||||
|
||||
Sets the base directory SOAP::WSDL::Transport::Test should look for response
|
||||
files.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright 2004-2007 Martin Kutter.
|
||||
|
||||
This file is part of SOAP-WSDL. You may distribute/modify it under
|
||||
the same terms as perl itself
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
|
||||
|
||||
=head1 REPOSITORY INFORMATION
|
||||
|
||||
$Rev: 218 $
|
||||
$LastChangedBy: kutterma $
|
||||
$Id: HTTP.pm 218 2007-09-10 16:19:23Z kutterma $
|
||||
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Transport/HTTP.pm $
|
||||
|
||||
=cut
|
||||
@@ -60,16 +60,22 @@ my %TYPES = (
|
||||
'http://schemas.xmlsoap.org/wsdl/soap/' => {
|
||||
operation => {
|
||||
type => 'CLASS',
|
||||
class => 'SOAP::WSDL::SoapOperation',
|
||||
class => 'SOAP::WSDL::SOAP::Operation',
|
||||
},
|
||||
binding => {
|
||||
type => 'PARENT',
|
||||
},
|
||||
body => {
|
||||
type => 'PARENT',
|
||||
type => 'CLASS',
|
||||
class => 'SOAP::WSDL::SOAP::Body',
|
||||
},
|
||||
header => {
|
||||
type => 'CLASS',
|
||||
class => 'SOAP::WSDL::SOAP::Header',
|
||||
},
|
||||
address => {
|
||||
type => 'PARENT',
|
||||
type => 'CLASS',
|
||||
class => 'SOAP::WSDL::SOAP::Address',
|
||||
}
|
||||
},
|
||||
'http://www.w3.org/2001/XMLSchema' => {
|
||||
@@ -134,20 +140,20 @@ my %TYPES = (
|
||||
type => 'METHOD',
|
||||
method => 'set_list',
|
||||
},
|
||||
union => {
|
||||
union => {
|
||||
type => 'METHOD',
|
||||
method => 'set_union',
|
||||
},
|
||||
enumeration => {
|
||||
type => 'METHOD',
|
||||
method => 'push_enumeration',
|
||||
type => 'SKIP',
|
||||
# method => 'push_enumeration',
|
||||
},
|
||||
group => {
|
||||
type => 'METHOD',
|
||||
method => 'set_flavor',
|
||||
value => 'all',
|
||||
value => 'group',
|
||||
},
|
||||
all => {
|
||||
all => {
|
||||
type => 'METHOD',
|
||||
method => 'set_flavor',
|
||||
value => 'all',
|
||||
@@ -168,7 +174,7 @@ my %TYPES = (
|
||||
|
||||
sub lookup {
|
||||
my $self = shift;
|
||||
my $namespace = shift || 'http://schemas.xmlsoap.org/wsdl/';
|
||||
my $namespace = shift || 'http://schemas.xmlsoap.org/wsdl/';
|
||||
my $name = shift;
|
||||
return $TYPES{ $namespace }->{ $name };
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ sub START {
|
||||
|
||||
sub find_type {
|
||||
my ($self, $ns, $name) = @_;
|
||||
|
||||
($ns, $name) = @{ $ns } if ref $ns; # allow passing list refs
|
||||
foreach my $schema (@{ $schema_of{ ident $self } }) {
|
||||
my $type = $schema->find_type($ns, $name);
|
||||
return $type if $type;
|
||||
@@ -26,7 +26,7 @@ sub find_type {
|
||||
|
||||
sub find_element {
|
||||
my ($self, $ns, $name) = @_;
|
||||
|
||||
($ns, $name) = @{ $ns } if ref $ns; # allow passing list refs
|
||||
foreach my $schema (@{ $schema_of{ ident $self } }) {
|
||||
my $type = $schema->find_element($ns, $name);
|
||||
return $type if $type;
|
||||
|
||||
@@ -3,7 +3,6 @@ use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
use Data::Dumper;
|
||||
|
||||
sub serialize {
|
||||
my ($self, $name, $value, $opt) = @_;
|
||||
@@ -33,14 +32,4 @@ sub serialize {
|
||||
return $xml;
|
||||
}
|
||||
|
||||
sub explain {
|
||||
my ($self, $opt, $name ) = @_;
|
||||
$opt->{ indent } = q{} if not defined $opt->{ indent };
|
||||
return "$opt->{ indent }'$name' => \$someValue,\n"
|
||||
}
|
||||
|
||||
sub toClass {
|
||||
warn "# builtin";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -5,7 +5,8 @@ use Carp;
|
||||
use Class::Std::Storable;
|
||||
use Scalar::Util qw(blessed);
|
||||
use base qw/SOAP::WSDL::Base/;
|
||||
use Data::Dumper;
|
||||
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %annotation_of :ATTR(:name<annotation> :default<()>);
|
||||
my %element_of :ATTR(:name<element> :default<()>);
|
||||
@@ -17,17 +18,9 @@ my %abstract_of :ATTR(:name<abstract> :default<()>);
|
||||
my %mixed_of :ATTR(:name<mixed> :default<()>); # default is false
|
||||
|
||||
# is set to simpleContent/complexContent
|
||||
my %content_Model_of :ATTR(:name<contentModel> :default<()>);
|
||||
my %content_model_of :ATTR(:name<contentModel> :default<()>);
|
||||
|
||||
sub find_element {
|
||||
my ($self, @args) = @_;
|
||||
my @found_at = grep {
|
||||
$_->get_targetNamespace() eq $args[0] &&
|
||||
$_->get_name() eq $args[1]
|
||||
}
|
||||
@{ $element_of{ ident $self } };
|
||||
return $found_at[0];
|
||||
}
|
||||
sub get_variety; *get_variety = \&get_flavor;
|
||||
|
||||
sub push_element {
|
||||
my $self = shift;
|
||||
@@ -121,205 +114,5 @@ sub serialize {
|
||||
return $xml;
|
||||
}
|
||||
|
||||
sub explain {
|
||||
my ($self, $opt, $name ) = @_;
|
||||
my $flavor = $self->get_flavor();
|
||||
|
||||
$name ||= q{};
|
||||
|
||||
return q{} if not $flavor; # empty complexType
|
||||
$opt->{ indent } ||= q{ };
|
||||
my $xml = q{};
|
||||
$xml .= "$opt->{indent}\'$name'=> {\n" if $name;
|
||||
|
||||
if ( ($flavor eq "sequence") or ($flavor eq "all") ) {
|
||||
$opt->{ indent } .= " ";
|
||||
for my $element (@{ $self->get_element() }) {
|
||||
$xml .= $element->explain( $opt )
|
||||
}
|
||||
$opt->{ indent } =~s/\s{2}$//; # step back
|
||||
}
|
||||
elsif ($flavor eq "complexContent")
|
||||
{
|
||||
|
||||
}
|
||||
elsif ($flavor eq "simpleContent")
|
||||
{
|
||||
warn "found unsupported complexType definition $flavor";
|
||||
}
|
||||
else
|
||||
{
|
||||
warn "found unsupported complexType definition $flavor";
|
||||
}
|
||||
|
||||
|
||||
# if we're called inside a element...
|
||||
$xml .= "$opt->{indent}},\n" if $name;
|
||||
|
||||
return $xml;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
my ($self, $opt, $name ) = @_;
|
||||
my $flavor = $self->get_flavor();
|
||||
my $txt;
|
||||
return q{} if not $flavor; # empty complexType
|
||||
|
||||
my %nsmap = reverse %{ $opt->{ wsdl }->get_xmlns() };
|
||||
|
||||
if ( ($flavor eq "sequence") or ($flavor eq "all") )
|
||||
{
|
||||
for my $element (@{ $self->get_element() }) {
|
||||
$txt .= $element->to_typemap( $opt );
|
||||
}
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
|
||||
sub to_class {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
|
||||
my $template = <<'EOT';
|
||||
package [% type_prefix %][% self.get_name %];
|
||||
use strict;
|
||||
|
||||
use SOAP::WSDL::XSD::Typelib::ComplexType;
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::ComplexType
|
||||
);
|
||||
|
||||
[% FOREACH element=self.get_element -%]
|
||||
my %[% element.get_name %]_of :ATTR(:get<[% element.get_name %]>);
|
||||
[% END %]
|
||||
|
||||
__PACKAGE__->_factory(
|
||||
[ qw([% FOREACH element=self.get_element -%]
|
||||
[% element.get_name %]
|
||||
[% END %]) ],
|
||||
{
|
||||
[% FOREACH element=self.get_element %][% element.get_name %] => \%[% element.get_name %]_of,
|
||||
[% END %]
|
||||
},
|
||||
{
|
||||
[%-
|
||||
FOREACH element=self.get_element;
|
||||
IF (element.get_type); # element type="..."
|
||||
split_name = element.get_type.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
IF nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema' -%]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% localname %]',
|
||||
[% ELSE -%]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[%- END;
|
||||
ELSIF (element.get_ref); # element ref="..."
|
||||
split_name = element.get_ref.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1; %]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[% ELSIF (simpleType = element.first_simpleType);
|
||||
base = simpleType.get_base();
|
||||
%]
|
||||
# basic simple type handling: we treat atomic simple types
|
||||
# in complexType elements as their base types
|
||||
# - and we only treat <restriction base="..."> yet.
|
||||
# our base here is [% base %]
|
||||
[%
|
||||
split_name = base.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
IF nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema' -%]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% localname %]',
|
||||
[% ELSE -%]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[%- END;
|
||||
END;
|
||||
END %]
|
||||
}
|
||||
);
|
||||
|
||||
sub get_xmlns { '[% self.get_targetNamespace %]' }
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
[% MACRO pod BLOCK %]=pod[% END %]
|
||||
[% MACRO cut BLOCK %]=cut[% END %]
|
||||
[% MACRO head1 BLOCK %]=head1[% END %]
|
||||
[% MACRO head2 BLOCK %]=head2[% END %]
|
||||
|
||||
[% pod %]
|
||||
|
||||
[% head1 %] NAME
|
||||
|
||||
[% type_prefix %][% self.get_name %]
|
||||
|
||||
[% head1 %] SYNOPSIS
|
||||
|
||||
[% head1 %] DESCRIPTION
|
||||
|
||||
Type class for the XML type [% self.get_name %].
|
||||
|
||||
[% head1 %] PROPERTIES
|
||||
|
||||
The following properties may be accessed using get_PROPERTY / set_PROPERTY
|
||||
methods:
|
||||
|
||||
[%- FOREACH element = self.get_element %]
|
||||
[% element.get_name -%]
|
||||
[% END %]
|
||||
|
||||
[% head1 %] Object structure
|
||||
|
||||
[% FOREACH element=self.get_element;
|
||||
IF (element.get_type);
|
||||
split_name = element.get_type.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
IF nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema' -%]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% localname %]',
|
||||
[% ELSE -%]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[%- END;
|
||||
ELSIF (element.get_ref); # element ref="..."
|
||||
split_name = element.get_ref.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1; %]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[% ELSIF (simpleType = element.first_simpleType);
|
||||
base = simpleType.get_base();
|
||||
split_name = base.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
IF nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema' -%]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% localname %]',
|
||||
[% ELSE -%]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[%- END;
|
||||
END;
|
||||
END %]
|
||||
|
||||
Structure as perl hash:
|
||||
|
||||
The object structure is displayed as hash below though this is not correct.
|
||||
Complex hash elements actually are objects of their corresponding classes
|
||||
(look for classes of the same name in your typleib).
|
||||
new() will accept a hash structure like this, but transform it to a object
|
||||
tree.
|
||||
|
||||
[% structure %]
|
||||
|
||||
[% cut %]
|
||||
|
||||
EOT
|
||||
|
||||
$self->SUPER::to_class($opt, $template);
|
||||
}
|
||||
|
||||
sub _check_value {
|
||||
my $self = shift;
|
||||
}
|
||||
1;
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@ use strict;
|
||||
use warnings;
|
||||
use Class::Std::Storable;
|
||||
use base qw(SOAP::WSDL::Base);
|
||||
use Data::Dumper;
|
||||
|
||||
my %simpleType_of :ATTR(:name<simpleType> :default<()>);
|
||||
our $VERSION='2.00_17';
|
||||
|
||||
my %annotation_of :ATTR(:name<annotation> :default<()>);
|
||||
my %simpleType_of :ATTR(:name<simpleType> :default<()>);
|
||||
my %complexType_of :ATTR(:name<complexType> :default<()>);
|
||||
my %facet_of :ATTR(:name<facet> :default<()>);
|
||||
my %type_of :ATTR(:name<type> :default<()>);
|
||||
@@ -21,13 +23,6 @@ my %nillable_of :ATTR(:name<nillable> :default<()>);
|
||||
my %ref_of :ATTR(:name<ref> :default<()>);
|
||||
my %substitutionGroup_of :ATTR(:name<substitutionGroup> :default<()>);
|
||||
|
||||
sub first_type {
|
||||
my $result_ref = $complexType_of{ ident shift };
|
||||
return if not $result_ref;
|
||||
return $result_ref if (not ref $result_ref eq 'ARRAY');
|
||||
return $result_ref->[0];
|
||||
}
|
||||
|
||||
sub first_simpleType {
|
||||
my $result_ref = $simpleType_of{ ident shift };
|
||||
return if not $result_ref;
|
||||
@@ -108,295 +103,6 @@ sub serialize {
|
||||
return $type->serialize( $name, $value, $opt );
|
||||
}
|
||||
|
||||
sub explain {
|
||||
my ($self, $opt, $name) = @_;
|
||||
my $type;
|
||||
my $text = q{};
|
||||
|
||||
# if we have a simple / complexType, explain right here
|
||||
if ($type = $self->first_simpleType() )
|
||||
{
|
||||
if ($opt->{ anonymous }) {
|
||||
delete $opt->{ anonymous };
|
||||
return $type->explain( $opt, undef );
|
||||
}
|
||||
return $type->explain( $opt, $self->get_name() );
|
||||
}
|
||||
elsif ($type = $self->first_complexType() )
|
||||
{
|
||||
if ($opt->{ anonymous }) {
|
||||
delete $opt->{ anonymous };
|
||||
return $type->explain( $opt, undef );
|
||||
}
|
||||
return $type->explain( $opt, $self->get_name() );
|
||||
}
|
||||
elsif (my $element_name = $self->get_ref() ) {
|
||||
my $element = $opt->{ wsdl }->first_types()->find_element(
|
||||
$opt->{ wsdl }->_expand( $element_name )
|
||||
);
|
||||
return $element->explain( $opt, $self->get_name() );
|
||||
}
|
||||
|
||||
# return if it's not a derived type - we don't handle
|
||||
# other stuff yet.
|
||||
return $text if (not $self->get_type() );
|
||||
|
||||
# if we have a derived type, fetch type and explain
|
||||
my ($prefix, $localname) = split /:/ , $self->get_type();
|
||||
my %ns_map = reverse %{ $opt->{ wsdl }->get_xmlns };
|
||||
|
||||
$type = $opt->{ wsdl }->first_types()->find_type(
|
||||
$ns_map{ $prefix }, $localname
|
||||
);
|
||||
|
||||
use Data::Dumper;
|
||||
die "no type for $prefix:$localname ($ns_map{ $prefix })"
|
||||
. Dumper $opt->{ wsdl }->first_types()->first_schema()->_DUMP
|
||||
if (not $type);
|
||||
|
||||
if ($opt->{ anonymous }) {
|
||||
delete $opt->{ anonymous };
|
||||
return $text .= $type->explain( $opt, undef );
|
||||
}
|
||||
return $text .= $type->explain( $opt, $name || $self->get_name() );
|
||||
return 'ERROR: '. $@;
|
||||
}
|
||||
|
||||
sub to_typemap {
|
||||
|
||||
my ($self, $opt) = @_;
|
||||
my $txt = q{};
|
||||
|
||||
my %nsmap = reverse %{ $opt->{ wsdl }->get_xmlns() };
|
||||
my $type;
|
||||
|
||||
push @{ $opt->{path} }, $self->get_name();
|
||||
|
||||
if ( my $typename = $self->get_type() ) {
|
||||
my ($prefix, $localname) = split /:/, $self->get_type();
|
||||
my $ns = $nsmap{ $prefix };
|
||||
my $typeclass;
|
||||
|
||||
# builtin type
|
||||
if ( $nsmap{ $prefix } eq 'http://www.w3.org/2001/XMLSchema') {
|
||||
$typeclass = "SOAP::WSDL::XSD::Typelib::Builtin::$localname";
|
||||
}
|
||||
else
|
||||
{
|
||||
$type = $opt->{ wsdl }->first_types()->find_type( $ns, $localname );
|
||||
|
||||
# referenced types need type_prefix (may be globally unique)
|
||||
$typeclass = $opt->{ type_prefix } . $type->get_name();
|
||||
$txt .= $type->to_typemap($opt);
|
||||
}
|
||||
$txt .= q{'} . join( q{/}, @{ $opt->{path} } ) . "' => '$typeclass',\n";
|
||||
}
|
||||
|
||||
# atomic types need element prefix
|
||||
elsif ($type = $self->first_simpleType() ) {
|
||||
# atomic types need element prefix (may be locally unique)
|
||||
# TODO fix simpletype Typemap
|
||||
my $typeclass = $opt->{ element_prefix } . $self->get_name();
|
||||
$txt .= q{'} . join( q{/}, @{ $opt->{path} } ) . "' => '$typeclass',\n";
|
||||
|
||||
my $flavor = $type->get_flavor();
|
||||
if ( $flavor eq 'sequence' ) {
|
||||
$txt .= "# atomic simple type (sequence)\n";
|
||||
$txt .= $type->to_typemap($opt). "\n";
|
||||
$txt .= "# end atomic simple type (sequence)\n";
|
||||
}
|
||||
elsif ( $flavor eq 'all' ) {
|
||||
$txt .= "# atomic simple type (all)\n";
|
||||
$txt .= $type->to_typemap($opt). "\n";
|
||||
$txt .= "# end atomic simple type (all)\n";
|
||||
}
|
||||
|
||||
}
|
||||
elsif ($type = $self->first_complexType() ) {
|
||||
my $typeclass = $opt->{ element_prefix } . $self->get_name();
|
||||
$txt .= q{'} . join( q{/}, @{ $opt->{path} } ) . "' => '$typeclass',\n";
|
||||
my $flavor = $type->get_flavor()
|
||||
|| 'UNKNOWN';
|
||||
if ( $flavor eq 'sequence' ) {
|
||||
$txt .= "# atomic complex type (sequence)\n";
|
||||
$txt .= $type->to_typemap($opt). "\n";;
|
||||
$txt .= "# end atomic complex type (sequence)\n";
|
||||
}
|
||||
elsif ( $flavor eq 'all' ) {
|
||||
$txt .= "# atomic complex type (all)\n";
|
||||
$txt .= $type->to_typemap($opt). "\n";
|
||||
$txt .= "# end atomic complex type (all)\n";
|
||||
}
|
||||
else {
|
||||
warn "flavor $flavor in element " . $self->get_name() . "\n";
|
||||
}
|
||||
}
|
||||
pop @{ $opt->{ path } };
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
|
||||
sub to_class {
|
||||
my $self = shift;
|
||||
my $opt = shift;
|
||||
|
||||
my $template = <<'EOT';
|
||||
package [% element_prefix %][% self.get_name %];
|
||||
use strict;
|
||||
|
||||
use SOAP::WSDL::XSD::Typelib::Element;
|
||||
|
||||
[% IF (type = self.first_simpleType) %]
|
||||
# <element name="[% self.get_name %]"><simpleType> definition
|
||||
use SOAP::WSDL::XSD::Typelib::SimpleType;
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Element
|
||||
SOAP::WSDL::XSD::Typelib::SimpleType
|
||||
[% type.flavor_class %]
|
||||
[% type.base_class($type_prefix) %]
|
||||
);
|
||||
[% ELSIF (ref_name = self.get_ref);
|
||||
split_name = ref_name.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
ref_class = element_prefix _ localname;
|
||||
%]
|
||||
# <element name="[% self.get_name %]" ref="[% ref_name %]"> definition
|
||||
# use [% ref_class %];
|
||||
use base qw(
|
||||
[% ref_class %]
|
||||
);
|
||||
[% ELSIF (type = self.first_complexType) %]
|
||||
# atomic complexType
|
||||
# <element name="[% self.get_name %]"><complexType> definition
|
||||
use SOAP::WSDL::XSD::Typelib::ComplexType;
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Element
|
||||
SOAP::WSDL::XSD::Typelib::ComplexType
|
||||
);
|
||||
|
||||
[% FOREACH element = type.get_element %]
|
||||
my %[% element.get_name %]_of :ATTR(:get<[% element.get_name %]>);
|
||||
[% END %]
|
||||
|
||||
__PACKAGE__->_factory(
|
||||
[ qw([% FOREACH element = type.get_element %]
|
||||
[% element.get_name %]
|
||||
[% END %]) ],
|
||||
{
|
||||
[% FOREACH element = type.get_element %] [% element.get_name %] => \%[% element.get_name %]_of,
|
||||
[% END %]
|
||||
},
|
||||
{
|
||||
[% FOREACH element = type.get_element;
|
||||
split_name = element.get_type.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
IF nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema' %]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% localname %]',
|
||||
[% ELSE %]
|
||||
[% element.get_name %] => '[% type_prefix %][% localname %]',
|
||||
[% END %]
|
||||
[% END %]
|
||||
}
|
||||
);
|
||||
[%# END complexType %]
|
||||
[% ELSIF (type = self.get_type) %]
|
||||
#
|
||||
# <element name="[% self.get_name %]" type="[% self.get_type %]"/> definition
|
||||
#
|
||||
[% split_name = self.get_type.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
|
||||
IF (nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema');
|
||||
base_class = 'SOAP::WSDL::XSD::Typelib::Builtin::' _ localname ;
|
||||
ELSE;
|
||||
base_class = type_prefix _ localname;
|
||||
-%]
|
||||
|
||||
use [% base_class %];
|
||||
[% END %]
|
||||
use base qw(
|
||||
SOAP::WSDL::XSD::Typelib::Element
|
||||
[% base_class %]
|
||||
);
|
||||
[% END %]
|
||||
|
||||
sub get_xmlns { '[% self.get_targetNamespace %]' }
|
||||
|
||||
__PACKAGE__->__set_name('[% self.get_name %]');
|
||||
__PACKAGE__->__set_nillable([% self.get_nillable %]);
|
||||
__PACKAGE__->__set_minOccurs([% self.get_minOccurs %]);
|
||||
__PACKAGE__->__set_maxOccurs([% self.get_maxOccurs %]);
|
||||
__PACKAGE__->__set_ref('[% self.get_ref %]');
|
||||
|
||||
1;
|
||||
|
||||
|
||||
__END__
|
||||
|
||||
[% MACRO pod BLOCK %]=pod[% END %]
|
||||
[% MACRO cut BLOCK %]=cut[% END %]
|
||||
[% MACRO head1 BLOCK %]=head1[% END %]
|
||||
[% MACRO head2 BLOCK %]=head2[% END %]
|
||||
|
||||
[% pod %]
|
||||
|
||||
[% head1 %] NAME
|
||||
|
||||
[% element_prefix %][% self.get_name %]
|
||||
|
||||
[% head1 %] SYNOPSIS
|
||||
|
||||
[% head1 %] DESCRIPTION
|
||||
|
||||
Type class for the XML element [% self.get_name %].
|
||||
|
||||
[% head1 %] PROPERTIES
|
||||
|
||||
The following properties may be accessed using get_PROPERTY / set_PROPERTY
|
||||
methods:
|
||||
|
||||
[%- IF (type = self.first_complexType);
|
||||
FOREACH element = type.get_element %]
|
||||
[% element.get_name -%]
|
||||
[% END;
|
||||
END %]
|
||||
|
||||
[% head1 %] Object structure
|
||||
|
||||
[%- IF (type = self.first_complexType);
|
||||
FOREACH element = type.get_element;
|
||||
split_name = element.get_type.split(':');
|
||||
prefix = split_name.0;
|
||||
localname = split_name.1;
|
||||
IF nsmap.$prefix == 'http://www.w3.org/2001/XMLSchema' %]
|
||||
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% localname %]',
|
||||
[% ELSE %]
|
||||
[% element.get_name %] => '[% type_prefix %]::[% localname %]',
|
||||
[% END;
|
||||
END;
|
||||
END %]
|
||||
|
||||
Structure as perl hash:
|
||||
|
||||
The object structure is displayed as hash below though this is not correct.
|
||||
Complex hash elements actually are objects of their corresponding classes
|
||||
(look for classes of the same name in your typleib).
|
||||
new() will accept a hash structure like this, but transform it to a object
|
||||
tree.
|
||||
|
||||
[% structure %]
|
||||
|
||||
[% cut %]
|
||||
|
||||
EOT
|
||||
|
||||
$self->SUPER::to_class($opt, $template);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ my %BUILTINS = (
|
||||
'QName' => {},
|
||||
'NOTATION' => {},
|
||||
'integer' => {},
|
||||
'non-positive-integer' => {},
|
||||
'non-negative-integer' => {},
|
||||
'nonPositiveInteger' => {},
|
||||
'nonNegativeInteger' => {},
|
||||
'positiveInteger' => {},
|
||||
'negativeInteger' => {},
|
||||
'long' => {},
|
||||
@@ -44,8 +44,6 @@ my %BUILTINS = (
|
||||
'NMTOKEN' => {},
|
||||
);
|
||||
|
||||
# TODO place into appropriate schema and push on schema definitions list
|
||||
# in types
|
||||
sub START {
|
||||
my $self = shift;
|
||||
my @args = @_;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user