Compare commits

...
4 Commits
Author SHA1 Message Date
Martin Kutter c2da74b5ae import SOAP-WSDL 2.00_11 from CPAN
git-cpan-module:   SOAP-WSDL
git-cpan-version:  2.00_11
git-cpan-authorid: MKUTTER
git-cpan-file:     authors/id/M/MK/MKUTTER/SOAP-WSDL-2.00_11.tar.gz
2009-12-12 19:47:49 -08:00
Martin Kutter 7ba1959888 import SOAP-WSDL 2.00_10 from CPAN
git-cpan-module:   SOAP-WSDL
git-cpan-version:  2.00_10
git-cpan-authorid: MKUTTER
git-cpan-file:     authors/id/M/MK/MKUTTER/SOAP-WSDL-2.00_10.tar.gz
2009-12-12 19:47:48 -08:00
Martin Kutter a554e87f49 import SOAP-WSDL 2.00_09 from CPAN
git-cpan-module:   SOAP-WSDL
git-cpan-version:  2.00_09
git-cpan-authorid: MKUTTER
git-cpan-file:     authors/id/M/MK/MKUTTER/SOAP-WSDL-2.00_09.tar.gz
2009-12-12 19:47:47 -08:00
Martin Kutter 312f3d6bbd import SOAP-WSDL 2.00_08 from CPAN
git-cpan-module:   SOAP-WSDL
git-cpan-version:  2.00_08
git-cpan-authorid: MKUTTER
git-cpan-file:     authors/id/M/MK/MKUTTER/SOAP-WSDL-2.00_08.tar.gz
2009-12-12 19:47:46 -08:00
95 changed files with 8551 additions and 1878 deletions
+16 -16
View File
@@ -1,40 +1,40 @@
use Module::Build; use Module::Build;
Module::Build->new( Module::Build->new(
create_makefile_pl => 'passthrough',
dist_abstract => 'SOAP with WSDL support', dist_abstract => 'SOAP with WSDL support',
dist_name => 'SOAP-WSDL', dist_name => 'SOAP-WSDL',
dist_version => '2.00_07', dist_version => '2.00_11',
module_name => 'SOAP::WSDL', module_name => 'SOAP::WSDL',
license => 'artistic', license => 'artistic',
requires => { requires => {
'Class::Std' => q/v0.0.8/, 'Class::Std' => q/v0.0.8/,
'Class::Std::Storable' => 0, 'Class::Std::Storable' => 0,
'SOAP::Lite' => 0, 'Date::Parse' => 0,
'Date::Format' => 0,
'LWP::UserAgent' => 0,
'List::Util' => 0, 'List::Util' => 0,
'File::Basename' => 0, 'File::Basename' => 0,
'File::Path' => 0, 'File::Path' => 0,
'XML::XPath' => 0,
'XML::LibXML' => 0,
'XML::SAX::Base' => 0,
'XML::SAX::ParserFactory' => 0,
'XML::Parser::Expat' => 0, 'XML::Parser::Expat' => 0,
'Template' => 0,
'Getopt::Long' => 0,
}, },
buildrequires => { buildrequires => {
'Benchmark' => 0, 'Date::Parse' => 0,
'Cwd' => 0, 'Date::Format' => 0,
'Test::More' => 0, 'Test::More' => 0,
'SOAP::Lite' => 0, 'Class::Std' => q/v0.0.8/,
'Class::Std' => 0.0.8,
'Class::Std::Storable' => 0, 'Class::Std::Storable' => 0,
'List::Util' => 0, 'List::Util' => 0,
'LWP::UserAgent' => 0,
'File::Basename' => 0, 'File::Basename' => 0,
'File::Path' => 0, 'File::Path' => 0,
'XML::Simple' => 0,
'XML::LibXML' => 0,
'XML::Parser::Expat' => 0, 'XML::Parser::Expat' => 0,
'XML::SAX::Base' => 0, 'Template' => 0,
'XML::SAX::ParserFactory' => 0, 'Getopt::Long' => 0,
'Pod::Simple::Text' => 0, 'Cwd' => 0,
'XML::SAX::ParserFactory' => 0, 'File::Find' => 0,
}, },
recursive_test_files => 1, recursive_test_files => 1,
)->create_build_script; )->create_build_script;
+778 -1
View File
@@ -1 +1,778 @@
See perldoc SOAP::WSDL ------------------------------------------------------------------------
r176 | kutterma | 2007-08-31 17:28:29 +0200 (Fr, 31 Aug 2007) | 2 lines
- set SVN keywords
- updated docs
------------------------------------------------------------------------
r175 | kutterma | 2007-08-31 17:05:42 +0200 (Fr, 31 Aug 2007) | 6 lines
- modified SOAP::WSDL::Client to allow passing the SOAPAction header to call()
- modified SOAP::WSDL::Definitions's generator to emit interfaces which include
soap_action and style information for every operation
- re-generated GetWeather example interface
- fixed wsdl2perl.pl (typo)
------------------------------------------------------------------------
r174 | kutterma | 2007-08-31 15:49:04 +0200 (Fr, 31 Aug 2007) | 2 lines
- SOAPAction header is now always quoted.
- updated docs
------------------------------------------------------------------------
r173 | kutterma | 2007-08-31 15:48:10 +0200 (Fr, 31 Aug 2007) | 1 line
- added WS-I basic profile compliance docs. Looks like we're far from being compliant...
------------------------------------------------------------------------
r172 | kutterma | 2007-08-30 22:58:41 +0200 (Do, 30 Aug 2007) | 1 line
- updated TODO list
------------------------------------------------------------------------
r170 | kutterma | 2007-08-30 22:32:56 +0200 (Do, 30 Aug 2007) | 1 line
- added RELEASE_NOTES
------------------------------------------------------------------------
r169 | kutterma | 2007-08-30 21:33:50 +0200 (Do, 30 Aug 2007) | 1 line
- fixed SOAP11 serializer package name
------------------------------------------------------------------------
r168 | kutterma | 2007-08-30 21:32:39 +0200 (Do, 30 Aug 2007) | 4 lines
- added Serializer factory
- modified client to use serializer
- moved old SOAP::WSDL::Envelope into Serializer namespace
- moved Tranport factory into Factory namespace
------------------------------------------------------------------------
r167 | kutterma | 2007-08-30 21:30:17 +0200 (Do, 30 Aug 2007) | 1 line
- fixed Envelope to comply to new serializer scheme
------------------------------------------------------------------------
r166 | kutterma | 2007-08-30 18:44:48 +0200 (Do, 30 Aug 2007) | 1 line
- re-fixed Transport factory
------------------------------------------------------------------------
r165 | kutterma | 2007-08-30 18:43:36 +0200 (Do, 30 Aug 2007) | 1 line
- added HTTP Transport class (really)
------------------------------------------------------------------------
r164 | kutterma | 2007-08-30 14:38:47 +0200 (Do, 30 Aug 2007) | 1 line
- first try at serializer factory.
------------------------------------------------------------------------
r163 | kutterma | 2007-08-30 10:34:00 +0200 (Do, 30 Aug 2007) | 1 line
- updated docs (reference to homepage and forum)
------------------------------------------------------------------------
r162 | kutterma | 2007-08-30 10:29:49 +0200 (Do, 30 Aug 2007) | 1 line
- updated docs
------------------------------------------------------------------------
r161 | kutterma | 2007-08-30 10:17:28 +0200 (Do, 30 Aug 2007) | 2 lines
- modified client to use SOAP::WSDL::Transport factory
- fixed SOAP::WSDL::Transport factory
------------------------------------------------------------------------
r160 | kutterma | 2007-08-30 00:20:09 +0200 (Do, 30 Aug 2007) | 1 line
- added weird SOAP::Lite nameing scheme to registered && SOAP::Lite Transport instantiations
------------------------------------------------------------------------
r159 | kutterma | 2007-08-30 00:00:15 +0200 (Do, 30 Aug 2007) | 1 line
- first try at Transport factory and Transport::HTTP implementation class.
------------------------------------------------------------------------
r158 | kutterma | 2007-08-29 22:36:34 +0200 (Mi, 29 Aug 2007) | 1 line
- updated TODO list
------------------------------------------------------------------------
r153 | kutterma | 2007-08-29 11:24:40 +0200 (Mi, 29 Aug 2007) | 4 lines
- removed XML::LibXML dependencies (is now required, not used in test scripts)
- fixed WSDLParser to switch on expat namespace support when parsing files
- added expat based tests ported from XML::LibXML based WSDL parser tests
- updated docs
------------------------------------------------------------------------
r152 | kutterma | 2007-08-28 23:28:06 +0200 (Di, 28 Aug 2007) | 3 lines
- updated Build.PL
- updated CHANGES
- updated MANIFEST
------------------------------------------------------------------------
r151 | kutterma | 2007-08-28 23:07:14 +0200 (Di, 28 Aug 2007) | 1 line
- fixed namespace test
------------------------------------------------------------------------
r150 | kutterma | 2007-08-28 23:06:00 +0200 (Di, 28 Aug 2007) | 1 line
- renamed tests to better meet their content
------------------------------------------------------------------------
r149 | kutterma | 2007-08-28 23:03:30 +0200 (Di, 28 Aug 2007) | 1 line
- cleanup
------------------------------------------------------------------------
r148 | kutterma | 2007-08-28 23:02:01 +0200 (Di, 28 Aug 2007) | 2 lines
- added namespace test
- removed SAX handler from usage test
------------------------------------------------------------------------
r147 | kutterma | 2007-08-28 22:57:48 +0200 (Di, 28 Aug 2007) | 1 line
- added namespace support
------------------------------------------------------------------------
r146 | kutterma | 2007-08-28 21:56:35 +0200 (Di, 28 Aug 2007) | 1 line
- removed POD directive from template, so the CPAN indexer won't show it...
------------------------------------------------------------------------
r145 | kutterma | 2007-08-28 16:35:18 +0200 (Di, 28 Aug 2007) | 5 lines
- XML::SAX::Base and XML::SAX::ParserFactory and Pod::Simple::Text dependencies to ease testing
- removed unneccessary performance test
- Added Expat-based WSDL parser and test to get rid of XML::LibXML dependency some day...
- needs further work: namespaces are not processed correctly, yet
------------------------------------------------------------------------
r144 | kutterma | 2007-08-14 11:05:40 +0200 (Di, 14 Aug 2007) | 1 line
- added missing prerequisite 'Template' to Build.PL
------------------------------------------------------------------------
r143 | kutterma | 2007-08-13 20:43:20 +0200 (Mo, 13 Aug 2007) | 3 lines
- fixed POD (#1772710)
- fixed Makefile.PL - now try the passthrough variant first. If too many CPAN testers still fail, we may switch to traditional, some day...
- prepared 2.00_10 pre-release
------------------------------------------------------------------------
r142 | kutterma | 2007-08-13 15:55:45 +0200 (Mo, 13 Aug 2007) | 1 line
typo
------------------------------------------------------------------------
r141 | kutterma | 2007-08-12 21:45:51 +0200 (So, 12 Aug 2007) | 2 lines
- corrected POD error
- little speedup in add_FOO methods
------------------------------------------------------------------------
r140 | kutterma | 2007-08-12 21:27:58 +0200 (So, 12 Aug 2007) | 1 line
- corrected POD error
------------------------------------------------------------------------
r139 | kutterma | 2007-08-12 21:15:59 +0200 (So, 12 Aug 2007) | 1 line
- adder repository information
------------------------------------------------------------------------
r138 | kutterma | 2007-08-12 21:13:08 +0200 (So, 12 Aug 2007) | 1 line
- typo
------------------------------------------------------------------------
r137 | kutterma | 2007-08-12 21:12:20 +0200 (So, 12 Aug 2007) | 3 lines
- updated docs
- added svn information
- cosmetics
------------------------------------------------------------------------
r136 | kutterma | 2007-08-12 15:11:50 +0200 (So, 12 Aug 2007) | 2 lines
- fixed element ref="" top level- elements in code generator
- prepared 2.00_09 pre-release
------------------------------------------------------------------------
r135 | kutterma | 2007-08-12 14:44:06 +0200 (So, 12 Aug 2007) | 1 line
- prepared 2.00_09 pre-release
------------------------------------------------------------------------
r134 | kutterma | 2007-08-12 14:30:33 +0200 (So, 12 Aug 2007) | 2 lines
- updated README
- bumped up version
------------------------------------------------------------------------
r133 | kutterma | 2007-08-12 14:27:17 +0200 (So, 12 Aug 2007) | 1 line
- fixed Build.PL to leave Makefile.PL untouched.
------------------------------------------------------------------------
r132 | kutterma | 2007-08-12 14:21:24 +0200 (So, 12 Aug 2007) | 1 line
- now really added Makefile.PL
------------------------------------------------------------------------
r131 | kutterma | 2007-08-12 14:18:59 +0200 (So, 12 Aug 2007) | 3 lines
- fixed documentation for generated code with element ref="" declarations
- fixed element ref="" test for generated code
- added (generated) Makefile.PL to make CPAN testers happy
------------------------------------------------------------------------
r130 | kutterma | 2007-08-10 15:57:12 +0200 (Fr, 10 Aug 2007) | 1 line
- first try at truely callback-based parser (inspired by XML::Compile)
------------------------------------------------------------------------
r129 | kutterma | 2007-08-07 17:53:40 +0200 (Di, 07 Aug 2007) | 1 line
- moved duplicate sub generation out of loop
------------------------------------------------------------------------
r128 | kutterma | 2007-08-07 14:16:28 +0200 (Di, 07 Aug 2007) | 1 line
- bool now returns numerical value in bool context, not "true" or "false" (always true...)
------------------------------------------------------------------------
r127 | kutterma | 2007-08-07 11:45:23 +0200 (Di, 07 Aug 2007) | 1 line
- fixed test to be timezone sensitive
------------------------------------------------------------------------
r126 | kutterma | 2007-08-07 11:09:51 +0200 (Di, 07 Aug 2007) | 1 line
- made test timezone-sensitive
------------------------------------------------------------------------
r125 | kutterma | 2007-08-07 11:09:16 +0200 (Di, 07 Aug 2007) | 1 line
- made test timezone-sensitive
------------------------------------------------------------------------
r124 | kutterma | 2007-08-06 18:05:02 +0200 (Mo, 06 Aug 2007) | 2 lines
- fixed element ref handling in code generator in ComplexType.
- top-level element ref still not supported/tested
------------------------------------------------------------------------
r123 | kutterma | 2007-08-06 17:48:57 +0200 (Mo, 06 Aug 2007) | 1 line
- test now dies and outputs code to eval on eval errors
------------------------------------------------------------------------
r122 | kutterma | 2007-08-06 17:29:46 +0200 (Mo, 06 Aug 2007) | 1 line
- fixed element ref="" handling in complexType
------------------------------------------------------------------------
r121 | kutterma | 2007-08-06 17:29:14 +0200 (Mo, 06 Aug 2007) | 1 line
- added test data for element ref inside complexType
------------------------------------------------------------------------
r120 | kutterma | 2007-08-06 17:28:54 +0200 (Mo, 06 Aug 2007) | 1 line
- added test for element ref inside complexType
------------------------------------------------------------------------
r119 | kutterma | 2007-08-06 17:13:03 +0200 (Mo, 06 Aug 2007) | 1 line
- fixed element ref handling
------------------------------------------------------------------------
r118 | kutterma | 2007-08-06 17:12:47 +0200 (Mo, 06 Aug 2007) | 1 line
- added element ref test data
------------------------------------------------------------------------
r117 | kutterma | 2007-08-06 17:12:36 +0200 (Mo, 06 Aug 2007) | 1 line
- added element ref test
------------------------------------------------------------------------
r116 | kutterma | 2007-08-06 15:47:30 +0200 (Mo, 06 Aug 2007) | 1 line
- refined docs
------------------------------------------------------------------------
r115 | kutterma | 2007-08-06 15:39:39 +0200 (Mo, 06 Aug 2007) | 1 line
- updated docs. Hope the CPAN indexer ignores "=for developers"...
------------------------------------------------------------------------
r114 | kutterma | 2007-08-06 14:12:28 +0200 (Mo, 06 Aug 2007) | 1 line
- removed annoying pod
------------------------------------------------------------------------
r113 | kutterma | 2007-08-05 18:42:09 +0200 (So, 05 Aug 2007) | 5 lines
- removed SOAP::Lite dependency
- updated docs
- changed SOAP::WSDL::XSD::Typelib::ComplexType to require the actuall class for element data, not just the base class (good for finding errors earlier)
- implemented returning SOAP::SOM objects in SOAP::WSDL
- added SOAP::WSDL example(weather_wsdl.pl)
------------------------------------------------------------------------
r112 | kutterma | 2007-08-03 16:12:57 +0200 (Fr, 03 Aug 2007) | 1 line
updated docs
------------------------------------------------------------------------
r111 | kutterma | 2007-08-03 16:12:04 +0200 (Fr, 03 Aug 2007) | 1 line
- added "skip"
------------------------------------------------------------------------
r110 | kutterma | 2007-07-31 22:27:25 +0200 (Di, 31 Jul 2007) | 2 lines
- further work on removing SOAP::Lite dependency
- Note: SOAP::WSDL may be broken !
------------------------------------------------------------------------
r109 | kutterma | 2007-07-31 21:10:40 +0200 (Di, 31 Jul 2007) | 3 lines
- finished move from XSD::Primitive to Builtin
- fixed a few tests
- removed typo namespace from TypeLookupt
------------------------------------------------------------------------
r108 | kutterma | 2007-07-31 21:02:43 +0200 (Di, 31 Jul 2007) | 1 line
- removed unneeded example stuff
------------------------------------------------------------------------
r107 | kutterma | 2007-07-31 20:32:43 +0200 (Di, 31 Jul 2007) | 1 line
- rename to Builtin
------------------------------------------------------------------------
r106 | kutterma | 2007-07-31 20:32:11 +0200 (Di, 31 Jul 2007) | 1 line
- prepared rename to Builtin
------------------------------------------------------------------------
r105 | kutterma | 2007-07-31 13:17:52 +0200 (Di, 31 Jul 2007) | 2 lines
- added configurable ContentType / charset
- maybe split up charset and content type into two methods ?
------------------------------------------------------------------------
r104 | kutterma | 2007-07-31 00:16:15 +0200 (Di, 31 Jul 2007) | 3 lines
- removed optional nanoseconds from dateTime conversions
- added conversion to date objects
- removed fetching WSDL via SOAP::Schema in SOAP::WSDL. SOAP::Lite is still used as base class.
------------------------------------------------------------------------
r103 | kutterma | 2007-07-30 13:25:06 +0200 (Mo, 30 Jul 2007) | 1 line
- updated TODO
------------------------------------------------------------------------
r102 | kutterma | 2007-07-30 13:23:09 +0200 (Mo, 30 Jul 2007) | 2 lines
- updated Build.PL dependencies
- update TODO
------------------------------------------------------------------------
r101 | kutterma | 2007-07-30 13:22:05 +0200 (Mo, 30 Jul 2007) | 2 lines
- added dateTime test
- fixed pod test
------------------------------------------------------------------------
r100 | kutterma | 2007-07-27 16:03:15 +0200 (Fr, 27 Jul 2007) | 2 lines
- allow passing list refs of hash refs to set_value.
I hope I got all combinations by now - start getting ugly...
------------------------------------------------------------------------
r99 | kutterma | 2007-07-26 23:18:35 +0200 (Do, 26 Jul 2007) | 1 line
- added SOAP::Lite usage (to be removed later)
------------------------------------------------------------------------
r98 | kutterma | 2007-07-26 23:16:30 +0200 (Do, 26 Jul 2007) | 3 lines
- removed SOAP::Lite dependency
- added set_trace and tracing facility support via callback in call()
- added fault_class property to allow different Fault classes (somewhen later on)
------------------------------------------------------------------------
r97 | kutterma | 2007-07-25 16:59:49 +0200 (Mi, 25 Jul 2007) | 3 lines
- dateTime now converts date strings into XML date strings
- updated docs
------------------------------------------------------------------------
r96 | kutterma | 2007-07-23 11:17:36 +0200 (Mo, 23 Jul 2007) | 3 lines
- SOAP::WSDL::Definitions::create now
- converts '.' in service names to '::' (.NET class separator to perl class separator)
- outputs Typemaps and Interface classes in UTF8 to allow proper inclusion of UTF8 documentation from WSDL
------------------------------------------------------------------------
r95 | kutterma | 2007-07-23 10:26:59 +0200 (Mo, 23 Jul 2007) | 1 line
- typo
------------------------------------------------------------------------
r94 | kutterma | 2007-07-23 10:11:46 +0200 (Mo, 23 Jul 2007) | 1 line
- typo
------------------------------------------------------------------------
r93 | kutterma | 2007-07-22 23:24:12 +0200 (So, 22 Jul 2007) | 1 line
updated TODO
------------------------------------------------------------------------
r92 | kutterma | 2007-07-22 23:19:15 +0200 (So, 22 Jul 2007) | 3 lines
- WSDLHandler now handles <wsdl:documentation> tags
- SOAP::WSDL::Definitions now includes some usable doc in generated interface classes
- fixed explain in SimpleType, ComplexType and Element (someway)
------------------------------------------------------------------------
r91 | kutterma | 2007-07-22 21:18:21 +0200 (So, 22 Jul 2007) | 1 line
- updated docs
------------------------------------------------------------------------
r90 | kutterma | 2007-07-22 15:42:23 +0200 (So, 22 Jul 2007) | 1 line
- updated docs
------------------------------------------------------------------------
r89 | kutterma | 2007-07-22 15:38:25 +0200 (So, 22 Jul 2007) | 2 lines
- updated docs
- removed useless docs from "internally used only" - modules
------------------------------------------------------------------------
r88 | kutterma | 2007-07-22 09:17:57 +0200 (So, 22 Jul 2007) | 1 line
typo
------------------------------------------------------------------------
r87 | kutterma | 2007-07-21 23:57:46 +0200 (Sa, 21 Jul 2007) | 1 line
- updated docs
------------------------------------------------------------------------
r86 | kutterma | 2007-07-21 23:24:24 +0200 (Sa, 21 Jul 2007) | 5 lines
- removed irritating pod from SOAP::WSDL::XSD::Typelib::Builtin::* classes and put int into SOAP::WSDL::XSD::Typelib::Builtin
- added fast constructor creation BEGIN block to all SOAP::WSDL::XSD::Typelib::Builtin::* classes
- added examples
- updated docs
- prepared 2.00_07 pre-release
------------------------------------------------------------------------
r85 | kutterma | 2007-07-21 18:12:49 +0200 (Sa, 21 Jul 2007) | 4 lines
- added wsdl2perl code generation script - works against FortuneCookie web service at fullerdata.com
- fixed SOAP::WSDL::Client::Base to work as base class for generated classes
- added interface generation facility to SOAP::WSDL::Definitions
- updated docs (a few)
------------------------------------------------------------------------
r84 | kutterma | 2007-07-20 15:37:40 +0200 (Fr, 20 Jul 2007) | 9 lines
- added Expat-based parser
- made Expat-based parser the default
- added fast "new" method to most important "Builtin" types
- added Parser POD
- fixed propagating element names in complex types to element elements - element ref="element" should work on
class level now (don't know whether typelib supports it yet)
- updated tests
- updated HACKING
- prepared 2.00_06 release
------------------------------------------------------------------------
r83 | kutterma | 2007-07-19 13:09:33 +0200 (Do, 19 Jul 2007) | 1 line
- fixed element class generation (removed additional ::)
------------------------------------------------------------------------
r82 | kutterma | 2007-07-17 22:17:02 +0200 (Di, 17 Jul 2007) | 1 line
- updated README and HACKING
------------------------------------------------------------------------
r81 | kutterma | 2007-07-17 22:00:14 +0200 (Di, 17 Jul 2007) | 5 lines
- added parent ref in SOAP::WSDL::Base - now we have a real tree, and maybe can completely support namespaces some day
- replaced grep by List::Util::first where appropriate
- code cleanup
- fixed test for Code Generation
- updated a few tests
------------------------------------------------------------------------
r80 | kutterma | 2007-07-17 17:00:48 +0200 (Di, 17 Jul 2007) | 1 line
- improved pod in generated classes
------------------------------------------------------------------------
r79 | kutterma | 2007-07-17 14:41:44 +0200 (Di, 17 Jul 2007) | 1 line
- made explain look nicer
------------------------------------------------------------------------
r78 | kutterma | 2007-07-15 12:25:03 +0200 (So, 15 Jul 2007) | 7 lines
- SOAP::WSDL::Definitions can now generate
- Typemaps
- Type and Element classes
- fixed SOAP::WSDL::XSD::Typelib::ComplexType to support elements with type="ComplexType" definitions
- moved toClass method in SOAP::WSDL::XSD::ComplexType, Element and SimpleType to to_class and added compatibility wrapper with warning for toClass calls
- added generator test
- updated docs
------------------------------------------------------------------------
r77 | kutterma | 2007-07-14 10:46:54 +0200 (Sa, 14 Jul 2007) | 1 line
- started working on high-level code generator
------------------------------------------------------------------------
r76 | kutterma | 2007-07-13 09:21:33 +0200 (Fr, 13 Jul 2007) | 1 line
- fixed handling of complex data (hashes with lists embedded lists of objects)
------------------------------------------------------------------------
r75 | kutterma | 2007-07-10 12:08:39 +0200 (Di, 10 Jul 2007) | 1 line
- removed unneeded SOAP::Lite calls
------------------------------------------------------------------------
r74 | kutterma | 2007-07-10 12:08:10 +0200 (Di, 10 Jul 2007) | 1 line
- updated to new SOAP::Lite API
------------------------------------------------------------------------
r73 | kutterma | 2007-07-10 12:00:25 +0200 (Di, 10 Jul 2007) | 6 lines
- re-integrated old SOAP::WSDL tests
- updated docs
- SOAP::WSDL::XSD::Typelib::Builtin::string now escapes XML builtin entities on serialization
- SOAP::WSDL::XSD::Element now supports generating classes for elements and types into different namespaces
- SOAP::WSDL::Definitions now supports different namespaces for elements and types when generating typmaps
- 2.00_05 release preparation
------------------------------------------------------------------------
r72 | kutterma | 2007-07-06 11:20:56 +0200 (Fr, 06 Jul 2007) | 1 line
- fixed detail (typo)
------------------------------------------------------------------------
r71 | kutterma | 2007-07-05 16:13:28 +0200 (Do, 05 Jul 2007) | 1 line
- TODO comments added
------------------------------------------------------------------------
r70 | kutterma | 2007-07-04 16:14:50 +0200 (Mi, 04 Jul 2007) | 2 lines
- updated docs
- prepared 2.00_04 release
------------------------------------------------------------------------
r69 | kutterma | 2007-07-04 16:07:54 +0200 (Mi, 04 Jul 2007) | 1 line
- ComplexType now ignores xmlns - TODO: check xmlns, don't ignore...
------------------------------------------------------------------------
r68 | kutterma | 2007-07-04 11:25:31 +0200 (Mi, 04 Jul 2007) | 1 line
- made builtin types with overloads serializable
------------------------------------------------------------------------
r67 | kutterma | 2007-07-04 09:51:06 +0200 (Mi, 04 Jul 2007) | 4 lines
- updated docs
- removed unneeded uses from test
- added Build requirements from tests
- prepared 2.00_03 release
------------------------------------------------------------------------
r66 | kutterma | 2007-07-04 00:06:29 +0200 (Mi, 04 Jul 2007) | 3 lines
- split up builtin type lib into single files for Class::Std::Storable
- fixed more tests
- fixed complexType serialization for non-objecs
------------------------------------------------------------------------
r65 | kutterma | 2007-07-03 16:52:54 +0200 (Di, 03 Jul 2007) | 2 lines
- fixed a few tests
- added performance improvements
------------------------------------------------------------------------
r64 | kutterma | 2007-07-03 15:09:27 +0200 (Di, 03 Jul 2007) | 1 line
- small performance improvements
------------------------------------------------------------------------
r63 | kutterma | 2007-07-03 14:37:28 +0200 (Di, 03 Jul 2007) | 3 lines
- fixed serializing complextypes correctly
- fixed handling has attribute refs in new
- fixed performance problems in MessageHandler
------------------------------------------------------------------------
r62 | kutterma | 2007-07-03 14:37:14 +0200 (Di, 03 Jul 2007) | 1 line
- re-added
------------------------------------------------------------------------
r61 | kutterma | 2007-07-03 14:36:59 +0200 (Di, 03 Jul 2007) | 1 line
------------------------------------------------------------------------
r60 | kutterma | 2007-07-01 09:52:41 +0200 (So, 01 Jul 2007) | 2 lines
- fixed lots of tests
- attic tests may be re-integrated now...
------------------------------------------------------------------------
r59 | kutterma | 2007-06-28 13:07:35 +0200 (Do, 28 Jun 2007) | 1 line
- added ignore for dist tar.gz
------------------------------------------------------------------------
r58 | kutterma | 2007-06-28 13:06:25 +0200 (Do, 28 Jun 2007) | 1 line
- updated buildrequires
------------------------------------------------------------------------
r57 | kutterma | 2007-06-28 13:05:03 +0200 (Do, 28 Jun 2007) | 1 line
- typo
------------------------------------------------------------------------
r56 | kutterma | 2007-06-28 11:15:24 +0200 (Do, 28 Jun 2007) | 1 line
- pre-release 2.00_01
------------------------------------------------------------------------
r55 | kutterma | 2007-06-28 10:23:20 +0200 (Do, 28 Jun 2007) | 1 line
- moved old tests to attic
------------------------------------------------------------------------
r54 | kutterma | 2007-06-28 10:15:41 +0200 (Do, 28 Jun 2007) | 1 line
- fixed a few typos
------------------------------------------------------------------------
r53 | kutterma | 2007-06-28 10:10:41 +0200 (Do, 28 Jun 2007) | 3 lines
- fixed MessageHandler to support deserializing into objects which return false in boolean context
- updated docs
- fixed Fault11 (named detail correctly)
------------------------------------------------------------------------
r52 | kutterma | 2007-06-27 17:36:01 +0200 (Mi, 27 Jun 2007) | 3 lines
- added Fault for SOAP 1.1 implementation
- fixed ComplexType - though it doesn't work quite for faults yet...
------------------------------------------------------------------------
r51 | kutterma | 2007-06-27 13:27:59 +0200 (Mi, 27 Jun 2007) | 13 lines
- added test for sending objects via call()
- modified Client to accept objects of type SOAP::WSDL::XSD::Typelib::Builtin::anyType as message content
without checking the WSDL objects
Note:
- SOAPAction is just guessed - needs to be replaced by something better
- The method should be looked up from the typelib, too, and serialized according to the rules specified in the WSDL
and dumped into the typelib.
- updated to_typelib to include top element
- fixed element and complextype templates for toClass
------------------------------------------------------------------------
r50 | kutterma | 2007-06-27 00:01:32 +0200 (Mi, 27 Jun 2007) | 1 line
- added xsi xmlns to envelope
------------------------------------------------------------------------
r49 | kutterma | 2007-06-26 23:52:18 +0200 (Di, 26 Jun 2007) | 1 line
- cosmetics and a few doc updates
------------------------------------------------------------------------
r48 | kutterma | 2007-06-26 22:47:52 +0200 (Di, 26 Jun 2007) | 2 lines
- refactored element serializing to make it somewhat more consistent
- added nillable implementation for Elements
------------------------------------------------------------------------
r47 | kutterma | 2007-06-26 18:06:59 +0200 (Di, 26 Jun 2007) | 1 line
- removed shebang
------------------------------------------------------------------------
r46 | kutterma | 2007-06-26 18:06:33 +0200 (Di, 26 Jun 2007) | 1 line
- added warnings
------------------------------------------------------------------------
r45 | kutterma | 2007-06-26 17:39:09 +0200 (Di, 26 Jun 2007) | 3 lines
- got toClass working for generating WSDL based type libraries.
- changed typelib base class behavior to qualify first element called.
TODO (a bigger one): Fully support namespaces...
------------------------------------------------------------------------
r44 | kutterma | 2007-06-26 12:10:33 +0200 (Di, 26 Jun 2007) | 14 lines
- changed Typelib::Element to work as attribute of a type (serialize serializes start_tag and end_tag provided by Typelib::Element around it's vontent, if present)
- worked on toClass functionality with embedded templates.
There's much to do - current impl should support:
* <element name="name" type="type"
* <element name="name"><simpleType>
* <element name="name"><complexType>
* <simpleType ...><list>
* <simpleType ...><restriction>
* <complexType ...><all>
* <complexType ...><sequence>
All other variants are not completely supported yet.
------------------------------------------------------------------------
r43 | kutterma | 2007-06-25 18:58:56 +0200 (Mo, 25 Jun 2007) | 1 line
- broke element again...
------------------------------------------------------------------------
r42 | kutterma | 2007-06-25 17:30:34 +0200 (Mo, 25 Jun 2007) | 3 lines
- fixed to_typemap to report atomic simple and complex types correctly
- update tests
- renamed WSDLFilter to WSDLHandler
------------------------------------------------------------------------
r41 | kutterma | 2007-06-25 17:29:41 +0200 (Mo, 25 Jun 2007) | 1 line
------------------------------------------------------------------------
r40 | kutterma | 2007-06-25 14:15:40 +0200 (Mo, 25 Jun 2007) | 2 lines
- Client.pm now uses XML::LibXML as default and falls back on XML::SAX::ParserFactory if not present
- fixed tests
------------------------------------------------------------------------
r39 | kutterma | 2007-06-25 14:07:28 +0200 (Mo, 25 Jun 2007) | 2 lines
- typo in Element
- fixed tests
------------------------------------------------------------------------
r38 | kutterma | 2007-06-25 10:31:20 +0200 (Mo, 25 Jun 2007) | 2 lines
- made WSDLFilter.pm a inside out class and let it run without XML::SAX::Base (This probably breaks a lot of tests - we need to implement XML::LibXML semantics in all tests / classes which use it)
- first swag at to_typemap Typemap generation. to_typemap implemented throughout the WSDL:: modules. Some implementations (Elenenet.pm, ComplexType.pm) need further work for correctly handling atomic simpleType / complexType definitions.
------------------------------------------------------------------------
r37 | kutterma | 2007-06-24 09:15:22 +0200 (So, 24 Jun 2007) | 3 lines
- added test for on-the-fly created ComplexType
- fixed ComplexType factory to really work
- startet working on Element facets
------------------------------------------------------------------------
r36 | kutterma | 2007-06-24 09:14:46 +0200 (So, 24 Jun 2007) | 2 lines
- added test for on-the-fly created ComplexType
- startet working on Element facets
------------------------------------------------------------------------
r35 | kutterma | 2007-06-24 08:13:32 +0200 (So, 24 Jun 2007) | 1 line
- implemented ComplexType as class factory to get rid of the annoying START every subclass had to implement.
------------------------------------------------------------------------
r34 | kutterma | 2007-06-23 23:22:35 +0200 (Sa, 23 Jun 2007) | 2 lines
- added XSD Typelib SimpleType, Element and ComplexType base classes (stereotypes).
ComplexType's not yet complete (no restriction / extension etc. handling).
------------------------------------------------------------------------
r33 | kutterma | 2007-06-23 11:04:56 +0200 (Sa, 23 Jun 2007) | 2 lines
- added SOAP::WSDL::XSD::Typelib::Builtin implementation of builtin XML Schema datatypes with built-in stringification, boolification and numerification.
- SAX::MessageHandler now deserializes simple types in SOAP messages into SOAP::WSDL::XSD::Typelib::Builtin (provided these are named in the ClassResolver...)
------------------------------------------------------------------------
r32 | kutterma | 2007-06-23 02:14:16 +0200 (Sa, 23 Jun 2007) | 4 lines
- added pod
- added ref handling for elements
- added abstract handling for elements (easy...)
- added storing of content model (simpleContent/complexContent) to simpleType and complexType, though the attribute is still ignored in serializing
------------------------------------------------------------------------
r31 | kutterma | 2007-06-23 00:37:18 +0200 (Sa, 23 Jun 2007) | 1 line
- renamed MessageFilter to MessageHandler
------------------------------------------------------------------------
r30 | kutterma | 2007-06-23 00:35:54 +0200 (Sa, 23 Jun 2007) | 1 line
- renamed MessageFilter to MessageHandler
------------------------------------------------------------------------
r29 | kutterma | 2007-06-23 00:35:16 +0200 (Sa, 23 Jun 2007) | 2 lines
- switched to Class::Std::Storable
- renamed MessageFilter to MessageHandler
------------------------------------------------------------------------
r28 | kutterma | 2007-06-22 18:56:28 +0200 (Fr, 22 Jun 2007) | 3 lines
- optimised SOAP::WSDL::SAX::MessageFilter for performance
- moved Typelob into own directory and load it dynamically from test script
- added some pod
------------------------------------------------------------------------
r27 | kutterma | 2007-06-22 15:34:28 +0200 (Fr, 22 Jun 2007) | 5 lines
- modified SOAP::WSDL::XSD lib to allow serializing of object hierarchies
- added SOAP::WSDL::SAX::MessageFilter for creating object hierarchies from SOAP messages
- moved Builtin XML Schema types to SOAP::WSDL:XSD::Schema::Builtin
- added test + benchmark for serializing /deserializing SOAP messages into object trees
- fixed Client to use SOAP::WSDL::Types as typelib, not first SOAP::WSDL::XSD::Schema
------------------------------------------------------------------------
r26 | kutterma | 2007-06-21 23:35:30 +0200 (Do, 21 Jun 2007) | 2 lines
- first swag at a typed SOAP Message parser.
Typelib is still to be implemented...
------------------------------------------------------------------------
r25 | kutterma | 2007-06-21 18:14:49 +0200 (Do, 21 Jun 2007) | 1 line
- added missing files from last commit
------------------------------------------------------------------------
r24 | kutterma | 2007-06-19 00:29:36 +0200 (Di, 19 Jun 2007) | 3 lines
- worked a bit on explain
- introduced handling of multiple schema definitions in one WSDL file
- fixed propagating targetNamespace to child elements in WSDLFilter
------------------------------------------------------------------------
r23 | kutterma | 2007-06-16 14:48:30 +0200 (Sa, 16 Jun 2007) | 1 line
- updated new SOAP::WSDL framework to use inside out classes based on Class::Std (not yet complete)
------------------------------------------------------------------------
r22 | kutterma | 2007-06-12 23:19:41 +0200 (Di, 12 Jun 2007) | 4 lines
- updated a few tests
- fixed a few WSDLs
- fixed handling of elements with minOccurs 0
- fixed setting of minOccurs/maxOccurs for all/sequence complexTypes
------------------------------------------------------------------------
r21 | kutterma | 2007-06-08 21:38:41 +0200 (Fr, 08 Jun 2007) | 2 lines
- updated a few tests
- fixed namespaces in tests
------------------------------------------------------------------------
r19 | kutterma | 2007-05-31 16:58:18 +0200 (Do, 31 Mai 2007) | 10 lines
- first swag at a WSDL-generated Object-tree based SOAP client.
Works as following:
a) a sax filter transforms the sax stream from a wsdl into a perl object tree
b) the perl object tree has methods for performing the following tasks:
a) explain: Tell what services and methods are there, and how to use them
b) serialize: Serialize data structures to the XML defined in the WSDL & schema
c) The client uses the generated XML to call the SOAP Server. Unfortunately, SOAP::Lite
does not allow custom XML to be rendered as a method's "value", so we have to replace
call() completely and generate the envelope on our own (which is not complete yet).
------------------------------------------------------------------------
r9 | kutterma | 2007-05-28 17:08:41 +0200 (Mo, 28 Mai 2007) | 1 line
- first try at bindings support - see t/12/bindings on how we could find out bindings and portname from a target URL
------------------------------------------------------------------------
r4 | kutterma | 2007-05-28 15:15:03 +0200 (Mo, 28 Mai 2007) | 1 line
- move from private repository to sourceforge
------------------------------------------------------------------------
+31 -5
View File
@@ -21,6 +21,8 @@ example/lib/MyInterfaces/GlobalWeather.pm
example/lib/MyTypemaps/FullerData_x0020_Fortune_x0020_Cookie.pm example/lib/MyTypemaps/FullerData_x0020_Fortune_x0020_Cookie.pm
example/lib/MyTypemaps/GlobalWeather.pm example/lib/MyTypemaps/GlobalWeather.pm
example/weather.pl example/weather.pl
example/weather_wsdl.pl
example/weather_xml_compile.pl
example/wsdl/FortuneCookie.xml example/wsdl/FortuneCookie.xml
example/wsdl/genericbarcode.xml example/wsdl/genericbarcode.xml
example/wsdl/globalweather.xml example/wsdl/globalweather.xml
@@ -31,11 +33,16 @@ lib/SOAP/WSDL/Binding.pm
lib/SOAP/WSDL/Client.pm lib/SOAP/WSDL/Client.pm
lib/SOAP/WSDL/Client/Base.pm lib/SOAP/WSDL/Client/Base.pm
lib/SOAP/WSDL/Definitions.pm lib/SOAP/WSDL/Definitions.pm
lib/SOAP/WSDL/Envelope.pm
lib/SOAP/WSDL/Expat/MessageParser.pm lib/SOAP/WSDL/Expat/MessageParser.pm
lib/SOAP/WSDL/Expat/MessageStreamParser.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/Serializer.pm
lib/SOAP/WSDL/Factory/Transport.pm
lib/SOAP/WSDL/Manual.pod lib/SOAP/WSDL/Manual.pod
lib/SOAP/WSDL/Manual/Glossary.pod lib/SOAP/WSDL/Manual/Glossary.pod
lib/SOAP/WSDL/Manual/WS_I_BasicProfile_Compliance.pod
lib/SOAP/WSDL/Message.pm lib/SOAP/WSDL/Message.pm
lib/SOAP/WSDL/Operation.pm lib/SOAP/WSDL/Operation.pm
lib/SOAP/WSDL/OpMessage.pm lib/SOAP/WSDL/OpMessage.pm
@@ -43,16 +50,19 @@ lib/SOAP/WSDL/Parser.pod
lib/SOAP/WSDL/Part.pm lib/SOAP/WSDL/Part.pm
lib/SOAP/WSDL/Port.pm lib/SOAP/WSDL/Port.pm
lib/SOAP/WSDL/PortType.pm lib/SOAP/WSDL/PortType.pm
lib/SOAP/WSDL/RELEASE_NOTES
lib/SOAP/WSDL/SAX/MessageHandler.pm lib/SOAP/WSDL/SAX/MessageHandler.pm
lib/SOAP/WSDL/SAX/WSDLHandler.pm lib/SOAP/WSDL/SAX/WSDLHandler.pm
lib/SOAP/WSDL/Serializer/SOAP11.pm
lib/SOAP/WSDL/Service.pm lib/SOAP/WSDL/Service.pm
lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm
lib/SOAP/WSDL/SoapOperation.pm lib/SOAP/WSDL/SoapOperation.pm
lib/SOAP/WSDL/Transport/HTTP.pm
lib/SOAP/WSDL/TypeLookup.pm lib/SOAP/WSDL/TypeLookup.pm
lib/SOAP/WSDL/Types.pm lib/SOAP/WSDL/Types.pm
lib/SOAP/WSDL/XSD/Builtin.pm
lib/SOAP/WSDL/XSD/ComplexType.pm lib/SOAP/WSDL/XSD/ComplexType.pm
lib/SOAP/WSDL/XSD/Element.pm lib/SOAP/WSDL/XSD/Element.pm
lib/SOAP/WSDL/XSD/Primitive.pm
lib/SOAP/WSDL/XSD/Schema.pm lib/SOAP/WSDL/XSD/Schema.pm
lib/SOAP/WSDL/XSD/Schema/Builtin.pm lib/SOAP/WSDL/XSD/Schema/Builtin.pm
lib/SOAP/WSDL/XSD/SimpleType.pm lib/SOAP/WSDL/XSD/SimpleType.pm
@@ -107,13 +117,18 @@ lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm
lib/SOAP/WSDL/XSD/Typelib/Element.pm lib/SOAP/WSDL/XSD/Typelib/Element.pm
lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm lib/SOAP/WSDL/XSD/Typelib/SimpleType.pm
LICENSE LICENSE
MANIFEST Makefile.PL
MANIFEST This list of files
META.yml META.yml
README README
t/001_use.t t/001_use.t
t/002_parse_wsdl.t
t/002_sax.t t/002_sax.t
t/003_sax_serializer.t t/003_sax_serializer.t
t/003_wsdl_based_serializer.t
t/004_parse_wsdl.t
t/004_sax_wsdl.t t/004_sax_wsdl.t
t/005_parse_contributed.t
t/005_sax_contributed_wsdl.t t/005_sax_contributed_wsdl.t
t/006_client.t t/006_client.t
t/007_envelope.t t/007_envelope.t
@@ -125,8 +140,13 @@ t/013_complexType.t
t/014_sax_typelib.t t/014_sax_typelib.t
t/015_to_typemap.t t/015_to_typemap.t
t/016_client_object.t t/016_client_object.t
t/017_generator.t t/017_generator_expat.t
t/017_generator_libxml.t
t/018_generator_expat.t
t/018_generator_libxml.t
t/020_storable.t t/020_storable.t
t/021_generator_element_ref_expat.t
t/021_generator_element_ref_libxml.t
t/098_pod.t t/098_pod.t
t/acceptance/results/03_complexType-all.xml t/acceptance/results/03_complexType-all.xml
t/acceptance/results/03_complexType-sequence.xml t/acceptance/results/03_complexType-sequence.xml
@@ -140,6 +160,7 @@ t/acceptance/wsdl/006_sax_client.wsdl
t/acceptance/wsdl/008_complexType.wsdl t/acceptance/wsdl/008_complexType.wsdl
t/acceptance/wsdl/02_port.wsdl t/acceptance/wsdl/02_port.wsdl
t/acceptance/wsdl/03_complexType-all.wsdl t/acceptance/wsdl/03_complexType-all.wsdl
t/acceptance/wsdl/03_complexType-element-ref.wsdl
t/acceptance/wsdl/03_complexType-sequence.wsdl t/acceptance/wsdl/03_complexType-sequence.wsdl
t/acceptance/wsdl/04_element-simpleType.wsdl t/acceptance/wsdl/04_element-simpleType.wsdl
t/acceptance/wsdl/04_element.wsdl t/acceptance/wsdl/04_element.wsdl
@@ -154,6 +175,8 @@ t/acceptance/wsdl/contributed/OITest.wsdl
t/acceptance/wsdl/contributed/tools.wsdl t/acceptance/wsdl/contributed/tools.wsdl
t/acceptance/wsdl/email_account.wsdl t/acceptance/wsdl/email_account.wsdl
t/Expat/01_expat.t t/Expat/01_expat.t
t/Expat/02_sub_parser.t
t/Expat/03_wsdl.t
t/lib/MyComplexType.pm t/lib/MyComplexType.pm
t/lib/MyElement.pm t/lib/MyElement.pm
t/lib/MySimpleType.pm t/lib/MySimpleType.pm
@@ -166,6 +189,7 @@ t/SOAP/WSDL/02_port.t
t/SOAP/WSDL/03_complexType-all.t t/SOAP/WSDL/03_complexType-all.t
t/SOAP/WSDL/03_complexType-choice.t t/SOAP/WSDL/03_complexType-choice.t
t/SOAP/WSDL/03_complexType-complexContent.t t/SOAP/WSDL/03_complexType-complexContent.t
t/SOAP/WSDL/03_complexType-element-ref.t
t/SOAP/WSDL/03_complexType-group.t t/SOAP/WSDL/03_complexType-group.t
t/SOAP/WSDL/03_complexType-sequence.t t/SOAP/WSDL/03_complexType-sequence.t
t/SOAP/WSDL/03_complexType-simpleContent.t t/SOAP/WSDL/03_complexType-simpleContent.t
@@ -175,8 +199,10 @@ t/SOAP/WSDL/04_element.t
t/SOAP/WSDL/05_simpleType-list.t t/SOAP/WSDL/05_simpleType-list.t
t/SOAP/WSDL/05_simpleType-restriction.t t/SOAP/WSDL/05_simpleType-restriction.t
t/SOAP/WSDL/05_simpleType-union.t t/SOAP/WSDL/05_simpleType-union.t
t/SOAP/WSDL/10_performance.t
t/SOAP/WSDL/11_helloworld.NET.t t/SOAP/WSDL/11_helloworld.NET.t
t/SOAP/WSDL/12_binding.pl t/SOAP/WSDL/12_binding.pl
t/SOAP/WSDL/XSD/Typelib/Builtin/001_string.t t/SOAP/WSDL/XSD/Typelib/Builtin/001_string.t
t/SOAP/WSDL/XSD/Typelib/Builtin/002_dateTime.t
t/SOAP/WSDL/XSD/Typelib/Builtin/002_time.t
t/SOAP/WSDL/XSD/Typelib/Builtin/003_date.t
TODO TODO
+19 -11
View File
@@ -1,21 +1,21 @@
--- ---
name: SOAP-WSDL name: SOAP-WSDL
version: 2.00_07 version: 2.00_11
author: author:
abstract: SOAP with WSDL support abstract: SOAP with WSDL support
license: artistic license: artistic
requires: requires:
Class::Std: v0.0.8 Class::Std: v0.0.8
Class::Std::Storable: 0 Class::Std::Storable: 0
Date::Format: 0
Date::Parse: 0
File::Basename: 0 File::Basename: 0
File::Path: 0 File::Path: 0
Getopt::Long: 0
LWP::UserAgent: 0
List::Util: 0 List::Util: 0
SOAP::Lite: 0 Template: 0
XML::LibXML: 0
XML::Parser::Expat: 0 XML::Parser::Expat: 0
XML::SAX::Base: 0
XML::SAX::ParserFactory: 0
XML::XPath: 0
generated_by: Module::Build version 0.2808 generated_by: Module::Build version 0.2808
meta-spec: meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.2.html url: http://module-build.sourceforge.net/META-spec-v1.2.html
@@ -23,7 +23,7 @@ meta-spec:
provides: provides:
SOAP::WSDL: SOAP::WSDL:
file: lib/SOAP/WSDL.pm file: lib/SOAP/WSDL.pm
version: 2.00_05 version: 2.00_10
SOAP::WSDL::Base: SOAP::WSDL::Base:
file: lib/SOAP/WSDL/Base.pm file: lib/SOAP/WSDL/Base.pm
SOAP::WSDL::Binding: SOAP::WSDL::Binding:
@@ -34,12 +34,16 @@ provides:
file: lib/SOAP/WSDL/Client/Base.pm file: lib/SOAP/WSDL/Client/Base.pm
SOAP::WSDL::Definitions: SOAP::WSDL::Definitions:
file: lib/SOAP/WSDL/Definitions.pm file: lib/SOAP/WSDL/Definitions.pm
SOAP::WSDL::Envelope:
file: lib/SOAP/WSDL/Envelope.pm
SOAP::WSDL::Expat::MessageParser: SOAP::WSDL::Expat::MessageParser:
file: lib/SOAP/WSDL/Expat/MessageParser.pm file: lib/SOAP/WSDL/Expat/MessageParser.pm
SOAP::WSDL::Expat::MessageStreamParser: SOAP::WSDL::Expat::MessageStreamParser:
file: lib/SOAP/WSDL/Expat/MessageStreamParser.pm file: lib/SOAP/WSDL/Expat/MessageStreamParser.pm
SOAP::WSDL::Expat::MessageSubParser:
file: lib/SOAP/WSDL/Expat/MessageSubParser.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: SOAP::WSDL::Message:
file: lib/SOAP/WSDL/Message.pm file: lib/SOAP/WSDL/Message.pm
SOAP::WSDL::OpMessage: SOAP::WSDL::OpMessage:
@@ -56,20 +60,24 @@ provides:
file: lib/SOAP/WSDL/SAX/MessageHandler.pm file: lib/SOAP/WSDL/SAX/MessageHandler.pm
SOAP::WSDL::SOAP::Typelib::Fault11: SOAP::WSDL::SOAP::Typelib::Fault11:
file: lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm file: lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm
SOAP::WSDL::Serializer::SOAP11:
file: lib/SOAP/WSDL/Serializer/SOAP11.pm
SOAP::WSDL::Service: SOAP::WSDL::Service:
file: lib/SOAP/WSDL/Service.pm file: lib/SOAP/WSDL/Service.pm
SOAP::WSDL::SoapOperation: SOAP::WSDL::SoapOperation:
file: lib/SOAP/WSDL/SoapOperation.pm file: lib/SOAP/WSDL/SoapOperation.pm
SOAP::WSDL::Transport::HTTP:
file: lib/SOAP/WSDL/Transport/HTTP.pm
SOAP::WSDL::TypeLookup: SOAP::WSDL::TypeLookup:
file: lib/SOAP/WSDL/TypeLookup.pm file: lib/SOAP/WSDL/TypeLookup.pm
SOAP::WSDL::Types: SOAP::WSDL::Types:
file: lib/SOAP/WSDL/Types.pm file: lib/SOAP/WSDL/Types.pm
SOAP::WSDL::XSD::Builtin:
file: lib/SOAP/WSDL/XSD/Builtin.pm
SOAP::WSDL::XSD::ComplexType: SOAP::WSDL::XSD::ComplexType:
file: lib/SOAP/WSDL/XSD/ComplexType.pm file: lib/SOAP/WSDL/XSD/ComplexType.pm
SOAP::WSDL::XSD::Element: SOAP::WSDL::XSD::Element:
file: lib/SOAP/WSDL/XSD/Element.pm file: lib/SOAP/WSDL/XSD/Element.pm
SOAP::WSDL::XSD::Primitive:
file: lib/SOAP/WSDL/XSD/Primitive.pm
SOAP::WSDL::XSD::Schema: SOAP::WSDL::XSD::Schema:
file: lib/SOAP/WSDL/XSD/Schema.pm file: lib/SOAP/WSDL/XSD/Schema.pm
SOAP::WSDL::XSD::Schema::Builtin: SOAP::WSDL::XSD::Schema::Builtin:
+31
View File
@@ -0,0 +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');
+24
View File
@@ -1,2 +1,26 @@
INTRO
-----
SOAP-WSDL provides a SOAP client with WSDL support.
This is a developer release - everything may (and most things will) change. This is a developer release - everything may (and most things will) change.
INSTALLING
----------
Use the following mantra:
perl Build.PL
perl Build
perl Build test
perl Build install
If you don't have Module::Build installed, you may also use
perl Makefile.PL
make
make test
make install
Note that Module::Build is the recommended installer - make will not run
all tests provided with SOAP-WSDL.
+33 -25
View File
@@ -1,27 +1,35 @@
- remove benchmarks from tests. Create benchmark/ directory and store benchmarks in. TODO list for SOAP::WSDL
- SOAP::WSDL::Definitions::create creates bad interface docs. Fix it.
- add tests for SOAP::WSDL::Definitions::create 2.00 Pre-releases
- test for correct creation --------
- test against web service (fullerdata.com?) * SOAP Header support (#1764845)
- Improve docs
- Remove SOAP::Lite dependency - for now, just support HTTP(s) via LWP::UserAgent. * Implement a interface similar to SOAP::Schema (#1783639)
- write inheritance Test for all XSD::Typelib::Builtin::* classes
- Check & probably fix simpleType support. * (#1785195) Support deserializer plugins
The WS at http://www.webservicex.net/genericbarcode.asmx?wsdl should make up a good example for simpleType * Support XML::Compiled as one serializer/deserializer
definitions.
- update all Builtin Types to new constructor BEGIN block (Class::Std unfortunately is way slow) * Check & probably fix simpleType support.
- DONE. The WS at http://www.webservicex.net/genericbarcode.asmx?wsdl should
- Remove useless (but on CPAN annoying) doc from Builtin::* classes make up a good example for simpleType definitions.
- DONE
- add example WS scripts * Remove benchmarks from test. Create benchmark/ directory to store benchmarks.
- DONE.
- SOAP::WSDL::XSD::Typelib::Builtin::string does not unescape XML builtin entities on get_value() * write inheritance Test for all XSD::Typelib::Builtin::* classes
- WONTFIX.
Entities are unescaped by XML parser. * support embedded atomic types (#1761532)
If you want the plain value, you have to use get_value, as XML conversion is overloaded on stringification. Implement by including a second (and third and fourth)
- Make callin WS easier: implent WS-I-based SOAP::WSDL::Client::WSI
- WONTFIX - SOAP::WSDL::Base should behave equal package type_prefix::complex_type::element_name;
- add capability to create request objects based on input part definitions to SOAP::WSDL::Client::Base
- DONE. element package.
Maybe even allow unlimited depth? What does the specs say?
2.1 release
--------
Past 2.1 release
--------
* XML schema support ("minimal conformant") (#1764845)
* Support SOAP attachments
+14 -14
View File
@@ -1,13 +1,10 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Fcntl;
use IO::File;
use Pod::Usage; use Pod::Usage;
use Getopt::Long; use Getopt::Long;
use LWP::Simple qw(get); use LWP::UserAgent;
use SOAP::WSDL::SAX::WSDLHandler; use SOAP::WSDL::Expat::WSDLParser;
use XML::LibXML;
my %opt = ( my %opt = (
url => '', url => '',
@@ -17,6 +14,7 @@ my %opt = (
typemap_prefix => 'MyTypemaps::', typemap_prefix => 'MyTypemaps::',
interface_prefix => 'MyInterfaces::', interface_prefix => 'MyInterfaces::',
base_path => 'lib/', base_path => 'lib/',
proxy => undef
); );
GetOptions(\%opt, GetOptions(\%opt,
@@ -29,6 +27,7 @@ GetOptions(\%opt,
base_path|b=s base_path|b=s
typemap_include|mi=s typemap_include|mi=s
help|h help|h
proxy|x=s
) )
); );
@@ -37,21 +36,22 @@ my $url = $ARGV[0];
pod2usage( -exit => 1 , verbose => 2 ) if ($opt{help}); pod2usage( -exit => 1 , verbose => 2 ) if ($opt{help});
pod2usage( -exit => 1 , verbose => 1 ) if not ($url); pod2usage( -exit => 1 , verbose => 1 ) if not ($url);
my $handler = SOAP::WSDL::SAX::WSDLHandler->new(); my $parser = SOAP::WSDL::Expat::WSDLParser->new();
my $parser = XML::LibXML->new();
my $xml = get($url) or die "Could not load WSDL schema $url\n"; local $ENV{HTTP_PROXY} = $opt{proxy} if $opt{proxy};
my $lwp = LWP::UserAgent->new();
my $response = $lwp->get($url);
die $response->message(), "\n" if $response->code != 200;
$parser->set_handler( $handler ); my $xml = $response->content();
$parser->parse_string( $xml );
my $wsdl = $handler->get_data(); my $wsdl = $parser->parse_string( $xml );
if ($opt{typemap_include}) { if ($opt{typemap_include}) {
my $fh = IO::File->new($opt{typemap_include} , O_RDONLY) open my $fh , $opt{typemap_include}
or die "cannot open typemap_include file $opt{typemap_include}\n"; or die "cannot open typemap_include file $opt{typemap_include}\n";
$opt{custom_types} = join q{}, $fh->getlines(); $opt{custom_types} .= join q{}, <$fh>;
$fh->close(); close $fh;
delete $opt{typemap_include}; delete $opt{typemap_include};
} }
+29 -15
View File
@@ -11,23 +11,37 @@
use lib 'lib/'; use lib 'lib/';
use MyInterfaces::FullerData_x0020_Fortune_x0020_Cookie; use MyInterfaces::FullerData_x0020_Fortune_x0020_Cookie;
use MyElements::GetFortuneCookie;
my $cookieService = MyInterfaces::FullerData_x0020_Fortune_x0020_Cookie->new(); my $cookieService = MyInterfaces::FullerData_x0020_Fortune_x0020_Cookie->new();
my $cookie = $cookieService->GetFortuneCookie(); my $cookie;
$cookie = $cookieService->GetFortuneCookie()
or die "$cookie";
if ($cookie) { print $cookie; # ->get_GetFortuneCookieResult()->get_value, "\n";
print $cookie->get_GetFortuneCookieResult()->get_value, "\n";
} $cookie = $cookieService->GetSpecificCookie({ index => 23 })
else { or die "$cookie";
print $cookie;
} print $cookie->get_GetSpecificCookieResult(), "\n";
$cookie = $cookieService->GetSpecificCookie({ index => 23 });
if ($cookie) {
print $cookie
->get_GetSpecificCookieResult(), "\n";
}
else {
print $cookie; print $cookie;
}
=for demo:
# the same in SOAP lite (second call)
#
use SOAP::Lite;
my $lite = SOAP::Lite->new()->on_action(sub { join '/', @_ } )
->proxy('http://www.fullerdata.com/FortuneCookie/FortuneCookie.asmx');
$lite->call(
SOAP::Data->name('GetSpecificCookie')
->attr({ 'xmlns', 'http://www.fullerdata.com/FortuneCookie/FortuneCookie.asmx' }),
SOAP::Data->name('index')->value(23)
);
die $soap->message() if ($soap->fault());
print $soap->result();
+9 -1
View File
@@ -3,6 +3,7 @@ use strict;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element; use SOAP::WSDL::XSD::Typelib::Element;
# atomic complexType # atomic complexType
# <element name="GetCitiesByCountry"><complexType> definition # <element name="GetCitiesByCountry"><complexType> definition
use SOAP::WSDL::XSD::Typelib::ComplexType; use SOAP::WSDL::XSD::Typelib::ComplexType;
@@ -46,9 +47,16 @@ __PACKAGE__->__set_ref('');
__END__ __END__
=pod =pod
=head1 NAME MyElements::GetCitiesByCountry =head1 NAME
MyElements::GetCitiesByCountry
=head1 SYNOPSIS =head1 SYNOPSIS
@@ -3,6 +3,7 @@ use strict;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element; use SOAP::WSDL::XSD::Typelib::Element;
# atomic complexType # atomic complexType
# <element name="GetCitiesByCountryResponse"><complexType> definition # <element name="GetCitiesByCountryResponse"><complexType> definition
use SOAP::WSDL::XSD::Typelib::ComplexType; use SOAP::WSDL::XSD::Typelib::ComplexType;
@@ -46,9 +47,16 @@ __PACKAGE__->__set_ref('');
__END__ __END__
=pod =pod
=head1 NAME MyElements::GetCitiesByCountryResponse =head1 NAME
MyElements::GetCitiesByCountryResponse
=head1 SYNOPSIS =head1 SYNOPSIS
+9 -1
View File
@@ -3,6 +3,7 @@ use strict;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element; use SOAP::WSDL::XSD::Typelib::Element;
# atomic complexType # atomic complexType
# <element name="GetWeather"><complexType> definition # <element name="GetWeather"><complexType> definition
use SOAP::WSDL::XSD::Typelib::ComplexType; use SOAP::WSDL::XSD::Typelib::ComplexType;
@@ -54,9 +55,16 @@ __PACKAGE__->__set_ref('');
__END__ __END__
=pod =pod
=head1 NAME MyElements::GetWeather =head1 NAME
MyElements::GetWeather
=head1 SYNOPSIS =head1 SYNOPSIS
+9 -1
View File
@@ -3,6 +3,7 @@ use strict;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element; use SOAP::WSDL::XSD::Typelib::Element;
# atomic complexType # atomic complexType
# <element name="GetWeatherResponse"><complexType> definition # <element name="GetWeatherResponse"><complexType> definition
use SOAP::WSDL::XSD::Typelib::ComplexType; use SOAP::WSDL::XSD::Typelib::ComplexType;
@@ -46,9 +47,16 @@ __PACKAGE__->__set_ref('');
__END__ __END__
=pod =pod
=head1 NAME MyElements::GetWeatherResponse =head1 NAME
MyElements::GetWeatherResponse
=head1 SYNOPSIS =head1 SYNOPSIS
+10 -2
View File
@@ -3,6 +3,7 @@ use strict;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element; use SOAP::WSDL::XSD::Typelib::Element;
# #
# <element name="string" type="s:string"/> definition # <element name="string" type="s:string"/> definition
# #
@@ -13,7 +14,7 @@ use base qw(
); );
sub get_xmlns { 'http://www.fullerdata.com/FortuneCookie/FortuneCookie.asmx' } sub get_xmlns { 'http://www.webserviceX.NET' }
__PACKAGE__->__set_name('string'); __PACKAGE__->__set_name('string');
__PACKAGE__->__set_nillable(true); __PACKAGE__->__set_nillable(true);
@@ -26,9 +27,16 @@ __PACKAGE__->__set_ref('');
__END__ __END__
=pod =pod
=head1 NAME MyElements::string =head1 NAME
MyElements::string
=head1 SYNOPSIS =head1 SYNOPSIS
+31 -207
View File
@@ -1,4 +1,5 @@
package MyInterfaces::GlobalWeather; package MyInterfaces::GlobalWeather;
use strict; use strict;
use warnings; use warnings;
use MyTypemaps::GlobalWeather; use MyTypemaps::GlobalWeather;
@@ -16,8 +17,18 @@ sub new {
} }
__PACKAGE__->__create_methods( __PACKAGE__->__create_methods(
GetWeather => [ 'MyElements::GetWeather', ], GetWeather => {
GetCitiesByCountry => [ 'MyElements::GetCitiesByCountry', ], parts => [ 'MyElements::GetWeather', ],
soap_action => 'http://www.webserviceX.NET/GetWeather',
style => 'document',
# use => '', # use not implemented yet
},
GetCitiesByCountry => {
parts => [ 'MyElements::GetCitiesByCountry', ],
soap_action => 'http://www.webserviceX.NET/GetCitiesByCountry',
style => 'document',
# use => '', # use not implemented yet
},
); );
@@ -25,6 +36,10 @@ __PACKAGE__->__create_methods(
__END__ __END__
=pod =pod
=head1 NAME =head1 NAME
@@ -38,222 +53,31 @@ http://www.webservicex.net/globalweather.asmx
my $GetCitiesByCountry = $interface->GetCitiesByCountry(); my $GetCitiesByCountry = $interface->GetCitiesByCountry();
=head1 Service GlobalWeather =head1 METHODS
=head2 Service information: =head2 GetWeather
Port name: GlobalWeatherSoap Get weather report for all major cities around the world.
Binding: tns:GlobalWeatherSoap
Location: http://www.webservicex.net/globalweather.asmx
=head2 SOAP Operations SYNOPSIS:
B<Note:> $service->GetWeather({
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.
=head3 GetWeather
B<Input Message:>
{
'GetWeather'=> {
'CityName' => $someValue, 'CityName' => $someValue,
'CountryName' => $someValue, 'CountryName' => $someValue,
}, });
}
B<Output Message:> =head2 GetCitiesByCountry
{ Get all major cities by country name(full / part).
'GetWeather'=> {
'CityName' => $someValue, SYNOPSIS:
$service->GetCitiesByCountry({
'CountryName' => $someValue, 'CountryName' => $someValue,
}, });
}
B<Fault:>
=pod
=head3 GetCitiesByCountry
B<Input Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Output Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Fault:>
=head2 Service information:
Port name: GlobalWeatherHttpGet
Binding: tns:GlobalWeatherHttpGet
Location:
=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.
=head3 GetWeather
B<Input Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Output Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Fault:>
=head3 GetCitiesByCountry
B<Input Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Output Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Fault:>
=head2 Service information:
Port name: GlobalWeatherHttpPost
Binding: tns:GlobalWeatherHttpPost
Location:
=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.
=head3 GetWeather
B<Input Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Output Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Fault:>
=head3 GetCitiesByCountry
B<Input Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Output Message:>
{
'GetWeather'=> {
'CityName' => $someValue,
'CountryName' => $someValue,
},
}
B<Fault:>
=cut
+11 -6
View File
@@ -3,6 +3,14 @@ use strict;
use warnings; use warnings;
my %typemap = ( 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
'GetWeather' => 'MyElements::GetWeather', 'GetWeather' => 'MyElements::GetWeather',
# atomic complex type (sequence) # atomic complex type (sequence)
'GetWeather/CityName' => 'SOAP::WSDL::XSD::Typelib::Builtin::string', 'GetWeather/CityName' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
@@ -24,12 +32,9 @@ my %typemap = (
'GetCitiesByCountryResponse/GetCitiesByCountryResult' => 'SOAP::WSDL::XSD::Typelib::Builtin::string', 'GetCitiesByCountryResponse/GetCitiesByCountryResult' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# end atomic complex type (sequence) # end atomic complex type (sequence)
Fault => 'SOAP::WSDL::SOAP::Typelib::Fault11',
'Fault/faultstring' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'Fault/faultcode' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'Fault/faultactor' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'Fault/faultactor' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'Fault/detail' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
); );
+10 -9
View File
@@ -1,19 +1,20 @@
# Accessing the fortune cookie service at # Accessing the globalweather service at
# www.webservicex.net/GlobalWeather/GlobalWeather.asmx # www.webservicex.net/GlobalWeather/GlobalWeather.asmx
# #
# I have no connection to www.webservicex.net # Note that the GlobalWeather web service returns a (quoted) XML structure -
# don't be surprised by the response's format.
# #
# I have no connection to www.webservicex.net
# Use this script at your own risk. # Use this script at your own risk.
#
# This script demonstrates the use of a interface generated by wsdl2perl.pl
use lib 'lib/'; use lib 'lib/';
use MyInterfaces::GlobalWeather; use MyInterfaces::GlobalWeather;
my $webservice = MyInterfaces::GlobalWeather->new(); my $weather = MyInterfaces::GlobalWeather->new();
my $result = $weather->GetWeather({ CountryName => 'Germany', CityName => 'Munich' });
my $result = $webservice->GetWeather({ CountryName => 'Germany', CityName => 'Munich' }); # boolean comparison overloaded
die $result->get_faultstring()->get_value() if not ($result);
if ($result) {
print $result->get_GetWeatherResult()->get_value() , "\n"; print $result->get_GetWeatherResult()->get_value() , "\n";
}
else {
print $result;
}
+39
View File
@@ -0,0 +1,39 @@
# Accessing the globalweather service at
# www.webservicex.net/GlobalWeather/GlobalWeather.asmx
#
# Note that the GlobalWeather web service returns a (quoted) XML structure -
# don't be surprised by the response's format.
#
# I have no connection to www.webservicex.net
# Use this script at your own risk.
#
# This script demonstrates the use of SOAP::WSDL in SOAP::Lite style.
use lib 'lib/';
use lib '../lib';
use SOAP::WSDL;
use File::Basename qw(dirname);
use File::Spec;
my $path = File::Spec->rel2abs( dirname __FILE__);
my $soap = SOAP::WSDL->new();
my $som = $soap->wsdl("file:///$path/wsdl/globalweather.xml")
->call('GetWeather', GetWeather => { CountryName => 'Germany', CityName => 'Munich' });
die $som->message() if $som->fault();
print $som->result();
# SOAP::Lite variant:
use SOAP::Lite;
my $soap = SOAP::Lite->new()->on_action( sub { join'/', @_ } )
->proxy("http://www.webservicex.net/globalweather.asmx");
my $som = $soap->call(
SOAP::Data->name('GetWeather')->attr({ xmlns => 'http://www.webserviceX.NET' }),
SOAP::Data->name('CountryName')->value('Germany'),
SOAP::Data->name('CityName')->value('Munich')
);
print $som->result();
+43
View File
@@ -0,0 +1,43 @@
# Accessing the globalweather service at
# www.webservicex.net/GlobalWeather/GlobalWeather.asmx
#
# Note that the GlobalWeather web service returns a (quoted) XML structure -
# don't be surprised by the response's format.
#
# I have no connection to www.webservicex.net
# Use this script at your own risk.
#
# This script demonstrates the use of SOAP::WSDL in SOAP::Lite style.
=for later
use lib 'lib/';
use lib '../lib';
use SOAP::WSDL;
use File::Basename qw(dirname);
use File::Spec;
my $path = File::Spec->rel2abs( dirname __FILE__);
my $soap = SOAP::WSDL->new();
my $som = $soap->wsdl("file:///$path/wsdl/globalweather.xml")->no_dispatch(1)
->call('GetWeather', GetWeather => { CountryName => 'Germany', CityName => 'Munich' });
print $som;
=for later use
die $som->message() if $som->fault();
print $som->result();
=cut
use Carp;
use diagnostics;
use XML::Compile::WSDL;
my $schema = XML::Compile::WSDL->new('wsdl/globalweather.xml',
schema_dirs => 'D:/Test/XMLC/'
);
my $operation = $schema->prepare('GetWeather', role => 'CLIENT', port => 'GlobalWeatherSoap');
use Data::Dumper;
print Dumper $operation;
+335 -331
View File
@@ -1,181 +1,185 @@
package SOAP::WSDL; package SOAP::WSDL;
use strict; use strict;
use warnings; use warnings;
use vars qw/$AUTOLOAD/; use vars qw($AUTOLOAD);
use Carp;
use Scalar::Util qw(blessed); use Scalar::Util qw(blessed);
use SOAP::WSDL::Client;
use SOAP::WSDL::Envelope; use SOAP::WSDL::Envelope;
use SOAP::WSDL::SAX::WSDLHandler; use SOAP::WSDL::SAX::WSDLHandler;
use base qw(SOAP::Lite); use Class::Std;
use Data::Dumper;
our $VERSION='2.00_05';
BEGIN {
eval {
use XML::LibXML; use XML::LibXML;
use LWP::UserAgent;
our $VERSION='2.00_10';
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>);
my %outputtree_of :ATTR(:name<outputtree>);
my %outputhash_of :ATTR(:name<outputhash>);
my %servicename_of :ATTR(:name<servicename>);
my %portname_of :ATTR(:name<portname>);
my %class_resolver_of :ATTR(:name<class_resolver>);
my %method_info_of :ATTR(:default<()>);
my %port_of :ATTR(:default<()>);
my %porttype_of :ATTR(:default<()>);
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 %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,
);
for my $method (keys %LOOKUP ) {
no strict qw(refs);
*{ $method } = sub {
my $self = shift;
my $ident = ident $self;
if (@_) {
$LOOKUP{ $method }->{ $ident } = shift;
return $self;
}
return $LOOKUP{ $method }->{ $ident };
}; };
if ($@) {
use XML::SAX::ParserFactory;
}
} }
sub AUTOLOAD { {
my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); # we need to roll our own for supporting
die "$method not found"; # SOAP::WSDL->new( key => value ) syntax,
} # like SOAP::Lite does
no warnings qw(redefine);
sub new {
my $class = shift;
my %args_from = @_;
my $self = \do { my $foo = undef };
bless $self, $class;
sub outputtree { for (keys %args_from) {
my $self = shift; my $method = $self->can("set_$_")
return $self->{ _WSDL }->{ outputtree } if not @_; or croak "unknown parameter $_ passed to new";
return $self->{ _WSDL }->{ outputtree } = shift; $method->($self, $args_from{$_});
} }
my $ident = ident $self;
$self->wsdlinit() if ($wsdl_of{ $ident });
sub class_resolver { $client_of{ $ident } = SOAP::WSDL::Client->new();
my $self = shift;
return $self->{ _WSDL }->{ class_resolver } if not @_; return $self;
return $self->{ _WSDL }->{ class_resolver } = shift; }
} }
sub wsdlinit { sub wsdlinit {
my $self = shift; my $self = shift;
my $ident = ident $self;
my %opt = @_; my %opt = @_;
my $wsdl_xml = SOAP::Schema->new( schema_url => $self->wsdl() )->access( my $lwp = LWP::UserAgent->new();
$self->wsdl() my $response = $lwp->get( $wsdl_of{ $ident } );
); croak $response->message() if ($response->code != 200);
my $filter; # TODO: Port parser to expat and remove XML::LibXML dependency
my $parser = eval { XML::LibXML->new() }; my $parser = XML::LibXML->new();
if ($parser) { my $filter = SOAP::WSDL::SAX::WSDLHandler->new();
$filter = SOAP::WSDL::SAX::WSDLHandler->new();
$parser->set_handler( $filter ); $parser->set_handler( $filter );
} $parser->parse_string( $response->content() );
else {
$filter = SOAP::WSDL::SAX::WSDLHandler->new( base => 'XML::SAX::Base' );
$parser = XML::SAX::ParserFactory->parser( Handler => $filter );
}
$parser->parse_string( $wsdl_xml );
my $wsdl_definitions = $filter->get_data()
or die "unable to parse WSDL";
# sanity checks
my $wsdl_definitions = $filter->get_data() or die "unable to parse WSDL";
my $types = $wsdl_definitions->first_types() my $types = $wsdl_definitions->first_types()
or die "unable to extract schema from WSDL"; or die "unable to extract schema from WSDL";
my $ns = $wsdl_definitions->get_xmlns() my $ns = $wsdl_definitions->get_xmlns()
or die "unable to extract XML Namespaces" . $wsdl_definitions->to_string; or die "unable to extract XML Namespaces" . $wsdl_definitions->to_string;
( %{ $ns } ) or die "unable to extract XML Namespaces"; ( %{ $ns } ) or die "unable to extract XML Namespaces";
# setup lookup variables # setup lookup variables
$self->{ _WSDL }->{ wsdl_definitions } = $wsdl_definitions; $definitions_of{ $ident } = $wsdl_definitions;
$self->{ _WSDL }->{ serialize_options } = { $serialize_options_of{ $ident } = {
autotype => 0, autotype => 0,
readable => $self->readable(),
typelib => $types, typelib => $types,
namespace => $ns, namespace => $ns,
}; };
$self->{ _WSDL }->{ explain_options } = { $explain_options_of{ $ident } = {
readable => $self->readable(), readable => $self->readable(),
wsdl => $wsdl_definitions, wsdl => $wsdl_definitions,
namespace => $ns, namespace => $ns,
typelib => $types, typelib => $types,
}; };
$self->servicename($opt{servicename}) if $opt{servicename}; $servicename_of{ $ident } = $opt{servicename} if $opt{servicename};
$self->portname($opt{portname}) if $opt{portname}; $portname_of{ $ident } = $opt{portname} if $opt{portname};
return $self; return $self;
} ## end sub wsdlinit } ## end sub wsdlinit
sub _wsdl_get_service { sub _wsdl_get_service :PRIVATE {
my $self = shift; my $ident = ident shift;
my $service; my $wsdl = $definitions_of{ $ident };
my $wsdl = $self->{ _WSDL }->{ wsdl_definitions }; return $service_of{ $ident } = $servicename_of{ $ident }
my $ns = $wsdl->get_targetNamespace(); ? $wsdl->find_service( $wsdl->get_targetNamespace() , $servicename_of{ $ident } )
if ( $self->{ _WSDL }->{ servicename } ) : $service_of{ $ident } = $wsdl->get_service()->[ 0 ];
{
$service =
$wsdl->find_service( $ns, $self->{ _WSDL }->{ servicename } );
}
else
{
$service = $wsdl->get_service()->[ 0 ];
warn "no servicename specified - using " . $service->get_name();
}
return $self->{ _WSDL }->{ service } = $service;
} ## end sub _wsdl_get_service } ## end sub _wsdl_get_service
sub _wsdl_get_port { sub _wsdl_get_port :PRIVATE {
my $self = shift; my $ident = ident shift;
my $service = $self->{ _WSDL }->{ service } my $wsdl = $definitions_of{ $ident };
|| $self->_wsdl_get_service();
my $wsdl = $self->{ _WSDL }->{ wsdl_definitions };
my $ns = $wsdl->get_targetNamespace(); my $ns = $wsdl->get_targetNamespace();
my $port; return $port_of{ $ident } = $portname_of{ $ident }
if ( $self->{ _WSDL }->{ portname } ) ? $service_of{ $ident }->get_port( $ns, $portname_of{ $ident } )
{ : $port_of{ $ident } = $service_of{ $ident }->get_port()->[ 0 ];
$port = $service->get_port( $ns, $self->{ _WSDL }->{ portname } );
} }
else
{
$port = $service->get_port()->[ 0 ];
}
$self->{ _WSDL }->{ port } = $port;
# preload portType sub _wsdl_get_binding :PRIVATE {
$self->_wsdl_get_portType();
# Auto-set proxy - required before issuing call()
$self->proxy( $port->get_location() );
return $port;
} ## end sub _wsdl_get_port
sub _wsdl_get_binding {
my $self = shift; my $self = shift;
my $wsdl = $self->{ _WSDL }->{ wsdl_definitions }; my $ident = ident $self;
my $ns = $wsdl->get_targetNamespace(); my $wsdl = $definitions_of{ $ident };
my $port = $self->{ _WSDL }->{ port } my $port = $port_of{ $ident } || $self->_wsdl_get_port();
|| $self->_wsdl_get_port(); $binding_of{ $ident } = $wsdl->find_binding( $wsdl->_expand( $port->get_binding() ) )
my ( $prefix, $localname ) = split /:/, $port->get_binding();
# TODO lookup $ns instead of just using
# the top element's targetns...
my $binding = $wsdl->find_binding( $ns, $localname )
or die "no binding found for ", $port->get_binding(); or die "no binding found for ", $port->get_binding();
return $self->{ _WSDL }->{ binding } = $binding; return $binding_of{ $ident };
} ## end sub _wsdl_get_binding }
sub _wsdl_get_portType { sub _wsdl_get_portType :PRIVATE {
my $self = shift; my $self = shift;
my $wsdl = $self->{ _WSDL }->{ wsdl_definitions }; my $ident = ident $self;
my $binding = $self->{ _WSDL }->{ binding } my $wsdl = $definitions_of{ $ident };
|| $self->_wsdl_get_binding(); my $binding = $binding_of{ $ident } || $self->_wsdl_get_binding();
my $ns = $wsdl->get_targetNamespace(); $porttype_of{ $ident } = $wsdl->find_portType( $wsdl->_expand( $binding->get_type() ) )
my ( $prefix, $localname ) = split /:/, $binding->get_type(); or die "cannot find portType for " . $binding->get_type();
my $portType = $wsdl->find_portType( $ns, $localname ); return $porttype_of{ $ident };
$self->{ _WSDL }->{ portType } = $portType; }
return $portType;
} ## end sub _wsdl_get_portType
sub _wsdl_init_methods :PRIVATE {
sub _wsdl_init_methods {
my $self = shift; my $self = shift;
my $wsdl = $self->{ _WSDL }->{ wsdl_definitions }; my $ident = ident $self;
my $wsdl = $definitions_of{ $ident };
my $ns = $wsdl->get_targetNamespace(); my $ns = $wsdl->get_targetNamespace();
# get bindings, portType, message, part(s) # get bindings, portType, message, part(s) - use private methods for clear separation...
# - use cached values where possible for speed, $self->_wsdl_get_service if not ($service_of{ $ident });
# private methods if not for clear separation... my $binding = $binding_of{ $ident } || $self->_wsdl_get_binding()
my $binding = $self->{ _WSDL }->{ binding }
|| $self->_wsdl_get_binding()
|| die "Can't find binding"; || die "Can't find binding";
my $portType = $self->{ _WSDL }->{ portType } my $portType = $porttype_of{ $ident } || $self->_wsdl_get_portType();
|| $self->_wsdl_get_portType()
|| die "Can't find portType";
my $methodHashRef = {}; $method_info_of{ $ident } = {};
foreach my $binding_operation (@{ $binding->get_operation() }) foreach my $binding_operation (@{ $binding->get_operation() })
{ {
@@ -211,201 +215,59 @@ sub _wsdl_init_methods {
} }
: undef; : undef;
$methodHashRef->{ $binding_operation->get_name() } = $method; $method_info_of{ $ident }->{ $binding_operation->get_name() } = $method;
} }
$self->{ _WSDL }->{ methodInfo } = $methodHashRef; return $method_info_of{ $ident };
return $methodHashRef;
} }
sub call { sub call {
my $self = shift; my $self = shift;
my $ident = ident $self;
my $method = shift; my $method = shift;
my $data = ref $_[0] ? $_[0] : { @_ }; my $data = ref $_[0] ? $_[0] : { @_ };
my $content = q{}; $self->wsdlinit() if not ($definitions_of{ $ident });
my $envelope; $self->_wsdl_init_methods() if not ($method_info_of{ $ident });
my $methodInfo;
if (blessed $data my $client = $client_of{ $ident };
&& $data->isa('SOAP::WSDL::XSD::Typelib::Builtin::anyType')) $client->set_proxy( $proxy_of{ $ident } || $port_of{ $ident }->get_location() );
$client->set_no_dispatch( $no_dispatch_of{ $ident } );
$client->set_outputxml( $outputtree_of{ $ident } ? 0 : 1 );
my $response = (blessed $data)
? $client->call( $method, $data )
: do {
my $content = '';
# TODO support RPC-encoding: Top-Level element + namespace...
foreach my $part ( @{ $method_info_of{ $ident }->{ $method }->{ parts } } ) {
$client->set_on_action( sub { $part->get_targetNamespace() . '/' . $_[1] } );
$content .= $part->serialize( $method, $data,
{ {
$envelope = SOAP::WSDL::Envelope->serialize( $method, $data ); %{ $serialize_options_of{ $ident } },
readable => $readable_of{ $ident },
# TODO replace by something derived from binding - this is just a
# workaround...
$methodInfo->{ soap_action }
= join '/', $data->get_xmlns(), $method;
}
else {
my $methodLookup = $self->{ _WSDL }->{ methodInfo }
|| $self->_wsdl_init_methods();
$methodInfo = $methodLookup->{ $method };
my $partListRef = $methodInfo->{ parts };
# set serializer options
# TODO allow custom options here
my $opt = $self->{ _WSDL }->{ serialize_options };
# set response target namespace
# TODO make rpc-encoded encoding recognise this namespace
# $opt->{ targetNamespace } = $soap_binding_operation ?
# $operation->input()->namespace() : undef;
# serialize content
# TODO create surrounding element for rpc-encoded messages
foreach my $part ( @{ $partListRef } ) {
$content .= $part->serialize( $method, $data, $opt );
}
$envelope = SOAP::WSDL::Envelope->serialize( $method, $content , $opt );
};
if ( $self->no_dispatch() ) {
return $envelope;
} ## end if ( $self->no_dispatch...
# get response via transport layer
# TODO remove dependency from SOAP::Lite and use a
# SAX-based filter using XML::LibXML to get the
# result.
# Filter should have the following methods:
# - result: returns the result of the call (like SOAP::Lite, but as
# perl data structure)
# - header: returns the content of the SOAP header
# - fault: returns the result of the call if a SOAP fault is sent back
# by the server. Retuns undef (nothing) if the call has been
# processed without errors.
my $response = $self->transport->send_receive(
context => $self, # this is provided for context
endpoint => $self->endpoint(),
action => $methodInfo->{ soap_action }, # SOAPAction from binding
envelope => $envelope, # use custom content
);
return $response if ($self->outputxml() );
if ($self->outputtree()) {
my ($parser, $handler); # replace by globals - singleton is faster
if (not $parser) {
require SOAP::WSDL::SOAP::Typelib::Fault11;
require SOAP::WSDL::SAX::MessageHandler;
require XML::LibXML;
$handler = SOAP::WSDL::SAX::MessageHandler->new(
{ class_resolver => $self->class_resolver() },
);
$parser = XML::LibXML->new();
$parser->set_handler( $handler);
}
# if we had no success (Transport layer error status code)
# or if transport layer failed
if (! $self->transport->is_success() ) {
# Try deserializing response - there may be some
if ($response) {
eval { $parser->parse_string( $response ) };
return $handler->get_data if not $@;
};
# generate & return fault if we cannot serialize response
# or have none...
return SOAP::WSDL::SOAP::Typelib::Fault11->new({
faultcode => 'soap:Server',
faultactor => 'urn:localhost',
faultstring => 'Error sending / receiving message: '
. $self->transport->message()
} ); } );
} }
$client->call($method, $content);
};
eval { $parser->parse_string( $response ) }; return $response if (
$outputxml_of{ $ident }
# return fault if we cannot deserialize response # || $outputhash_of{ $ident }
if ($@) { || $outputtree_of{ $ident }
return SOAP::WSDL::SOAP::Typelib::Fault11->new({ || $no_dispatch_of{ $ident } );
faultcode => 'soap:Server',
faultactor => 'urn:localhost',
faultstring => "Error deserializing message: $@. \n"
. "Message was: \n$response"
});
}
return $handler->get_data();
}
# deserialize and store result
my $result = $self->{ '_call' } =
eval { $self->deserializer->deserialize( $response ) }
if $response;
if (
!$self->transport->is_success || # transport fault
$@ || # not deserializible
# fault message even if transport OK
# or no transport error (for example, fo TCP, POP3, IO implementations)
UNIVERSAL::isa( $result => 'SOAP::SOM' ) && $result->fault
) {
return $self->{ '_call' } = (
$self->on_fault->( $self, ($@)
? $@ . ( $response || '' )
: $result
) || $result
);
} ## end if ( !$self->transport...
return unless $response; # nothing to do for one-ways return unless $response; # nothing to do for one-ways
return $result; # now convert into SOAP::SOM - bah !
} ## end sub call require SOAP::Lite;
return SOAP::Deserializer->new()->deserialize( $response );
}
sub explain { sub explain {
my $self = shift; my $ident = ident shift;
my $opt = $self->{ _WSDL }->{ explain_options }; my $opt = $explain_options_of{ $ident };
return $definitions_of{ $ident }->explain( $opt );
return $self->{ _WSDL }->{ wsdl_definitions }->explain( $opt ); }
} ## end sub explain
sub _load_method {
my $method = shift;
no strict "refs";
*$method = sub {
my $self = shift;
return ( @_ ) ? $self->{ _WSDL }->{ $method } = shift
: $self->{ _WSDL }->{ $method }
};
} ## end sub _load_method
&_load_method( 'no_dispatch' );
&_load_method( 'wsdl' );
sub servicename {
my $self = shift;
return $self->{ _WSDL }->{ servicename } if ( not @_ );
$self->{ _WSDL }->{ servicename } = shift;
my $ns = $self->{ _WSDL }->{ wsdl_definitions }->get_targetNamespace();
$self->{ _WSDL }->{ service } =
$self->{ _WSDL }->{ wsdl_definitions }
->find_service( $ns, $self->{ _WSDL }->{ servicename } )
or die "No such service: " . $self->{ _WSDL }->{ servicename };
return $self;
} ## end sub servicename
sub portname {
my $self = shift;
return $self->{ _WSDL }->{ portname } if ( not @_ );
$self->{ _WSDL }->{ portname } = shift;
my $ns = $self->{ _WSDL }->{ wsdl_definitions }->get_targetNamespace();
$self->{ _WSDL }->{ port } =
$self->{ _WSDL }->{ service }
->find_port( $ns, $self->{ _WSDL }->{ portname } )
or die "No such port: " . $self->{ _WSDL }->{ portname };
return $self;
} ## end sub portname
1; 1;
@@ -417,12 +279,20 @@ __END__
SOAP::WSDL - SOAP with WSDL support SOAP::WSDL - SOAP with WSDL support
=head1 Overview
For creating Perl classes instrumenting a web service with a WSDL definition,
read L<SOAP::WSDL::Manual>.
For using an interpreting (thus slow and somewhat troublesome) WSDL based
SOAP client, which mimics L<SOAP::Lite|SOAP::Lite>'s API, read on.
=head1 SYNOPSIS =head1 SYNOPSIS
my $soap = SOAP::WSDL->new( my $soap = SOAP::WSDL->new(
wsdl => 'file://bla.wsdl', wsdl => 'file://bla.wsdl',
readable => 1, readable => 1,
)->wsdlinit(); );
my $result = $soap->call('MyMethod', %data); my $result = $soap->call('MyMethod', %data);
@@ -432,16 +302,29 @@ SOAP::WSDL provides easy access to Web Services with WSDL descriptions.
The WSDL is parsed and stored in memory. The WSDL is parsed and stored in memory.
Your data is serialized according to the rules in the WSDL and sent via Your data is serialized according to the rules in the WSDL.
SOAP::Lite's transport mechanism.
The only transport mechanisms currently supported are http and https.
=head1 METHODS =head1 METHODS
=head2 new
Constructor. All parameters passed are passed to the corresponding methods.
=head2 call
Performs a SOAP call. The result is either an object tree (with outputtree),
a hash reference (with outputhash), plain XML (with outputxml) or a SOAP::SOM
object (with neither of the above set).
my $result = $soap->call('method', %data);
=head2 wsdlinit =head2 wsdlinit
Reads the WSDL file and initializes SOAP::WSDL for working with it. Reads the WSDL file and initializes SOAP::WSDL for working with it.
Must be called after the wsdl URL has been set, and before calling one of Is called automatically from call() if not called directly before.
servicename servicename
portname portname
@@ -455,14 +338,6 @@ wsdlinit:
portname => 'MyPort' portname => 'MyPort'
); );
=head2 call
Performs a SOAP call. The result is either an object tree (with outputtree),
a hash reference (with outputhash), plain XML (with outputxml) or a SOAP::SOM
object (with neither of the above set).
my $result = $soap->call('method', %data);
=head1 CONFIGURATION METHODS =head1 CONFIGURATION METHODS
=head2 outputtree =head2 outputtree
@@ -515,8 +390,6 @@ SOAP::WSDL::XSD::ComplexType on how to build / generate one.
Sets the service to operate on. If no service is set via servicename, the Sets the service to operate on. If no service is set via servicename, the
first service found is used. first service found is used.
Must be called after calling wsdlinit().
Returns the soap object, so you can chain calls like Returns the soap object, so you can chain calls like
$soap->servicename->('Name')->portname('Port'); $soap->servicename->('Name')->portname('Port');
@@ -528,8 +401,6 @@ Returns the soap object, so you can chain calls like
Sets the port to operate on. If no port is set via portname, the Sets the port to operate on. If no port is set via portname, the
first port found is used. first port found is used.
Must be called after calling wsdlinit().
Returns the soap object, so you can chain calls like Returns the soap object, so you can chain calls like
$soap->portname('Port')->call('MyMethod', %data); $soap->portname('Port')->call('MyMethod', %data);
@@ -539,12 +410,25 @@ Returns the soap object, so you can chain calls like
When set, call() returns the plain request XML instead of dispatching the When set, call() returns the plain request XML instead of dispatching the
SOAP call to the SOAP service. Handy for testing/debugging. SOAP call to the SOAP service. Handy for testing/debugging.
=head2 _wsdl_init_methods =head1 ACCESS TO SOAP::WSDL's internals
Creates a lookup table containing the information required for all methods =head2 get_client / set_client
specified for the service/port selected.
The lookup table is used by L<call|call>. 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.
=head1 Differences to previous versions =head1 Differences to previous versions
@@ -560,7 +444,8 @@ it's content.
The object tree has two main functions: It knows how to serialize data passed The object tree has two main functions: It knows how to serialize data passed
as hash ref, and how to render the WSDL elements found into perl classes. as hash ref, and how to render the WSDL elements found into perl classes.
Yup your're right, there's a builting code generation facility. Yup your're right, there's a builting code generation facility. Read
L<SOAP::WSDL::Manual> for using it.
=item * no_dispatch =item * no_dispatch
@@ -582,32 +467,91 @@ You may pass the servicename and portname as attributes to wsdlinit, though.
=head1 Differences to SOAP::Lite =head1 Differences to SOAP::Lite
=head2 Auto-Dispatching =head2 Message style/encoding
While SOAP::Lite supports rpc/encoded style/encoding only, SOAP::WSDL currently
supports document/literal style/encoding.
=head2 autotype / type information
SOAP::Lite defaults to transmitting XML type information by default, where
SOAP::WSDL defaults to leaving it out.
autotype(1) might even be broken in SOAP::WSDL - it's not well-tested, yet.
=head2 Output formats
In contrast to SOAP::Lite, SOAP::WSDL supports the following output formats:
=over
=item * SOAP::SOM objects.
This is the default. SOAP::Lite is required for outputting SOAP::SOM objects.
=item * Object trees.
This is the recommended output format.
You need a class resolver (typemap) for outputting object trees.
See L<class_resolver|class_resolver> above.
=item * Hash refs
This is for convnience: A single hash ref containing the content of the
SOAP body.
=item * xml
See below.
=back
=head2 outputxml
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
SOAP::WSDL does B<does not> support auto-dispatching. SOAP::WSDL does B<does not> support auto-dispatching.
This is on purpose: You may easily create interface classes by using This is on purpose: You may easily create interface classes by using
SOAP::WSDL and implementing something like SOAP::WSDL::Client and implementing something like
sub mySoapMethod { sub mySoapMethod {
my $self = shift; my $self = shift;
$soap_wsdl_client->call( mySoapMethod, @_); $soap_wsdl_client->call( mySoapMethod, @_);
} }
You may even do this in a class factory - SOAP::WSDL provides the methods You may even do this in a class factory - see L<wsdl2perl.pl> for creating
for generating such interfaces. such interfaces.
SOAP::Lite's autodispatching mechanism is - though convenient - a constant =head3 Debugging / Tracing
source of errors: Every typo in a method name gets caught by AUTOLOAD and
may lead to unpredictable results. While SOAP::Lite features a global tracing facility, SOAP::WSDL
allows to switch tracing on/of on a per-object base.
This has to be done in the SOAP client used by SOAP::WSDL - see
L<get_client|get_client> for an example and L<SOAP::WSDL::Client> for
details.
=head1 Bugs and Limitations =head1 Bugs and Limitations
=over =over
=item * readable =item * SOAP Headers are not supported
readable() must be called before calling wsdlinit. This is a bug. 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
outputhash is not implemented yet.
=item * Unsupported XML Schema definitions =item * Unsupported XML Schema definitions
@@ -619,7 +563,7 @@ The following XML Schema definitions are not supported:
simpleContent simpleContent
complexContent complexContent
=item * Serialization of hash refs dos not work for ambiguous values =item * Serialization of hash refs dos not work for ambiguos values
If you have list elements with multiple occurences allowed, SOAP::WSDL If you have list elements with multiple occurences allowed, SOAP::WSDL
has no means of finding out which variant you meant. has no means of finding out which variant you meant.
@@ -629,11 +573,11 @@ Passing in item => [1,2,3] could serialize to
<item>1 2</item><item>3</item> <item>1 2</item><item>3</item>
<item>1</item><item>2 3</item> <item>1</item><item>2 3</item>
Ambiguos data can be avoided by passing an object tree as data. Ambiguos data can be avoided by providing data as objects.
=item * XML Schema facets =item * XML Schema facets
Almost all XML schema facets are not yet implemented. The only facets Almost no XML schema facets are implemented yet. The only facets
currently implemented are: currently implemented are:
fixed fixed
@@ -652,6 +596,59 @@ The following facets have no influence yet:
=back =back
=head1 SEE ALSO
=head2 Related projects
=over
=item * L<SOAP::Lite|SOAP::Lite>
Full featured SOAP-library, little WSDL support. Supports rpc-encoded style only. Many protocols supported.
=item * <XML::Compile::WSDL|XML::Compile::WSDL>
A promising-looking approach derived from a cool functional DOM-based XML schema parser.
Will support encoding/decoding of SOAP messages based on WSDL definitions.
Not yet finished at the time of writing - but you may wish to give it a try, especially
if you need to adhere very closely to the XML Schema / WSDL specs.
=back
=head2 Sources of documentation
=over
=item * SOAP::WSDL homepage at sourceforge.net
L<http://soap-wsdl.sourceforge.net>
=item * SOAP::WSDL forum at CPAN::Forum
L<http://www.cpanforum.com/dist/SOAP-WSDL>
=back
=head1 ACKNOWLEDGMENTS
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)
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.
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.
=head1 LICENSE =head1 LICENSE
Copyright 2004-2007 Martin Kutter. Copyright 2004-2007 Martin Kutter.
@@ -663,5 +660,12 @@ the same terms as perl itself
Martin Kutter E<lt>martin.kutter fen-net.deE<gt> Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 176 $
$LastChangedBy: kutterma $
$Id: WSDL.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.pm $
=cut =cut
+5 -1
View File
@@ -7,6 +7,7 @@ use List::Util qw(first);
my %id_of :ATTR(:name<id> :default<()>); my %id_of :ATTR(:name<id> :default<()>);
my %name_of :ATTR(:name<name> :default<()>); my %name_of :ATTR(:name<name> :default<()>);
my %documentation_of :ATTR(:name<documentation> :default<()>);
my %targetNamespace_of :ATTR(:name<targetNamespace> :default<()>); my %targetNamespace_of :ATTR(:name<targetNamespace> :default<()>);
my %xmlns_of :ATTR(:name<xmlns> :default<{}>); my %xmlns_of :ATTR(:name<xmlns> :default<{}>);
my %parent_of :ATTR(:name<parent> :default<()>); my %parent_of :ATTR(:name<parent> :default<()>);
@@ -77,12 +78,15 @@ sub init {
my @args = @_; my @args = @_;
foreach my $value (@args) foreach my $value (@args)
{ {
die $value if (not defined ($value->{ Name })); die @args if (not defined ($value->{ Name }));
if ($value->{ Name } =~m{^xmlns\:}xms) { if ($value->{ Name } =~m{^xmlns\:}xms) {
die $xmlns_of{ ident $self } die $xmlns_of{ ident $self }
if ref $xmlns_of{ ident $self } ne 'HASH'; if ref $xmlns_of{ ident $self } ne 'HASH';
# add namespaces
$xmlns_of{ ident $self }->{ $value->{ Value } } = $xmlns_of{ ident $self }->{ $value->{ Value } } =
$value->{ LocalName }; $value->{ LocalName };
next; next;
} }
elsif ($value->{ Name } =~m{^xmlns$}xms) { elsif ($value->{ Name } =~m{^xmlns$}xms) {
+238 -53
View File
@@ -2,26 +2,97 @@ package SOAP::WSDL::Client;
use strict; use strict;
use warnings; use warnings;
use Carp; use Carp;
use Scalar::Util qw(blessed);
use SOAP::WSDL::Envelope;
use SOAP::Lite;
use Class::Std::Storable; use Class::Std::Storable;
use LWP::UserAgent;
use HTTP::Request;
use Scalar::Util qw(blessed);
use SOAP::WSDL::Factory::Serializer;
use SOAP::WSDL::Factory::Transport;
use SOAP::WSDL::Expat::MessageParser; use SOAP::WSDL::Expat::MessageParser;
use SOAP::WSDL::SOAP::Typelib::Fault11; use SOAP::WSDL::SOAP::Typelib::Fault11;
# Package globals for speed... # Package global for speed and memory savings.
# But should be factored out into serializer/deserializer...
my $PARSER; my $PARSER;
my $MESSAGE_HANDLER;
my %class_resolver_of :ATTR(:name<class_resolver> :default<()>); my %class_resolver_of :ATTR(:name<class_resolver> :default<()>);
my %no_dispatch_of :ATTR(:name<no_dispatch> :default<()>); my %no_dispatch_of :ATTR(:name<no_dispatch> :default<()>);
my %outputxml_of :ATTR(:name<outputxml> :default<()>); my %outputxml_of :ATTR(:name<outputxml> :default<()>);
my %proxy_of :ATTR(:name<proxy> :default<()>); my %transport_of :ATTR(:name<transport> :default<()>);
my %endpoint_of :ATTR(:name<endpoint> :default<()>);
my %soap_version_of :ATTR(:get<soap_version> :init_attr<soap_version> :default<'1.1'>);
my %fault_class_of :ATTR(:name<fault_class> :default<SOAP::WSDL::SOAP::Typelib::Fault11>);
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<()>);
# TODO remove when preparing 2.01 # TODO remove when preparing 2.01
sub outputtree { warn 'outputtree is deprecated and' sub outputtree { warn 'outputtree is deprecated and'
. 'will be removed before reaching v2.01 !' } . 'will be removed before reaching v2.01 !' }
sub BUILD {
my ($self, $ident, $attrs_of_ref) = @_;
if (exists $attrs_of_ref->{ proxy }) {
$self->set_proxy( $attrs_of_ref->{ proxy } );
delete $attrs_of_ref->{ proxy };
}
}
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();
}
sub set_proxy {
my ($self, @args_from) = @_;
my $ident = ident $self;
# remember old value to return it later - Class::Std does so, too
my $old_value = $transport_of{ $ident };
# accept both list and list ref args
@args_from = @{ $args_from[0] } if ref $args_from[0];
# remember endpoint
$endpoint_of{ $ident } = $args_from[0];
# set transport - SOAP::Lite works similar...
$transport_of{ $ident } = SOAP::WSDL::Factory::Transport
->get_transport( @args_from );
return $old_value;
}
sub set_soap_version {
my $ident = ident shift;
# remember old value to return it later - Class::Std does so, too
my $soap_version = $soap_version_of{ $ident };
# re-setting the soap version invalidates the
# serializer object
delete $serializer_of{ $ident };
$soap_version_of{ $ident } = shift;
return $soap_version;
}
# Mimic SOAP::Lite's behaviour for getter/setter routines
SUBFACTORY: { SUBFACTORY: {
no strict qw(refs); no strict qw(refs);
for (qw(class_resolver no_dispatch outputxml proxy)) { for (qw(class_resolver no_dispatch outputxml proxy)) {
@@ -44,82 +115,101 @@ BEGIN {
sub call { sub call {
my $self = shift; my $self = shift;
my $method = shift; my $method = shift;
my $data = ref $_[0] ? $_[0] : { @_ }; my $ident = ident $self;
my $content = q{}; my $data = ref $_[0]
my ($envelope, $soap_action); ? $_[0]
: (@_>1)
? { @_ }
: $_[0];
my $header = {};
if (blessed $data my ($soap_action, $operation);
&& $data->isa('SOAP::WSDL::XSD::Typelib::Builtin::anyType')) my $trace_sub = $self->get_trace();
{
$envelope = SOAP::WSDL::Envelope->serialize( $method, $data ); if (ref $method eq 'HASH') {
# TODO replace by something derived from binding - this is just a $soap_action = $method->{ soap_action };
# workaround... $operation = $method->{ operation }
$soap_action = join '/', $data->get_xmlns(), $method;
} }
else { else {
$envelope = SOAP::WSDL::Envelope->serialize( $method, $data ); $operation = $method;
# $soap_action = $self->on_action( $method );
} }
$serializer_of{ $ident } ||= SOAP::WSDL::Factory::Serializer->get_serializer({
soap_version => $self->get_soap_version(),
});
my $envelope = $serializer_of{ $ident }->serialize({
method => $operation,
body => $data,
header => $header,
});
return $envelope if $self->no_dispatch(); return $envelope if $self->no_dispatch();
# warn $envelope; # try to guess soap_action if not given
if (not defined $soap_action) {
$soap_action = (blessed $data
&& $data->isa('SOAP::WSDL::XSD::Typelib::Builtin::anyType'))
? $soap_action = join '/', $data->get_xmlns(), $operation
: ($on_action_of{$ident})
? $soap_action = $on_action_of{$ident}->( $self, $operation )
: "";
}
# get response via transport layer # always quote SOAPAction header.
# TODO remove dependency from SOAP::Lite and use a # WS-I BP 1.0 R1109
# SAX-based filter using XML::LibXML to get the $soap_action =~s{\A(:?"|')?}{"}xms;
# result. $soap_action =~s{(:?"|')?\Z}{"}xms;
# Filter should have the following methods:
# - result: returns the result of the call (like SOAP::Lite, but as # get response via transport layer.
# perl data structure) # Normally, SOAP::Lite's transport layer is used, though users
# - header: returns the content of the SOAP header # may provide their own.
# - fault: returns the result of the call if a SOAP fault is sent back my $transport = $self->get_transport();
# by the server. Retuns undef (nothing) if the call has been my $response = $transport->send_receive(
# processed without errors. endpoint => $self->get_endpoint(),
my $soap = SOAP::Lite->new()->proxy( $self->get_proxy() ); content_type => $content_type_of{ $ident },
my $response = $soap->transport->send_receive( envelope => $envelope,
context => $self, # this is provided for context action => $soap_action,
endpoint => $soap->endpoint(), on_receive_chunk => sub {} # optional, may be used for parsing large responses as they arrive.
action => $soap_action, # SOAPAction, should be from binding # might not be supported by all transport layers...
envelope => $envelope, # use custom content # and, of course, only is of interest for chunk parsers -
# namely ExpatNB and XML::LibXML's Push parser interface...
); );
# warn 'Received ' . length($response) . ' bytes of content';
return $response if ($self->outputxml() ); return $response if ($self->outputxml() );
$PARSER->class_resolver( $self->get_class_resolver() ); $PARSER->class_resolver( $self->get_class_resolver() );
# if we had no success (Transport layer error status code) # if we had no success (Transport layer error status code)
# or if transport layer failed # or if transport layer failed
if (! $soap->transport->is_success() ) { if ( ! $transport->is_success() ) {
# Try deserializing response - there may be some # Try deserializing response - there may be some
if ( $response ) { if ( $response ) {
eval { $PARSER->parse( $response ); }; eval { $PARSER->parse( $response ); };
if ($@) { return $PARSER->get_data() if (not $@);
warn "could not deserialize response: $@"; return $fault_class_of{$ident}->new({
} faultcode => 'soap:Server',
else { faultactor => 'urn:localhost',
return $PARSER->get_data(); faultstring => "Error deserializing message: $@. \n"
} . "Message was: \n$response"
});
}; };
require SOAP::WSDL::SOAP::Typelib::Fault11;
# generate & return fault if we cannot serialize response # generate & return fault if we cannot serialize response
# or have none... # or have none...
return SOAP::WSDL::SOAP::Typelib::Fault11->new({ return $fault_class_of{$ident}->new({
faultcode => 'soap:Server', faultcode => 'soap:Server',
faultactor => 'urn:localhost', faultactor => 'urn:localhost',
faultstring => 'Error sending / receiving message: ' faultstring => 'Error sending / receiving message: '
. $soap->transport->message() . $transport->message()
}); });
} }
eval { $PARSER->parse( $response ) }; eval { $PARSER->parse( $response ) };
# return fault if we cannot deserialize response # return fault if we cannot deserialize response
if ($@) { if ($@) {
return SOAP::WSDL::SOAP::Typelib::Fault11->new({ return $fault_class_of{$ident}->new({
faultcode => 'soap:Server', faultcode => 'soap:Server',
faultactor => 'urn:localhost', faultactor => 'urn:localhost',
faultstring => "Error deserializing message: $@. \n" faultstring => "Error deserializing message: $@. \n"
@@ -134,6 +224,77 @@ sub call {
=pod =pod
=head1 NAME
SOAP::WSDL::Client - SOAP::WSDL's SOAP Client
=head1 METHODS
=head2 call
$soap->call( \%method, \@parts );
%method is a hash with the following keys:
Name Description
----------------------------------------------------
operation operation name
soap_action SOAPAction HTTP header to use
style Operation style. One of (document|rpc)
use SOAP body encoding. One of (literal|encoded)
The style and use keys have no influence yet.
@parts is a list containing the elements of the message parts.
For backward compatibility, call may also be called as below:
$soap->call( $method, \@parts );
In this case, $method is the SOAP operation name, and the SOAPAction header
is guessed from the first part's namespace and the operation name (which is
mostly correct, but may fail). Operation style and body encoding are assumed to
be document/literal
=head2 Configuration methods
=head3 outputxml
$soap->outputxml(1);
When set, call() returns the raw XML of the SOAP Envelope.
=head3 set_content_type
$soap->set_content_type('application/xml; charset: utf8');
Sets the content type and character encoding.
You probably should not use a character encoding different from utf8:
SOAP::WSDL::Client will not convert the request into a different encoding
(yet).
To leave out the encoding, just set the content type without appendet charset
like in
text/xml
Default:
text/xml; charset: utf8
=head3 set_trace
$soap->set_trace(1);
$soap->set_trace( sub { Log::Log4perl::get_logger()->debug( @_ ) } );
When set to a true value, tracing (via warn) is enabled.
When set to a code reference, this function will be called on every
trace call, making it really easy for you to set up log4perl logging
or whatever you need.
=head2 Features different from SOAP::Lite =head2 Features different from SOAP::Lite
SOAP::WSDL does not aim to be a complete replacement for SOAP::Lite - the SOAP::WSDL does not aim to be a complete replacement for SOAP::Lite - the
@@ -145,7 +306,7 @@ Nonetheless SOAP::WSDL mimics part of SOAP::Lite's API and behaviour,
so SOAP::Lite users can switch without looking up every method call in the so SOAP::Lite users can switch without looking up every method call in the
documentation. documentation.
A few things are quite differentl from SOAP::Lite, though: A few things are quite different from SOAP::Lite, though:
=head3 SOAP request data =head3 SOAP request data
@@ -197,9 +358,33 @@ SOAP::WSDL::Client and implementing something like
$soap_wsdl_client->call( mySoapMethod, @_); $soap_wsdl_client->call( mySoapMethod, @_);
} }
You may even do this in a class factory - SOAP::WSDL provides the methods You may even do this in a class factory - see L<wsdl2perl.pl> for creating
for generating such interfaces. such interfaces.
=head3 Debugging / Tracing
While SOAP::Lite features a global tracing facility, SOAP::WSDL::Client
allows to switch tracing on/of on a per-object base.
See L<set_trace|set_trace> on how to enable tracing.
=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: Client.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/Client.pm $
=cut =cut
+48 -7
View File
@@ -21,23 +21,37 @@ sub __create_new {
} }
sub __create_methods { sub __create_methods {
my ($package, %parts_of) = @_; my ($package, %info_of) = @_;
no strict qw(refs); no strict qw(refs);
for my $method (keys %parts_of){ for my $method (keys %info_of){
my ($soap_action, @parts);
# up to 2.00_10 we had list refs...
if (ref $info_of{ $method }eq 'HASH') {
@parts = @{ $info_of{ $method }->{ parts } };
$soap_action = $info_of{ $method }->{ soap_action };
}
else {
@parts = @{ $info_of{ $method } };
$soap_action = ();
}
*{ "$package\::$method" } = sub { *{ "$package\::$method" } = sub {
my $self = shift; my $self = shift;
my @param = map { my @param = map {
my $data = shift || {}; my $data = shift || {};
eval "require $_"; eval "require $_";
$_->new( $data ); $_->new( $data );
} @{ $parts_of{ $method } }; } @parts;
$self->call( $method, @param ); return $self->SUPER::call( {
operation => $method,
soap_action => $soap_action,
}, @param );
} }
} }
} }
1; 1;
@@ -48,13 +62,40 @@ __END__
=head1 NAME =head1 NAME
SOAP::WSDL::Client::Base - Base client for WSDL-based SOAP access SOAP::WSDL::Client::Base - Factory class for WSDL-based SOAP access
=head1 SYNOPSIS =head1 SYNOPSIS
package MySoapClient; package MySoapInterface;
use SOAP::WSDL::Client::Base; use SOAP::WSDL::Client::Base;
__PACKAGE__->__create_new(
proxy => 'http://somewhere.over.the.rainbow',
class_resolver => 'Typemap::MySoapInterface'
);
__PACKAGE__->__create_methods( qw(one two three) ); __PACKAGE__->__create_methods( qw(one two three) );
1; 1;
=head1 DESCRIPTION
Factory class for creating interface classes. Should probably be renamed to
SOAP::WSDL::Factory::Interface...
=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: Base.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/Client/Base.pm $
=cut =cut
+107 -44
View File
@@ -1,4 +1,5 @@
package SOAP::WSDL::Definitions; package SOAP::WSDL::Definitions;
use utf8;
use strict; use strict;
use warnings; use warnings;
use Carp; use Carp;
@@ -49,8 +50,7 @@ sub explain {
my $txt = ''; my $txt = '';
for my $service (@{ $self->get_service() }) { for my $service (@{ $self->get_service() }) {
$txt .= $service->explain( $opt ); $txt .= $service->explain( $opt ) . "\n";
$txt .= "\n";
} }
return $txt; return $txt;
} }
@@ -102,48 +102,68 @@ sub _create_interface {
my $self = shift; my $self = shift;
my $opt = shift; my $opt = shift;
my $service_name = $opt->{ service }->get_name(); my $service_name = $opt->{ service }->get_name();
my $file_name = "$opt->{ base_path }/$opt->{ interface_prefix }/$service_name.pm"; $service_name =~s{\.}{\:\:}xmsg;
$file_name =~s{::}{/}gms; # TODO: iterate over ports.
my $path = dirname $file_name; # - ignore non-SOAP ports
my $name = basename $file_name; # - generate interface for all SOAP ports...
my $binding = $self->find_binding( $self->_expand( $opt->{ service }->first_port()->get_binding() ) ); my $binding = $self->find_binding( $self->_expand( $opt->{ service }->first_port()->get_binding() ) );
my $portType = $self->find_portType( $self->_expand( $binding->get_type() ) ); my $porttype = $self->find_portType( $self->_expand( $binding->get_type() ) );
my $portType_operation_from_ref = $portType->get_operation();
my $port_operation_ref = $porttype->get_operation();
my $operation_ref = $binding->get_operation(); my $operation_ref = $binding->get_operation();
$operation_ref = [ $operation_ref ] if ref $operation_ref ne 'ARRAY';
my %operations = map { # make up operations map - name => [ part types / elements class names ]
do { #
my $operation_name = $_->get_name(); my %operations = ();
my $port_op = first { $_->get_name eq $operation_name } @{ $portType_operation_from_ref }; for my $operation ( @{ $operation_ref } ) {
my $input = $port_op->first_input()->get_message(); my $operation_name = $operation->get_name();
my $message = $self->find_message( $self->_expand( $input ) ); my $soap_operation = $operation->first_operation();
my $parts = $message->get_part;
( $operation_name => [ $operations{ $operation_name }->{ style } = $soap_operation
map { ? $soap_operation->get_style()
do { : 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; my $name;
($name = $_->get_element()) if (my $element_name = $part->get_element() ) {
? do { $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; my ($prefix, $localname) = split m{:}xms , $name;
push @{ $operations{ $operation_name }->{$msg}->{ class } },
"$opt->{ element_prefix }$localname"; "$opt->{ element_prefix }$localname";
} }
: ($name = $_->get_type())
? do {
my ($prefix, $localname) = split m{:}xms , $name;
"$opt->{ type_prefix }$localname";
} }
: ()
} }
} @{ $parts }
] );
};
} @{ $operation_ref };
# use Data::Dumper;
# die Dumper \%operations;
my $template = <<'EOT'; my $template = <<'EOT';
package [% interface_prefix %][% service.get_name %]; package [% interface_prefix %][% service.get_name.replace('\.', '::') %];
use strict; use strict;
use warnings; use warnings;
use [% typemap_prefix %][% service.get_name %]; use [% typemap_prefix %][% service.get_name %];
@@ -153,7 +173,7 @@ sub new {
my $class = shift; my $class = shift;
my $arg_ref = shift || {}; my $arg_ref = shift || {};
my $self = $class->SUPER::new({ my $self = $class->SUPER::new({
class_resolver => '[% typemap_prefix %][% service.get_name %]', class_resolver => '[% typemap_prefix %][% service.get_name.replace('\.', '::') %]',
proxy => '[% service.first_port.get_location %]', proxy => '[% service.first_port.get_location %]',
%{ $arg_ref } %{ $arg_ref }
}); });
@@ -162,7 +182,12 @@ sub new {
__PACKAGE__->__create_methods( __PACKAGE__->__create_methods(
[% FOREACH name = operations.keys -%] [% FOREACH name = operations.keys -%]
[% name %] => [ [% FOREACH class = operations.$name %]'[% class %]', [% END %]], [% 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 %] [% END %]
); );
@@ -170,30 +195,55 @@ __PACKAGE__->__create_methods(
__END__ __END__
=pod [% MACRO pod BLOCK %]=pod[% END %]
[% MACRO cut BLOCK %]=pod[% END %]
[% MACRO head1 BLOCK %]=head1[% END %]
[% MACRO head2 BLOCK %]=head2[% END %]
[% pod %]
=head1 NAME [% head1 %] NAME
[% interface_prefix %][% service.get_name %] - SOAP interface to [% service.get_name %] at [% interface_prefix %][% service.get_name %] - SOAP interface to [% service.get_name %] at
[% service.first_port.get_location %] [% service.first_port.get_location %]
=head1 SYNOPSIS [% head1 %] SYNOPSIS
my $interface = [% interface_prefix %][% service.get_name %]->new(); my $interface = [% interface_prefix %][% service.get_name %]->new();
my $[% operations.keys.1 %] = $interface->[% operations.keys.1 %](); my $[% operations.keys.1 %] = $interface->[% operations.keys.1 %]();
[% service.explain({ wsdl => wsdl }) %] [% head1 %] METHODS
[% FOREACH name=operations.keys;
operation=operations.$name;
%]
[% head2 %] [% name %]
=cut [% operation.documentation %]
SYNOPSIS:
$service->[% name %]({
[% FOREACH type = operation.input.types; type; END %] });
[% END %]
[% cut %]
EOT EOT
require Template; 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( my $tt = Template->new(
OUTPUT_PATH => $path, OUTPUT_PATH => $path,
); );
$tt->process(\$template, { %{ $opt }, operations => \%operations, binding => $binding, wsdl => $self }, $name) $tt->process(\$template,
{ %{ $opt }, operations => \%operations, binding => $binding, wsdl => $self },
$name,
binmode => ':utf8'
)
or die $tt->error(); or die $tt->error();
return 1; return 1;
} }
@@ -204,6 +254,7 @@ sub _create_typemap {
my $self = shift; my $self = shift;
my $opt = shift; my $opt = shift;
my $service_name = $opt->{ service }->get_name(); my $service_name = $opt->{ service }->get_name();
$service_name =~s{\.}{\:\:}xmsg;
my $file_name = "$opt->{ base_path }/$opt->{ typemap_prefix }/$service_name.pm"; my $file_name = "$opt->{ base_path }/$opt->{ typemap_prefix }/$service_name.pm";
$file_name =~s{::}{/}gms; $file_name =~s{::}{/}gms;
my $path = dirname $file_name; my $path = dirname $file_name;
@@ -212,11 +263,19 @@ sub _create_typemap {
my $typemap = $opt->{ service }->to_typemap( { %{ $opt }, wsdl => $self } ); my $typemap = $opt->{ service }->to_typemap( { %{ $opt }, wsdl => $self } );
my $template = <<'EOT'; my $template = <<'EOT';
package [% typemap_prefix %][% service.get_name %]; package [% typemap_prefix %][% service.get_name.replace('\.', '::') %];
use strict; use strict;
use warnings; use warnings;
my %typemap = ( 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 %] [% typemap %]
[% custom_types %] [% custom_types %]
); );
@@ -237,7 +296,11 @@ EOT
my $tt = Template->new( my $tt = Template->new(
OUTPUT_PATH => $path, OUTPUT_PATH => $path,
); );
$tt->process(\$template, { %{ $opt }, typemap => $typemap }, $name) $tt->process(\$template,
{ %{ $opt }, typemap => $typemap },
$name,
binmode => ':utf8',
)
or die $tt->error(); or die $tt->error();
} }
+95 -80
View File
@@ -5,27 +5,8 @@ use warnings;
use SOAP::WSDL::XSD::Typelib::Builtin; use SOAP::WSDL::XSD::Typelib::Builtin;
use XML::Parser::Expat; use XML::Parser::Expat;
=pod
=head2 new
=over
=item SYNOPSIS
my $obj = ->new();
=item DESCRIPTION
Constructor.
=back
=cut
sub new { sub new {
my $class = shift; my ($class, $args) = @_;
my $args = shift;
my $self = { my $self = {
class_resolver => $args->{ class_resolver } class_resolver => $args->{ class_resolver }
}; };
@@ -38,113 +19,140 @@ sub class_resolver {
$self->{ class_resolver } = shift; $self->{ class_resolver } = shift;
} }
sub parse { sub _initialize {
my $self = shift; my ($self, $parser) = @_;
my $xml = shift;
$self->{ data } = undef; delete $self->{ data };
my $characters; my $characters;
my $current = '__STOP__'; my $current = undef;
my $ignore = [ 'Envelope', 'Body' ]; my $ignore = [ 'Envelope', 'Body' ]; # top level elements to ignore
my $list = []; my $list = []; # node list
my $namespace = {}; my $path = []; # current path
my $path = []; my $skip = 0; # skip elements
my $parser = XML::Parser::Expat->new();
# use "globals" for speed
my ($_prefix, $_localname, $_element, $_method,
$_class, $_parser, %_attrs) = ();
no strict qw(refs); no strict qw(refs);
$parser->setHandlers( $parser->setHandlers(
Start => sub { Start => sub {
my ($parser, $element, %attrs) = @_; ($_parser, $_element, %_attrs) = @_;
my ($prefix, $localname) = split m{:}xms , $element; ($_prefix, $_localname) = split m{:}xms , $_element;
# for non-prefixed elements
if (not $localname) { $_localname ||= $_element; # for non-prefixed elements
$localname = $element;
$prefix = q{};
}
# ignore top level elements # ignore top level elements
if (@{ $ignore } && $localname eq $ignore->[0]) { if (@{ $ignore } && $_localname eq $ignore->[0]) {
shift @{ $ignore }; shift @{ $ignore };
return; return;
} }
# empty characters
$characters = q{};
push @{ $path }, $localname; # step down... push @{ $path }, $_localname; # step down in path
push @{ $list }, $current; # remember current return if $skip; # skip inside __SKIP__
# resolve class of this element # resolve class of this element
my $class = $self->{ class_resolver }->get_class( $path ) $_class = $self->{ class_resolver }->get_class( $path )
or die "Cannot resolve class for " or die "Cannot resolve class for "
. join('/', @{ $path }) . " via $self->{ class_resolver }"; . 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 # Check whether we have a primitive - we implement them as classes
# TODO replace with UNIVERSAL->isa() # 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 # match is a bit faster if the string does not match, but WAY slower
# if $class matches... # if $class matches...
# if (not $class=~m{^SOAP::WSDL::XSD::Typelib::Builtin}xms) {
if (index $class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
if (index $_class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
# check wheter there is a CODE reference for $class::new. # check wheter there is a CODE reference for $class::new.
# If not, require it - all classes required here MUST # If not, require it - all classes required here MUST
# define new() # define new()
# This is the same as $class->can('new'), but it's way faster # This is the same as $class->can('new'), but it's way faster
*{ "$class\::new" }{ CODE } *{ "$_class\::new" }{ CODE }
or eval "require $class" ## no critic qw(ProhibitStringyEval) or eval "require $_class" ## no critic qw(ProhibitStringyEval)
or die $@; or die $@;
} }
# create object
# set current object $current = $_class->new({ %_attrs }); # set new current object
$current = $class->new({ %attrs });
# remember top level element # remember top level element
defined $self->{ data } exists $self->{ data }
or ($self->{ data } = $current); or ($self->{ data } = $current);
}, },
Char => sub { Char => sub {
return if $skip;
$characters .= $_[1]; $characters .= $_[1];
}, },
End => sub {
my $element = $_[1];
my ($prefix, $localname) = split m{:}xms , $element; End => sub {
# for non-prefixed elements $_element = $_[1];
if (not $localname) {
$localname = $element; ($_prefix, $_localname) = split m{:}xms , $_element;
$prefix = q{}; $_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... # This one easily handles ignores for us, too...
return if not ref $list->[-1]; return if not ref $$list[-1];
if ( $current # set characters in current if we are a simple type
->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') ) { # 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 ); $current->set_value( $characters );
} }
# currently doesn't work, as anyType does not implement value -
# maybe change ?
# $current->set_value( $characters ) if ($characters);
# set appropriate attribute in last element # set appropriate attribute in last element
# multiple values must be implemented in base class # multiple values must be implemented in base class
my $method = "add_$localname"; $_method = "add_$_localname";
$$list[-1]->$_method( $current );
$list->[-1]->$method( $current ); $current = pop @$list; # step up in object hierarchy...
# step up in path
pop @{ $path };
# step up in object hierarchy...
$current = pop @{ $list };
} }
); );
return $parser;
$parser->parse( $xml );
} }
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 { sub get_data {
my $self = shift; return $_[0]->{ data };
return $self->{ data };
} }
1; 1;
=pod =pod
@@ -167,6 +175,13 @@ Real fast expat based SOAP message parser.
See L<SOAP::WSDL::Parser> for details. 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 =head1 Bugs and Limitations
=over =over
@@ -193,9 +208,9 @@ This module may be used under the same terms as perl itself.
$ID: $ $ID: $
$LastChangedDate: $ $LastChangedDate: 2007-08-31 17:28:29 +0200 (Fr, 31 Aug 2007) $
$LastChangedRevision: $ $LastChangedRevision: 176 $
$LastChangedBy: $ $LastChangedBy: kutterma $
$HeadURL: $ $HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageParser.pm $
+17 -148
View File
@@ -2,147 +2,24 @@
package SOAP::WSDL::Expat::MessageStreamParser; package SOAP::WSDL::Expat::MessageStreamParser;
use strict; use strict;
use warnings; use warnings;
use SOAP::WSDL::XSD::Typelib::Builtin;
use XML::Parser::Expat; use XML::Parser::Expat;
use SOAP::WSDL::Expat::MessageParser;
use base qw(SOAP::WSDL::Expat::MessageParser);
=pod sub parse_start {
=head2 new
=over
=item SYNOPSIS
my $obj = ->new();
=item DESCRIPTION
Constructor.
=back
=cut
sub new {
my $class = shift;
my $self = {
class_resolver => shift->{ class_resolver }
};
bless $self, $class;
return $self;
}
sub class_resolver {
my $self = shift; my $self = shift;
$self->{ class_resolver } = shift; $self->{ parser } = $_[0]->_initialize( XML::Parser::ExpatNB->new() );
}
sub init;
*init = \&parse_start;
sub parse_more {
$_[0]->{ parser }->parse_more( $_[1] );
} }
sub init { sub parse_done {
my $self = shift; $_[0]->{ parser }->parse_done();
my $xml = shift;
$self->{ data } = undef;
my $characters;
my $current = '__STOP__';
my $ignore = [ 'Envelope', 'Body' ];
my $list = [];
my $namespace = {};
my $path = [];
my $parser = XML::Parser::ExpatNB->new();
no strict qw(refs);
$parser->setHandlers(
Start => sub {
my ($parser, $element, %attrs) = @_;
my ($prefix, $localname) = split m{:}xms , $element;
# for non-prefixed elements
if (not $localname) {
$localname = $element;
$prefix = q{};
} }
# ignore top level elements
if (@{ $ignore } && $localname eq $ignore->[0]) {
shift @{ $ignore };
return;
}
# empty characters
$characters = q{};
push @{ $path }, $localname; # step down...
push @{ $list }, $current; # remember current
# resolve class of this element
my $class = $self->{ class_resolver }->get_class( $path )
or die "Cannot resolve class for "
. join('/', @{ $path }) . " via $self->{ class_resolver }";
# 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
*{ "$class\::new" }{ CODE }
or eval "require $class" ## no critic qw(ProhibitStringyEval)
or die $@;
}
# create object
# set current object
$current = $class->new({ %attrs });
# remember top level element
defined $self->{ data }
or ($self->{ data } = $current);
},
Char => sub {
$characters .= $_[1];
},
End => sub {
my $element = $_[1];
my ($prefix, $localname) = split m{:}xms , $element;
# for non-prefixed elements
if (not $localname) {
$localname = $element;
$prefix = q{};
}
# This one easily handles ignores for us, too...
return if not ref $list->[-1];
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
my $method = "add_$localname";
$list->[-1]->$method( $current );
# step up in path
pop @{ $path };
# step up in object hierarchy...
$current = pop @{ $list };
}
);
return $parser;
}
sub get_data {
my $self = shift;
return $self->{ data };
}
1; 1;
@@ -174,15 +51,7 @@ See L<SOAP::WSDL::Parser> for details.
=head1 Bugs and Limitations =head1 Bugs and Limitations
=over See SOAP::WSDL::Expat::MessageParser
=item * Ignores all namespaces
=item * Does not handle mixed content
=item * The SOAP header is ignored
=back
=head1 AUTHOR =head1 AUTHOR
@@ -198,9 +67,9 @@ This module may be used under the same terms as perl itself.
$ID: $ $ID: $
$LastChangedDate: $ $LastChangedDate: 2007-08-31 17:28:29 +0200 (Fr, 31 Aug 2007) $
$LastChangedRevision: $ $LastChangedRevision: 176 $
$LastChangedBy: $ $LastChangedBy: kutterma $
$HeadURL: $ $HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageStreamParser.pm $
+213
View File
@@ -0,0 +1,213 @@
#!/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-08-31 17:28:29 +0200 (Fr, 31 Aug 2007) $
$LastChangedRevision: 176 $
$LastChangedBy: kutterma $
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageSubParser.pm $
+219
View File
@@ -0,0 +1,219 @@
#!/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-08-31 17:28:29 +0200 (Fr, 31 Aug 2007) $
$LastChangedRevision: 176 $
$LastChangedBy: kutterma $
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/SubParser.pm $
+175
View File
@@ -0,0 +1,175 @@
package SOAP::WSDL::Expat::WSDLParser;
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;
}
sub _initialize {
my ($self, $parser) = @_;
# init object data
$self->{ parser } = $parser;
delete $self->{ data };
# setup local variables for keeping temp data
my $characters = undef;
my $current = undef;
my $list = []; # node list
# TODO skip non-XML Schema namespace tags
$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') {
eval "require $action->{ class }";
croak $@ if ($@);
my $obj = $action->{ class }->new({ parent => $current })
->init( _fixup_attrs( $parser, %attrs ) );
if ($current) {
# inherit namespace, but don't override
$obj->set_targetNamespace( $current->get_targetNamespace() )
if not $obj->get_targetNamespace();
# push on parent's element/type list
my $method = "push_$localname";
no strict qw(refs);
$current->$method( $obj );
# remember element for stepping back
push @{ $list }, $current;
}
else {
$self->{ data } = $obj;
}
# set new element (step down)
$current = $obj;
}
elsif ($action->{ type } eq 'PARENT') {
$current->init( _fixup_attrs($parser, %attrs) );
}
elsif ($action->{ type } eq 'METHOD') {
my $method = $action->{ method } || $localname;
no strict qw(refs);
# call method with
# - default value ($action->{ value } if defined,
# dereferencing lists
# - the values of the elements Attributes hash
# TODO: add namespaces declared to attributes.
# Expat consumes them, so we have to re-add them here.
$current->$method( defined $action->{ value }
? ref $action->{ value }
? @{ $action->{ value } }
: ($action->{ value })
: _fixup_attrs($parser, %attrs)
);
}
},
Char => sub { $characters .= $_[1] },
End => sub {
my ($parser, $localname) = @_;
my $action = SOAP::WSDL::TypeLookup->lookup(
$parser->namespace( $localname ),
$localname
) || {};
return if not ($action->{ type });
if ( $action->{ type } eq 'CLASS' ) {
$current = pop @{ $list };
}
elsif ($action->{ type } eq 'CONTENT' ) {
my $method = $action->{ method };
# normalize whitespace
$characters =~s{ ^ \s+ (.+) \s+ $ }{$1}xms;
$characters =~s{ \s+ }{ }xmsg;
no strict qw(refs);
$current->$method( $characters );
}
}
);
return $parser;
}
# make attrs SAX style
sub _fixup_attrs {
my ($parser, %attrs_of) = @_;
my @attrs_from = map { $_ =
{
Name => $_,
Value => $attrs_of{ $_ },
LocalName => $_
}
} keys %attrs_of;
# add xmlns: attrs. expat eats them.
push @attrs_from, map {
# ignore xmlns=FOO namespaces - must be XML schema
# Other nodes should be ignored somewhere else
($_ eq '#default')
? ()
:
{
Name => "xmlns:$_",
Value => $parser->expand_ns_prefix( $_ ),
LocalName => $_
}
} $parser->new_ns_prefixes();
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;
+128
View File
@@ -0,0 +1,128 @@
package SOAP::WSDL::Factory::Serializer;
use strict;
use warnings;
my %SERIALIZER = (
'1.1' => 'SOAP::WSDL::Serializer::SOAP11',
);
# class method
sub register {
my ($class, $ref_type, $package) = @_;
$SERIALIZER{ $ref_type } = $package;
}
sub get_serializer {
my ($self, $args_of_ref) = @_;
eval "require $SERIALIZER{ $args_of_ref->{ soap_version } }" or die $@;
return $SERIALIZER{ $args_of_ref->{ soap_version } }->new();
}
1;
=pod
=head1 NAME
SOAP::WSDL::Factory::Serializer - factory for retrieving serializer objects
=head1 SYNOPSIS
# from SOAP::WSDL::Client:
$serializer = SOAP::WSDL::Factory::Serializer->get_serializer({
soap_version => $soap_version,
});
# in serializer class:
package MyWickedSerializer;
use SOAP::WSDL::Factory::Serializer;
# u don't know the SOAP 1.2 recommendation? poor boy...
SOAP::WSDL::Factory::Serializer->register( '1.2' , __PACKAGE__ );
=head1 DESCRIPTION
SOAP::WSDL::Factory::Serializer serves as factory for retrieving
serializer objects for SOAP::WSDL.
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()
=head1 METHODS
=head2 register
SOAP::WSDL::Serializer->register('1.1', 'MyWickedSerializer');
Globally registers a class for use as serializer class.
=head2 get_serializer
Returns an object of the serializer class for this endpoint.
=head1 WRITING YOUR OWN SERIALIZER CLASS
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.
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).
Serializer modules must be named equal to the serializer
class they contain. There can only be one serializer class per
serializer module.
Serializer class must implement the following methods:
=over
=item * new
Constructor.
=item * serialize
Serializes data to XML. The following named parameters are passed to
the serialize method in a anonymous hash ref:
{
method => $operation_name,
header => $header_data,
body => $body_data,
}
=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
+230
View File
@@ -0,0 +1,230 @@
package SOAP::WSDL::Factory::Transport;
use strict;
use warnings;
# class data
my %registered_transport_of = ();
# Local constants
# Could be made readonly, but that's just for the paranoid...
my %SOAP_LITE_TRANSPORT_OF = (
ftp => 'SOAP::Transport::FTP',
http => 'SOAP::Transport::HTTP',
https => 'SOAP::Transport::HTTPS',
mailto => 'SOAP::Transport::MAILTO',
'local' => 'SOAP::Transport::LOCAL',
jabber => 'SOAP::Transport::JABBER',
mq => 'SOAP::Transport::MQ',
);
my %SOAP_WSDL_TRANSPORT_OF = (
http => 'SOAP::WSDL::Transport::HTTP',
https => 'SOAP::WSDL::Transport::HTTP',
);
# class methods only
sub register {
my ($class, $scheme, $package) = @_;
$registered_transport_of{ $scheme } = $package;
}
sub get_transport {
my ($class, $scheme, %attrs) = @_;
$scheme =~s{ \A ([^\:]+) \: .+ }{$1}smx;
if (exists $registered_transport_of{ $scheme }) {
eval "require $registered_transport_of{ $scheme }" or die $@;
# try "foo::Client" class first - SOAP::Tranport always requires
# a package withoug the ::Client appended, and then
# instantiates a ::Client object...
# ... pretty weird ...
# ... must be from some time when the max number of files was a
# 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 $@;
return $registered_transport_of{ $scheme }->new( %attrs );
}
# try SOAP::Lite's Transport module - just skip if not require'able
SOAP_Lite: {
if (exists $SOAP_LITE_TRANSPORT_OF{ $scheme }) {
eval "require $SOAP_LITE_TRANSPORT_OF{ $scheme }"
or last SOAP_Lite;
my $protocol_class = $SOAP_LITE_TRANSPORT_OF{ $scheme } . '::Client';
return $protocol_class->new( %attrs );
}
}
if (exists $SOAP_WSDL_TRANSPORT_OF{ $scheme }) {
eval "require $SOAP_WSDL_TRANSPORT_OF{ $scheme }" or die $@;
return $SOAP_WSDL_TRANSPORT_OF{ $scheme }->new( %attrs );
}
die "no transport class found for scheme <$scheme>";
}
1;
=pod
=head1 NAME
SOAP::WSDL::Factory::Transport - factory for retrieving transport objects
=head1 SYNOPSIS
# from SOAP::WSDL::Client:
$transport = SOAP::WSDL::Factory::Transport->get_transport( $url, @opt );
# in transport class:
package MyWickedTransport;
use SOAP::WSDL::Factory::Transport;
# u don't know the httpr protocol? poor boy...
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.
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
=head1 METHODS
=head2 register
SOAP::WSDL::Transport->register('https', 'MyWickedTransport');
Globally registers a class for use as transport class.
=head2 proxy
$trans->proxy('http://soap-wsdl.sourceforge.net');
Sets the proxy (endpoint).
Returns the transport for this protocol.
=head2 set_transport
Sets the current transport object.
=head2 get_transport
Gets the current transport object.
=head1 WRITING YOUR OWN 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.
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).
Multiple protocols ore multiple classes are registered by multiple calls to
register().
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.
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:
=over
=item * new
=item * send_receive
Dispatches a request and returns the content of the response.
=item * code
Returns the status code of the last send_receive call (if any).
=item * message
Returns the status message of the last send_receive call (if any).
=item * status
Returns the status of the last send_receive call (if any).
=item * is_success
Returns true after a send_receive was successful, false if it was not.
=back
SOAP::Lite requires transport modules to pack client and server
classes in one file, and to follow this naming scheme:
Module name:
"SOAP::Transport::" . uc($scheme)
Client class (additional package in module):
"SOAP::Transport::" . uc($scheme) . "::Client"
Server class (additional package in module):
"SOAP::Transport::" . uc($scheme) . "::Client"
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.
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.
=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: Transport.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/Transport.pm $
=cut
+147 -1
View File
@@ -4,7 +4,7 @@
SOAP::WSDL::Manual - accessing WSDL based web services SOAP::WSDL::Manual - accessing WSDL based web services
=head1 Intro: Accessing a WSDL-based web service =head1 Accessing a WSDL-based web service
=head2 Quick walk-through for the unpatient =head2 Quick walk-through for the unpatient
@@ -57,6 +57,152 @@ classes and returned to the user as objects.
To find out which class a particular XML node should be, SOAP::WSDL uses To find out which class a particular XML node should be, SOAP::WSDL uses
typemaps. For every Web service, there's also a typemap created. typemaps. For every Web service, there's also a typemap created.
=head2 Interface class creation
To create interface classes, follow the steps above from
L<Quick walk-through for the unpatient|Quick walk-through for the unpatient>.
If this works fine for you, skip the next paragraphs. If not, read on.
The steps to instrument a web service with SOAP::WSDL perl bindings
(in detail) are as follows:
=over
=item * Gather web service information
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
later.
=item * Create WSDL bindings
perl wsdl2perl.pl -b base_dir URL
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
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::).
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.
=item * Write a perl script (or module) accessing the web service.
use MyInterface::SERVICE_NAME;
my $service = MyInterface::SERVICE_NAME->new();
my $result = $service->SERVICE_METHOD();
die $result if not $result;
print $result;
The above handling of errors ("die $result if not $result") may look a bit
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.
You may, of course, access individual fault properties, too. To get a list of
fault properties, see L<SOAP::WSDL::SOAP::Typelib::Fault11>
=back
=head2 Adding missing information
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.
There are two steps you need to perform for adding additional information.
=over
=item * Provide required type classes
For each extra data type used in the XML messages, a type class has to be
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.
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.
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.
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):
'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.
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.
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.
=back
=head1 Accessing a web service without a WSDL definition
=head1 Troubleshooting
=head1 SEE ALSO =head1 SEE ALSO
L<SOAP::WSDL::Manual::Glossary> The meaning of all these words L<SOAP::WSDL::Manual::Glossary> The meaning of all these words
+50 -10
View File
@@ -7,13 +7,16 @@ SOAP::WSDL::Manual::Glossary - Those acronyms and stuff
=head2 web service =head2 web service
Web services are RPC (Remote Procedure Call) interfaces accessible via Web services are RPC (Remote Procedure Call) interfaces accessible via
the internet, typically via HTTP(S). some internet protocol, typically via HTTP(S).
=head2 SOAP =head2 SOAP
SOAP (the Simple Object Access Protocol) is a specification for SOAP is an acronym for Simple Object Access Protocol.
defining RPC interfaces, including (but not neccessarily limited to) SOAP is a W3C recommendation. The latest version of the SOAP
web services. specification may be found at L<http://www.w3.org/TR/soap/>.
SOAP defines a protocoll for message exchange between applications.
The most popular usage is to use SOAP for remote procedure calls (RPC).
While one of the constituting aspects of a web service is its While one of the constituting aspects of a web service is its
reachability via some internet protocol, you might as well define reachability via some internet protocol, you might as well define
@@ -21,20 +24,57 @@ SOAP services accessible via postcards.
Despite it's name, SOAP has nothing more to do with objects than Despite it's name, SOAP has nothing more to do with objects than
cars have with pets - SOAP messages may, but not neccessarily do cars have with pets - SOAP messages may, but not neccessarily do
carry object, very much like your car may, but does not need to carry objects, very much like your car may, but does not need to
carry your pet. carry your pet.
=head2 WSDL =head2 WSDL
WSDL (Web Service Definition Language) is a XML-based markup language WSDL is an acronym for Web Services Description Language.
for defining web service interfaces. WSDL is a W3C recommendation. The latest version of the WSDL specification
may be found at L<http://www.w3.org/TR/wsdl20/>.
WSDL defines a XML-based language for describing web service interfaces,
including SOAP interfaces.
=head2 WS-I =head2 WS-I
WS-I (Web Service Interoperability) is a industry consortium dedicated WS-I (Web Services Interoperability Organization) is an open industry
to finding interoperability rules for web services. organisation chartered to promote Web service interoperability across
platforms, operating systems, and programming languages.
SOAP::WSDL aims to be a WS-I compliant SOAP client. WS-I publishes profiles, which provide implementation guidelines for
how related Web services specifications should be used together for
best interoperability. To date, WS-I has finalized the Basic Profile,
Attachments Profile and Simple SOAP Binding Profile.
SOAP::WSDL aims at complying to the Basic Profile (but does not
implement full support yet).
=head2 SOAP message styles
=head3 rpc
Meant for transporting a RPC message. All contents of the SOAP body are
put into a top-level node named equal to the SOAP operation.
WS-I Basic Profile allows the use of rpc message style.
SOAP::WSDL does not support rpc message style yet.
SOAP::Lite supports rpc message style only.
=head3 document
Meant for transporting arbitrary content. No additional nodes are inserted
between the SOAP body and the actual content.
WS-I Basic Profile allows the use of document message style.
=head2 SOAP encoding styles
=head3 encoded
=head3 literal
=head1 LICENSE =head1 LICENSE
File diff suppressed because it is too large Load Diff
+3
View File
@@ -4,6 +4,9 @@ use warnings;
use Class::Std::Storable; use Class::Std::Storable;
use base qw/SOAP::WSDL::Base/; 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 %operation_of :ATTR(:name<operation> :default<()>);
my %input_of :ATTR(:name<input> :default<()>); my %input_of :ATTR(:name<input> :default<()>);
my %output_of :ATTR(:name<output> :default<()>); my %output_of :ATTR(:name<output> :default<()>);
+82 -16
View File
@@ -6,8 +6,8 @@ SOAP::WSDL::Parser - How SOAP::WSDL parses XML messages
=head1 Which XML message does SOAP::WSDL parse ? =head1 Which XML message does SOAP::WSDL parse ?
Naturally, there are two kinds of XMLdocuments (or messages) SOAP::WSDL Naturally, there are two kinds of XML documents (or messages)
has to parse: SOAP::WSDL has to parse:
=over =over
@@ -19,13 +19,55 @@ has to parse:
=head1 Parser implementations =head1 Parser implementations
There are different parser implementations available for SOAP messages - There are different parser implementations available for SOAP messages
currently there's only one for WSDL definitions. 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>.
The use of SAX and L<XML::LibXML|XML::LibXML> in SOAP::WSDL is
deprecated for the following reasons:
=over
=item * Speed
L<XML::Parser::Expat|XML::Parser::Expat> is faster than
L<XML::LibXML|XML::LibXML> - at least when optimized for speed.
=item * Availability
L<XML::Parser|XML::Parser> is more popular than
L<XML::LibXML|XML::LibXML>.
=item * Stability
XML::LibXML is based on the libxml2 library. Several versions of
libxml2 are known to have specific bugs. As a workaround, there are
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.
=item * SOAP::Lite uses XML::Parser
L<SOAP::Lite|SOAP::Lite> uses L<XML::Parser|XML::Parser> if available.
SOAP::WSDL should not require users to install both L<XML::Parser|XML::Parser>
and L<XML::LibXML|XML::LibXML>.
=back
=head2 WSDL definitions parser =head2 WSDL definitions parser
=over =over
=item * SOAP::WSDL::Expat::WSDLParser
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 =item * SOAP::WSDL::SAX::WSDLHandler
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
@@ -90,6 +132,29 @@ A class resolver package might look like this:
}; };
1; 1;
=head3 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__'.
In the example above, EnqueueMessage/StuffIDontNeed and all child elements
are skipped.
my %class_list = (
'EnqueueMessage' => 'Typelib::TEnqueueMessage',
'EnqueueMessage/MMessage' => 'Typelib::TMessage',
'EnqueueMessage/MMessage/MRecipientURI' => 'SOAP::WSDL::XSD::Builtin::anyURI',
'EnqueueMessage/MMessage/MMessageContent' => 'SOAP::WSDL::XSD::Builtin::string',
'EnqueueMessage/StuffIDontNeed' => '__SKIP__',
'EnqueueMessage/StuffIDontNeed/Foo' => 'SOAP::WSDL::XSD::Builtin::string',
'EnqueueMessage/StuffIDontNeed/Bar' => 'SOAP::WSDL::XSD::Builtin::string',
);
Note that only SOAP::WSDL::Expat::MessageParser implements skipping elements
at the time of writing.
=head3 Creating type lib classes =head3 Creating type lib classes
Every element must have a correspondent one in the type library. Every element must have a correspondent one in the type library.
@@ -109,6 +174,19 @@ L<SOAP::WSDL::XSD::Typelib::ComplexType> and L<SOAP::WSDL::XSD::Typelib::SimpleT
=over =over
=item * SOAP::WSDL::Expat::MessageParser
A L<XML::Parser::Expat|XML::Parser::Expat> based parser. This is the fastest
parser for most SOAP messages and the default for SOAP::WSDL::Client.
=item * SOAP::WSDL::Expat::MessageStreamParser
A XML::Parser::ExpatNB based parser. Useful for parsing huge HTTP responses,
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 =item * SOAP::WSDL::SAX::MessageHandler
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
@@ -121,18 +199,6 @@ Can be used for parsing both streams (chunks) and documents.
See L<SOAP::WSDL::SAX::MessageHandler> for details. See L<SOAP::WSDL::SAX::MessageHandler> for details.
=item * SOAP::WSDL::Expat::MessageParser
A L<XML::Parser::Expat|XML::Parser::Expat> based parser. This is the fastest
parser for most SOAP messages and the default for SOAP::WSDL::Client.
=item * SOAP::WSDL::Expat::MessageStreamParser
A XML::Parser::ExpatNB based parser. Useful for parsing huge HTTP responses,
as you don't need to keep everything in memory.
See L<SOAP::WSDL::Expat::MessageStreamParser|SOAP::WSDL::Expat::MessageStreamParser> for details.
=back =back
=head3 Performance =head3 Performance
+71
View File
@@ -0,0 +1,71 @@
Release notes for SOAP::WSDL 2.00_11
-------
I'm happy to present a new pre-release version of SOAP::WSDL.
The following features were added (the numbers in brackets are the tracker IDs
from https://sourceforge.net/tracker/?group_id=111978&atid=660924):
* [1767963] Transport plugins via SOAP::WSDL::Factory::Transport.
SOAP::WSDL uses SOAP::Lite's tranport modules as default, with a
lightweight HTTP(S) transport plugin as fallback.
Custom transport modules can be registered via
SOAP::WSDL::Factory::Transport.
* [ 1772730 ] Serializer plugins via SOAP::WSDL::Factory::Serializer
The default serializer for SOAP1.1 is SOAP::WSDL::Serializer::SOAP11.
Custom serializers classes can be registered via
SOAP::WSDL::Factory::Serializer or set via SOAP::Lite's set_serializer
method.
The following bugs have been fixed (the numbers in brackets are the tracker IDs
from https://sourceforge.net/tracker/?group_id=111978&atid=660921):
* [ 1764854 ] Port WSDL parser to expat and remove XML::LibXML dependency
SOAP::WSDL now requires only XML::Parser to be installed.
XML::LibXML is not required any more, though XML::LibXML based modules still
exist.
The following uncategorized improvements have been made
* The number of dependencies has been reduced. SOAP::WSDL no longer requires the
following modules to be installed:
- XML::SAX::Base
- XML::SAX::ParserFactory
- Pod::Simple::Text
* The missing prerequisite Template has been added.
* Documentation has been improved.
The following changes were made in former pre-relase versions:
2.00_10
----
* Changed Makefile.PL to use Module::Build (passthrough mode)
* fixed element ref="" handling
2.00_09
----
* SOAP::WSDL::XSD::Typelib::Builtin::boolean objects now return their numerical
value in bool context, not "true" or "false" (always true...)
* date/time test are now timezone-sensitive
* examples added
2.00_08
---
* SOAP message parser may skip unwanted parts of the message - see
SOAP::WSDL::Expat::MessageParser for details.
* HTTP Content-Type is configurable now
* SOAP::WSDL::XSD::Typelib::ComplexType based objects now accept a
list ref of hash refs as parameter to set_value.
* SOAP::WSDL::XSD::Typelib::Builtin::dateTime and ::date now converts date
strings into XML date strings
* SOAP::WSDL::Definitions::create now
- converts '.' in service names to '::' (.NET class separator to perl class
separator)
- outputs Typemaps and Interface classes in UTF8 to allow proper inclusion
of UTF8 documentation from WSDL
* WSDLHandler now handles <wsdl:documentation> tags
* SOAP::WSDL::Definitions now includes some usable doc in generated interface classes
* fixed explain in SimpleType, ComplexType and Element (someway)
+4 -4
View File
@@ -273,9 +273,9 @@ This module may be used under the same terms as perl itself.
$ID: $ $ID: $
$LastChangedDate: $ $LastChangedDate: 2007-08-31 17:28:29 +0200 (Fr, 31 Aug 2007) $
$LastChangedRevision: $ $LastChangedRevision: 176 $
$LastChangedBy: $ $LastChangedBy: kutterma $
$HeadURL: $ $HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/SAX/MessageHandler.pm $
+17 -4
View File
@@ -3,13 +3,13 @@ use strict;
use warnings; use warnings;
use Carp; use Carp;
use Class::Std::Storable; use Class::Std::Storable;
# use base qw(XML::SAX::Base);
use SOAP::WSDL::TypeLookup; use SOAP::WSDL::TypeLookup;
my %tree_of :ATTR(:name<tree> :default<{}>); my %tree_of :ATTR(:name<tree> :default<{}>);
my %order_of :ATTR(:name<order> :default<[]>); my %order_of :ATTR(:name<order> :default<[]>);
my %targetNamespace_of :ATTR(:name<targetNamespace> :default<()>); my %targetNamespace_of :ATTR(:name<targetNamespace> :default<()>);
my %current_of :ATTR(:name<current> :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 # we have to implement our own new - we need a blessed Hash ref as $self
@@ -34,7 +34,6 @@ my %current_of :ATTR(:name<current> :default<()>);
# ...we ignore em all... # ...we ignore em all...
no strict qw(refs); no strict qw(refs);
foreach my $method ( qw( foreach my $method ( qw(
characters
processing_instruction processing_instruction
ignorable_whitespace ignorable_whitespace
set_document_locator set_document_locator
@@ -88,6 +87,7 @@ sub start_element {
$element->{ LocalName } $element->{ LocalName }
); );
$characters_of{ $ident } = q{};
return if not $action; return if not $action;
if ($action->{ type } eq 'CLASS') { if ($action->{ type } eq 'CLASS') {
@@ -139,6 +139,10 @@ sub start_element {
} }
} }
sub characters {
$characters_of{ ident $_[0] } .= $_[1]->{ Data };
}
sub end_element { sub end_element {
my ($self, $element) = @_; my ($self, $element) = @_;
my $ident = ident $self; my $ident = ident $self;
@@ -148,10 +152,19 @@ sub end_element {
$element->{ LocalName } $element->{ LocalName }
) || {}; ) || {};
if ($action->{ type } && $action->{ type } eq 'CLASS' ) return if not ($action->{ type });
{ if ( $action->{ type } eq 'CLASS' ) {
$current_of{ $ident } = pop @{ $order_of{ $ident } }; $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 { sub fatal_error {
@@ -1,13 +1,17 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
package SOAP::WSDL::Envelope; package SOAP::WSDL::Serializer::SOAP11;
use strict; use strict;
use base qw/SOAP::WSDL::Base/; use warnings;
use Class::Std::Storable;
# use base qw/SOAP::WSDL::Base/;
my $SOAP_NS = 'http://schemas.xmlsoap.org/soap/envelope/'; my $SOAP_NS = 'http://schemas.xmlsoap.org/soap/envelope/';
my $XML_INSTANCE_NS = 'http://www.w3.org/2001/XMLSchema-instance'; my $XML_INSTANCE_NS = 'http://www.w3.org/2001/XMLSchema-instance';
sub serialize { sub serialize {
my ($self, $name, $data, $opt) = @_; my ($self, $args_of_ref) = @_;
my $opt = $args_of_ref->{ options };
if (not $opt->{ namespace }->{ $SOAP_NS }) if (not $opt->{ namespace }->{ $SOAP_NS })
{ {
@@ -32,8 +36,9 @@ sub serialize {
# TODO insert encoding # TODO insert encoding
$xml.='>'; $xml.='>';
$xml .= $self->serialize_header($name, $data, $opt); $xml .= $self->serialize_header($args_of_ref->{ method }, $args_of_ref->{ header }, $opt);
$xml .= $self->serialize_body($name, $data, $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 .= "\n" if ($opt->{ readable });
$xml .= '</' . $soap_prefix .':Envelope>'; $xml .= '</' . $soap_prefix .':Envelope>';
$xml .= "\n" if ($opt->{ readable }); $xml .= "\n" if ($opt->{ readable });
+107
View File
@@ -0,0 +1,107 @@
package SOAP::WSDL::Transport::HTTP;
use strict;
use base qw(LWP::UserAgent);
# create methods normally inherited from SOAP::Client
SUBFACTORY: {
no strict qw(refs);
foreach my $method ( qw(code message status is_success) ) {
*{ $method } = sub {
my $self = shift;
return $self->{ $method } if not @_;
return $self->{ $method } = shift;
};
}
}
sub send_receive {
my ($self, %parameters) = @_;
my ($envelope, $soap_action, $endpoint, $encoding, $content_type) =
@parameters{qw(envelope action endpoint encoding content_type)};
$encoding = defined($encoding)
? '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
# content-length header and starting 5.6.1 length() calculates chars
# instead of bytes. 'use bytes' in THIS file doesn't work, because
# it's lexically scoped. Unfortunately, content-length we calculate
# here doesn't work either, because LWP overwrites it with
# content-length it calculates (which is wrong) AND uses length()
# during syswrite/sysread, so we are in a bad shape anyway.
#
# what to do? we calculate proper content-length (using
# bytelength() function from SOAP::Utils) and then drop utf8 mark
# from string (doing pack with 'C0A*' modifier) if length and
# bytelength are not the same
# use bytes is lexically scoped
my $bytelength = do { use bytes; length $envelope };
$envelope = pack('C0A*', $envelope)
if length($envelope) != $bytelength;
# END TODO
my $request = HTTP::Request->new( 'POST',
$endpoint,
[ 'Content-Type', "$content_type; charset=$encoding",
'Content-Length', $bytelength,
'SOAPAction', $soap_action,
],
$envelope );
use Data::Dumper;
warn Dumper $request;
my $response = $self->request( $request );
warn Dumper $response;
$self->code( $response->code);
$self->message( $response->message);
$self->is_success($response->is_success);
$self->status($response->status_line);
return $response->content();
}
1;
=pod
=head1 NAME
SOAP::WSDL::Transport::HTTP - Fallback http(s) transport class
=head1 DESCRIPTION
Provides a thin transport class used by SOAP::WSDL::Transport when
SOAP::Lite is not available.
=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: HTTP.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/Transport/HTTP.pm $
=cut
+32 -10
View File
@@ -15,9 +15,6 @@ my %TYPES = (
type => 'CLASS', type => 'CLASS',
class => 'SOAP::WSDL::PortType', class => 'SOAP::WSDL::PortType',
}, },
types => {
type => 'SKIP',
},
message => { message => {
type => 'CLASS', type => 'CLASS',
class => 'SOAP::WSDL::Message', class => 'SOAP::WSDL::Message',
@@ -53,6 +50,10 @@ my %TYPES = (
types => { types => {
type => 'CLASS', type => 'CLASS',
class => 'SOAP::WSDL::Types', class => 'SOAP::WSDL::Types',
},
documentation => {
type => 'CONTENT',
method => 'set_documentation',
} }
}, },
# soap: # soap:
@@ -71,11 +72,38 @@ my %TYPES = (
type => 'PARENT', type => 'PARENT',
} }
}, },
'http://www.w3c.org/2001/XMLSchema' => { 'http://www.w3.org/2001/XMLSchema' => {
schema => { schema => {
type => 'CLASS', type => 'CLASS',
class => 'SOAP::WSDL::XSD::Schema', class => 'SOAP::WSDL::XSD::Schema',
}, },
attribute => {
type => 'SKIP' # not implemented yet
},
attributeGroup => {
type => 'SKIP', # not implemented yet
},
key => {
type => 'SKIP', # not implemented yet
},
keyref => {
type => 'SKIP', # not implemented yet
},
unique => {
type => 'SKIP', # not implemented yet
},
notation => {
type => 'SKIP', # not implemented yet
},
annotation => {
type => 'SKIP', # not implemented yet
},
appinfo => {
type => 'SKIP', # not implemented yet
},
description => {
type => 'SKIP', # not implemented yet
},
element => { element => {
type => 'CLASS', type => 'CLASS',
class => 'SOAP::WSDL::XSD::Element', class => 'SOAP::WSDL::XSD::Element',
@@ -134,15 +162,9 @@ my %TYPES = (
method => 'set_flavor', method => 'set_flavor',
value => 'sequence', value => 'sequence',
}, },
}, },
); );
# thei're equal (typo ?)
$TYPES{ 'http://www.w3.org/2001/XMLSchema' } = $TYPES{
'http://www.w3c.org/2001/XMLSchema'
};
sub lookup { sub lookup {
my $self = shift; my $self = shift;
+46
View File
@@ -0,0 +1,46 @@
package SOAP::WSDL::XSD::Builtin;
use strict;
use warnings;
use Class::Std::Storable;
use base qw(SOAP::WSDL::Base);
use Data::Dumper;
sub serialize {
my ($self, $name, $value, $opt) = @_;
my $xml;
$opt->{ indent } ||= "";
$opt->{ attributes } ||= [];
$xml .= $opt->{ indent } if ($opt->{ readable });
$xml .= '<' . join ' ', $name, @{ $opt->{ attributes } };
if ( $opt->{ autotype }) {
my $ns = $self->get_targetNamespace();
my $prefix = $opt->{ namespace }->{ $ns }
|| die 'No prefix found for namespace '. $ns;
$xml .= ' type="' . $prefix . ':'
. $self->get_name() . '"' if ($self->get_name() );
}
if (defined $value) {
$xml .= '>';
$xml .= "$value";
$xml .= '</' . $name . '>' ;
}
else {
$xml .= '/>';
}
$xml .= "\n" if ($opt->{ readable });
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;
+36 -38
View File
@@ -128,15 +128,14 @@ sub explain {
return q{} if not $flavor; # empty complexType return q{} if not $flavor; # empty complexType
$opt->{ indent } ||= q{ }; $opt->{ indent } ||= q{ };
my $xml = q{}; my $xml = q{};
$xml .= "$opt->{indent}\'$name'=> " if $name; $xml .= "$opt->{indent}\'$name'=> {\n" if $name;
if ( ($flavor eq "sequence") or ($flavor eq "all") ) { if ( ($flavor eq "sequence") or ($flavor eq "all") ) {
$xml .= "{\n";
$opt->{ indent } .= " "; $opt->{ indent } .= " ";
$xml .= join q{}, map { $_->explain( $opt ) } for my $element (@{ $self->get_element() }) {
@{ $self->get_element() }; $xml .= $element->explain( $opt )
}
$opt->{ indent } =~s/\s{2}$//; # step back $opt->{ indent } =~s/\s{2}$//; # step back
$xml .= "$opt->{ indent }},\n";
} }
elsif ($flavor eq "complexContent") elsif ($flavor eq "complexContent")
{ {
@@ -150,6 +149,11 @@ sub explain {
{ {
warn "found unsupported complexType definition $flavor"; warn "found unsupported complexType definition $flavor";
} }
# if we're called inside a element...
$xml .= "$opt->{indent}},\n" if $name;
return $xml; return $xml;
} }
@@ -198,7 +202,7 @@ __PACKAGE__->_factory(
{ {
[%- [%-
FOREACH element=self.get_element; FOREACH element=self.get_element;
IF (element.get_type); IF (element.get_type); # element type="..."
split_name = element.get_type.split(':'); split_name = element.get_type.split(':');
prefix = split_name.0; prefix = split_name.0;
localname = split_name.1; localname = split_name.1;
@@ -207,7 +211,12 @@ __PACKAGE__->_factory(
[% ELSE -%] [% ELSE -%]
[% element.get_name %] => '[% type_prefix %][% localname %]', [% element.get_name %] => '[% type_prefix %][% localname %]',
[%- END; [%- END;
ELSIF (simpleType = element.first_simpleType); 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(); base = simpleType.get_base();
%] %]
# basic simple type handling: we treat atomic simple types # basic simple type handling: we treat atomic simple types
@@ -234,17 +243,24 @@ sub get_xmlns { '[% self.get_targetNamespace %]' }
__END__ __END__
=pod [% MACRO pod BLOCK %]=pod[% END %]
[% MACRO cut BLOCK %]=cut[% END %]
[% MACRO head1 BLOCK %]=head1[% END %]
[% MACRO head2 BLOCK %]=head2[% END %]
=head1 NAME [% type_prefix %][% self.get_name %] [% pod %]
=head1 SYNOPSIS [% head1 %] NAME
=head1 DESCRIPTION [% type_prefix %][% self.get_name %]
[% head1 %] SYNOPSIS
[% head1 %] DESCRIPTION
Type class for the XML type [% self.get_name %]. Type class for the XML type [% self.get_name %].
=head1 PROPERTIES [% head1 %] PROPERTIES
The following properties may be accessed using get_PROPERTY / set_PROPERTY The following properties may be accessed using get_PROPERTY / set_PROPERTY
methods: methods:
@@ -253,7 +269,7 @@ methods:
[% element.get_name -%] [% element.get_name -%]
[% END %] [% END %]
=head1 Object structure [% head1 %] Object structure
[% FOREACH element=self.get_element; [% FOREACH element=self.get_element;
IF (element.get_type); IF (element.get_type);
@@ -265,7 +281,12 @@ methods:
[% ELSE -%] [% ELSE -%]
[% element.get_name %] => '[% type_prefix %][% localname %]', [% element.get_name %] => '[% type_prefix %][% localname %]',
[%- END; [%- END;
ELSIF (simpleType = element.first_simpleType); 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(); base = simpleType.get_base();
split_name = base.split(':'); split_name = base.split(':');
prefix = split_name.0; prefix = split_name.0;
@@ -288,7 +309,7 @@ Structure as perl hash:
[% structure %] [% structure %]
=cut [% cut %]
EOT EOT
@@ -300,26 +321,3 @@ sub _check_value {
} }
1; 1;
=pod
=head1 Bugs and limitations
=over
=item * attribute definitions
Attribute definitions are ignored
=item * abstract, block, final, mixed
Handling of these attribute is not implemented yet.
=item * simpleContent, complexContent, extension, restriction, group, choice
Handling of these child elements is not implemented yet
=item * explain may produce erroneous results
=back
=cut
+49 -62
View File
@@ -90,8 +90,8 @@ sub serialize {
elsif (my $ref_name = $ref_of{ $ident }) { # ref elsif (my $ref_name = $ref_of{ $ident }) { # ref
my ($prefix, $localname) = split /:/ , $ref_name; my ($prefix, $localname) = split /:/ , $ref_name;
my $ns = $ns_map{ $prefix }; my $ns = $ns_map{ $prefix };
$type = $typelib->find_type( $ns, $localname ); $type = $typelib->find_element( $ns, $localname );
die "no type for $prefix:$localname" if (not $type); die "no element for ref $prefix:$localname" if (not $type);
return $type->serialize( $name, $value, $opt ); return $type->serialize( $name, $value, $opt );
} }
@@ -116,13 +116,25 @@ sub explain {
# if we have a simple / complexType, explain right here # if we have a simple / complexType, explain right here
if ($type = $self->first_simpleType() ) if ($type = $self->first_simpleType() )
{ {
$text .= $type->explain( $opt, $self->get_name() ); if ($opt->{ anonymous }) {
return $text; delete $opt->{ anonymous };
return $type->explain( $opt, undef );
}
return $type->explain( $opt, $self->get_name() );
} }
elsif ($type = $self->first_complexType() ) elsif ($type = $self->first_complexType() )
{ {
$text .= $type->explain( $opt, $self->get_name() ); if ($opt->{ anonymous }) {
return $text; 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 # return if it's not a derived type - we don't handle
@@ -140,10 +152,13 @@ sub explain {
use Data::Dumper; use Data::Dumper;
die "no type for $prefix:$localname ($ns_map{ $prefix })" die "no type for $prefix:$localname ($ns_map{ $prefix })"
. Dumper $opt->{ wsdl }->first_types()->first_schema()->_DUMP . Dumper $opt->{ wsdl }->first_types()->first_schema()->_DUMP
if (not $type); if (not $type);
return $text .= $type->explain( $opt, $self->get_name() ); if ($opt->{ anonymous }) {
delete $opt->{ anonymous };
return $text .= $type->explain( $opt, undef );
}
return $text .= $type->explain( $opt, $name || $self->get_name() );
return 'ERROR: '. $@; return 'ERROR: '. $@;
} }
@@ -231,6 +246,7 @@ package [% element_prefix %][% self.get_name %];
use strict; use strict;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element; use SOAP::WSDL::XSD::Typelib::Element;
[% IF (type = self.first_simpleType) %] [% IF (type = self.first_simpleType) %]
# <element name="[% self.get_name %]"><simpleType> definition # <element name="[% self.get_name %]"><simpleType> definition
use SOAP::WSDL::XSD::Typelib::SimpleType; use SOAP::WSDL::XSD::Typelib::SimpleType;
@@ -240,6 +256,17 @@ use base qw(
[% type.flavor_class %] [% type.flavor_class %]
[% type.base_class($type_prefix) %] [% 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) %] [% ELSIF (type = self.first_complexType) %]
# atomic complexType # atomic complexType
# <element name="[% self.get_name %]"><complexType> definition # <element name="[% self.get_name %]"><complexType> definition
@@ -295,10 +322,6 @@ use base qw(
SOAP::WSDL::XSD::Typelib::Element SOAP::WSDL::XSD::Typelib::Element
[% base_class %] [% base_class %]
); );
[% ELSIF (element = self.get_ref)
%]
# element ref"element" definition
# Sorry, we don't handle this yet...
[% END %] [% END %]
sub get_xmlns { '[% self.get_targetNamespace %]' } sub get_xmlns { '[% self.get_targetNamespace %]' }
@@ -314,17 +337,24 @@ __PACKAGE__->__set_ref('[% self.get_ref %]');
__END__ __END__
=pod [% MACRO pod BLOCK %]=pod[% END %]
[% MACRO cut BLOCK %]=cut[% END %]
[% MACRO head1 BLOCK %]=head1[% END %]
[% MACRO head2 BLOCK %]=head2[% END %]
=head1 NAME [% element_prefix %][% self.get_name %] [% pod %]
=head1 SYNOPSIS [% head1 %] NAME
=head1 DESCRIPTION [% element_prefix %][% self.get_name %]
[% head1 %] SYNOPSIS
[% head1 %] DESCRIPTION
Type class for the XML element [% self.get_name %]. Type class for the XML element [% self.get_name %].
=head1 PROPERTIES [% head1 %] PROPERTIES
The following properties may be accessed using get_PROPERTY / set_PROPERTY The following properties may be accessed using get_PROPERTY / set_PROPERTY
methods: methods:
@@ -335,7 +365,7 @@ methods:
[% END; [% END;
END %] END %]
=head1 Object structure [% head1 %] Object structure
[%- IF (type = self.first_complexType); [%- IF (type = self.first_complexType);
FOREACH element = type.get_element; FOREACH element = type.get_element;
@@ -360,7 +390,7 @@ Structure as perl hash:
[% structure %] [% structure %]
=cut [% cut %]
EOT EOT
@@ -369,47 +399,4 @@ EOT
1; 1;
__END__
=pod
=head1 NAME
SOAP::WSDL::XSD::Element - XSD Element representation
=head1 DESCRIPTION
Represents a XML Schema Definition's Element element for serializing into
various forms.
=head1 Bugs and limitations
=over
=item * block
Handling of the block attribute is not implemented yet.
=item * final
Handling of the final attribute is not implemented yet.
=item * substitutionGroup
Handling of the substitutionGroup attribute is not implemented yet
=item * explain may produce erroneous results
=back
=head1 COPYING
This module is part of SOAP-WSDL. See SOAP::WSDL for license.
=head1 AUTHOR
Insert @ instead of whitespace into e-mail.
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=cut
-50
View File
@@ -1,50 +0,0 @@
package SOAP::WSDL::XSD::Primitive;
use strict;
use warnings;
use Class::Std::Storable;
use base qw(SOAP::WSDL::Base);
use Data::Dumper;
sub serialize
{
my ($self, $name, $value, $opt) = @_;
my $xml;
$opt->{ indent } ||= "";
$opt->{ attributes } ||= [];
$xml .= $opt->{ indent } if ($opt->{ readable });
$xml .= '<' . join ' ', $name, @{ $opt->{ attributes } };
if ( $opt->{ autotype })
{
my $ns = $self->get_targetNamespace();
my $prefix = $opt->{ namespace }->{ $ns }
|| die 'No prefix found for namespace '. $ns;
$xml .= ' type="' . $prefix . ':'
. $self->get_name() . '"' if ($self->get_name() );
}
if (defined $value)
{
$xml .= '>';
$xml .= "$value";
$xml .= '</' . $name . '>' ;
}
else
{
$xml .= '/>';
}
$xml .= "\n" if ($opt->{ readable });
return $xml;
}
sub explain
{
my ($self, $opt, $name ) = @_;
$opt->{ indent } ||= "";
return "$opt->{ indent }'$name' => \$someValue,\n"
}
sub toClass {
warn "# primitive";
}
1;
+1
View File
@@ -7,6 +7,7 @@ use base qw(SOAP::WSDL::Base);
# child elements # child elements
my %type_of :ATTR(:name<type> :default<[]>); my %type_of :ATTR(:name<type> :default<[]>);
my %element_of :ATTR(:name<element> :default<[]>); my %element_of :ATTR(:name<element> :default<[]>);
my %group_of :ATTR(:name<group> :default<[]>);
# attributes # attributes
my %attributeFormDefault_of :ATTR(:name<attributeFormDefault> :default<()>); my %attributeFormDefault_of :ATTR(:name<attributeFormDefault> :default<()>);
+4 -4
View File
@@ -3,11 +3,11 @@ use strict;
use warnings; use warnings;
use Class::Std::Storable; use Class::Std::Storable;
use SOAP::WSDL::XSD::Schema; use SOAP::WSDL::XSD::Schema;
use SOAP::WSDL::XSD::Primitive; use SOAP::WSDL::XSD::Builtin;
use base qw(SOAP::WSDL::XSD::Schema); use base qw(SOAP::WSDL::XSD::Schema);
# all builtin types - add validation (e.g. content restrictions) later... # all builtin types - add validation (e.g. content restrictions) later...
my %PRIMITIVES = ( my %BUILTINS = (
'string' => {}, 'string' => {},
'boolean' => {}, 'boolean' => {},
'decimal' => {}, 'decimal' => {},
@@ -50,9 +50,9 @@ sub START {
my $self = shift; my $self = shift;
my @args = @_; my @args = @_;
while (my ($name, $value) = each %PRIMITIVES ) while (my ($name, $value) = each %BUILTINS )
{ {
$self->push_type( SOAP::WSDL::XSD::Primitive->new({ $self->push_type( SOAP::WSDL::XSD::Builtin->new({
name => $name, name => $name,
targetNamespace => 'http://www.w3.org/2001/XMLSchema', targetNamespace => 'http://www.w3.org/2001/XMLSchema',
} ) } )
+3 -29
View File
@@ -43,8 +43,7 @@ sub set_union {
} }
} }
sub push_enumeration sub push_enumeration {
{
my $self = shift; my $self = shift;
my @attr = @_; my @attr = @_;
my @attributes = @_; my @attributes = @_;
@@ -102,12 +101,8 @@ sub _serialize_single {
sub explain { sub explain {
my ($self, $opt, $name ) = @_; my ($self, $opt, $name ) = @_;
my $perl; $opt->{ indent } = q{} if not defined $opt->{ indent };
$opt->{ indent } ||= ""; return "$opt->{ indent }'$name' => \$someValue,\n"
$perl .= $opt->{ indent } if ($opt->{ readable });
$perl .= q{'} . $name . q{' => $someValue };
$perl .= "\n" if ($opt->{ readable });
return $perl;
} }
sub _check_value { sub _check_value {
@@ -155,25 +150,4 @@ EOT
return $code; return $code;
} }
1; 1;
=pod
=head1 Bugs and limitations
=over
=item * simpleContent, complexContent
These child elements are not implemented yet
=item * union
union simpleType definitions probalbly serialize wrong
=item * explain may produce erroneous results
=back
=cut
+33
View File
@@ -205,8 +205,27 @@ byte integer objects.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::date =head2 SOAP::WSDL::XSD::Typelib::Builtin::date
date values are automatically converted into XML date strings during setting:
YYYY-MM-DD+zz:zz
The time zone is set to the local time zone if not included.
All input variants supported by Date::Parse are supported. You may even pass
in dateTime strings - the time part will be ignored. Note that
set_value is around 100 times slower when setting non-XML-time strings
=head2 SOAP::WSDL::XSD::Typelib::Builtin::dateTime =head2 SOAP::WSDL::XSD::Typelib::Builtin::dateTime
dateTime values are automatically converted into XML dateTime strings during setting:
YYYY-MM-DDThh:mm:ss.nnnnnnn+zz:zz
The optional nanoseconds parts is excluded in converted values, as it would always be 0.
All input variants supported by Date::Parse are supported. Note that
set_value is around 100 times slower when setting non-XML-time strings
=head2 SOAP::WSDL::XSD::Typelib::Builtin::decimal =head2 SOAP::WSDL::XSD::Typelib::Builtin::decimal
decimal is the base of all non-float numbers decimal is the base of all non-float numbers
@@ -237,6 +256,8 @@ decimal is the base of all non-float numbers
=head2 SOAP::WSDL::XSD::Typelib::Builtin::IDREFS =head2 SOAP::WSDL::XSD::Typelib::Builtin::IDREFS
List of SOAP::WSDL::XSD::Typelib::Builtin::IDREF objects.
Derived by SOAP::WSDL::XSD::Typelib::Builtin::list. Derived by SOAP::WSDL::XSD::Typelib::Builtin::list.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::int =head2 SOAP::WSDL::XSD::Typelib::Builtin::int
@@ -273,6 +294,18 @@ Derived by SOAP::WSDL::XSD::Typelib::Builtin::list.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::time =head2 SOAP::WSDL::XSD::Typelib::Builtin::time
time values are automatically converted into XML time strings during setting:
hh:mm:ss.nnnnnnn+zz:zz
hh:mm:ss+zz:zz
The time zone is set to the local time zone if not included. The optional
nanoseconds part is not included in converted values, as it would always be 0.
All input variants supported by Date::Parse are supported. You may even pass
in dateTime strings - the date part will be ignored. Note that
set_value is around 100 times slower when setting non-XML-time strings
=head2 SOAP::WSDL::XSD::Typelib::Builtin::token =head2 SOAP::WSDL::XSD::Typelib::Builtin::token
=head2 SOAP::WSDL::XSD::Typelib::Builtin::unsignedByte =head2 SOAP::WSDL::XSD::Typelib::Builtin::unsignedByte
@@ -29,6 +29,13 @@ sub as_bool :BOOLIFY {
return $value_of { ident $_[0] }; return $value_of { ident $_[0] };
} }
sub _get_handlers {
my $parser = $_[1];
return {
Char => $parser->characters(),
}
}
Class::Std::initialize(); # make :BOOLIFY overloading serializable Class::Std::initialize(); # make :BOOLIFY overloading serializable
+3 -2
View File
@@ -1,6 +1,7 @@
package SOAP::WSDL::XSD::Typelib::Builtin::boolean; package SOAP::WSDL::XSD::Typelib::Builtin::boolean;
use strict; use strict;
use warnings; use warnings;
use Class::Std::Storable;
my %pattern_of :ATTR(:name<pattern> :default<()>); my %pattern_of :ATTR(:name<pattern> :default<()>);
my %whiteSpace_of :ATTR(:name<whiteSpace> :default<()>); my %whiteSpace_of :ATTR(:name<whiteSpace> :default<()>);
@@ -9,7 +10,7 @@ my %value_of :ATTR(:get<value> :init_attr<value> :default<()>);
# Speed up. Class::Std::new is slow - and we don't need it's functionality... # Speed up. Class::Std::new is slow - and we don't need it's functionality...
BEGIN { BEGIN {
use Class::Std::Storable; # use Class::Std::Storable;
use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType); use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType);
no warnings qw(redefine); no warnings qw(redefine);
@@ -40,7 +41,7 @@ sub serialize {
, $self->end_tag($opt); , $self->end_tag($opt);
} }
sub as_num :NUMERIFY { sub as_num :NUMERIFY :BOOLIFY {
return $_[0]->get_value(); return $_[0]->get_value();
} }
+32
View File
@@ -2,6 +2,9 @@ package SOAP::WSDL::XSD::Typelib::Builtin::date;
use strict; use strict;
use warnings; use warnings;
use Date::Parse;
use Date::Format;
my %pattern_of :ATTR(:name<pattern> :default<()>); my %pattern_of :ATTR(:name<pattern> :default<()>);
my %enumeration_of :ATTR(:name<enumeration> :default<()>); my %enumeration_of :ATTR(:name<enumeration> :default<()>);
my %whiteSpace_of :ATTR(:name<whiteSpace> :default<()>); my %whiteSpace_of :ATTR(:name<whiteSpace> :default<()>);
@@ -31,5 +34,34 @@ BEGIN {
} }
sub set_value {
# use set_value from base class if we have a XML-DateTime format
#2037-12-31+01:00
if (
$_[1] =~ m{ ^\d{4} \- \d{2} \- \d{2}
(:? [\+\-] \d{2} \: \d{2} )?$
}xms
) {
$_[0]->SUPER::set_value($_[1])
}
# use a combination of strptime and strftime for converting the date
# Unfortunately, strftime outputs the time zone as [+-]0000, whereas XML
# whants it as [+-]00:00
# We know that the latter part of the TZ is always :00 (there's no time
# zone whith minute offset yet), so we just use substr to get the part
# up to the last 2 timezone digits and append :00
# We leave out the optional nanoseconds part, as it would always be empty.
else {
# strptime sets empty values to undef - and strftime doesn't like that...
my @time_from = map { ! defined $_ ? 0 : $_ } strptime($_[1]);
# use Data::Dumper;
# die Dumper \@time_from;
my $time_str = strftime( '%Y-%m-%d%z', @time_from );
substr $time_str, -2, 0, ':';
$_[0]->SUPER::set_value($time_str);
}
}
1; 1;
+29 -1
View File
@@ -3,6 +3,8 @@ use strict;
use warnings; use warnings;
use Class::Std::Storable; use Class::Std::Storable;
use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType); use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType);
use Date::Parse;
use Date::Format;
my %pattern_of :ATTR(:name<pattern> :default<()>); my %pattern_of :ATTR(:name<pattern> :default<()>);
my %enumeration_of :ATTR(:name<enumeration> :default<()>); my %enumeration_of :ATTR(:name<enumeration> :default<()>);
@@ -30,8 +32,34 @@ BEGIN {
} }
return $self; return $self;
}; };
} }
sub set_value {
# use set_value from base class if we have a XML-DateTime format
#2037-12-31T00:00:00.0000000+01:00
if (
$_[1] =~ m{ ^\d{4} \- \d{2} \- \d{2}
T \d{2} \: \d{2} \: \d{2} (:? \. \d{1,7} )?
[\+\-] \d{2} \: \d{2} $
}xms
) {
$_[0]->SUPER::set_value($_[1])
}
# use a combination of strptime and strftime for converting the date
# strptime does not emit timezone info, so we're pretty fucked up here.
#
# Unfortunately, strftime outputs the time zone as [+-]0000, whereas XML
# whants it as [+-]00:00
# We leave out the optional nanoseconds part, as it would always be empty.
else {
# strptime sets empty values to undef - and strftime doesn't like that...
my @time_from = map { ! defined $_ ? 0 : $_ } strptime($_[1]);
undef $time_from[-1];
my $time_str = strftime( '%Y-%m-%dT%H:%M:%S%z', @time_from );
substr $time_str, -2, 0, ':';
$_[0]->SUPER::set_value($time_str);
}
}
1; 1;
+28
View File
@@ -1,6 +1,8 @@
package SOAP::WSDL::XSD::Typelib::Builtin::time; package SOAP::WSDL::XSD::Typelib::Builtin::time;
use strict; use strict;
use warnings; use warnings;
use Date::Parse;
use Date::Format;
my %pattern_of :ATTR(:name<pattern> :default<()>); my %pattern_of :ATTR(:name<pattern> :default<()>);
my %enumeration_of :ATTR(:name<enumeration> :default<()>); my %enumeration_of :ATTR(:name<enumeration> :default<()>);
@@ -30,4 +32,30 @@ BEGIN {
}; };
} }
sub set_value {
# use set_value from base class if we have a XML-Time format
# 00:00:00.0000000+01:00
if (
$_[1] =~ m{ ^ \d{2} \: \d{2} \: \d{2} (:? \. \d{1,7} )?
[\+\-] \d{2} \: \d{2} $
}xms
) {
$_[0]->SUPER::set_value($_[1])
}
# use a combination of strptime and strftime for converting the date
# Unfortunately, strftime outputs the time zone as [+-]0000, whereas XML
# whants it as [+-]00:00
# We leave out the optional nanoseconds part, as it would always be empty.
else {
# strptime sets empty values to undef - and strftime doesn't like that...
# we even need to set it to 1 to prevent a "Day '0' out of range 1..31" warning...
my @time_from = map { ! defined $_ ? 1 : $_ } strptime($_[1]);
my $time_str = strftime( '%H:%M:%S%z', @time_from );
substr $time_str, -2, 0, ':';
$_[0]->SUPER::set_value($time_str);
}
}
1; 1;
@@ -22,26 +22,3 @@ BEGIN {
}; };
} }
1; 1;
__END__
=pod
=head1 NAME
SOAP::WSDL::XSD::Typelib::Builtin::unsignedLong - unsigned long integer objects
=head1 DESCRIPTION
Subclass of nonNegativeInteger.
=head1 LICENSE
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
+153 -36
View File
@@ -1,11 +1,11 @@
#!/usr/bin/perl #!/usr/bin/perl
package SOAP::WSDL::XSD::Typelib::ComplexType; package SOAP::WSDL::XSD::Typelib::ComplexType;
use strict; use strict;
use warnings;
use Carp; use Carp;
use SOAP::WSDL::XSD::Typelib::Builtin; use SOAP::WSDL::XSD::Typelib::Builtin;
use Scalar::Util qw(blessed); use Scalar::Util qw(blessed);
use Class::Std::Storable; use Class::Std::Storable;
use Data::Dumper; use Data::Dumper;
use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anyType); use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anyType);
@@ -14,6 +14,32 @@ my %ELEMENTS_FROM;
my %ATTRIBUTES_OF; my %ATTRIBUTES_OF;
my %CLASSES_OF; my %CLASSES_OF;
# STORABLE_ methods for supporting Class::Std::Storable.
# We could also handle them via AUTOMETHOD,
# but AUTOMETHOD should always croak...
sub STORABLE_freeze_pre {
}
sub STORABLE_freeze_post {
}
sub STORABLE_thaw_pre {
}
sub STORABLE_thaw_post {
}
# for error reporting. Eases working with data objects...
sub AUTOMETHOD {
my ($self, $ident, @args_from) = @_;
my $class = ref $self || $self;
confess "Can't locate object method \"$_\" via package \"$class\". \n"
. "Valid methods are: "
. join(', ', map { ("get_$_" , "set_$_") } keys %{ $ATTRIBUTES_OF{ $class } })
. "\n"
}
# we store per-class elements. # we store per-class elements.
# call as __PACKAGE__->_factory # call as __PACKAGE__->_factory
sub _factory { sub _factory {
@@ -29,70 +55,88 @@ sub _factory {
my $type = $CLASSES_OF{ $class }->{ $name } my $type = $CLASSES_OF{ $class }->{ $name }
or die "No class given for $name"; or die "No class given for $name";
# require all types here
$type->isa('UNIVERSAL') $type->isa('UNIVERSAL')
or eval "require $type" or eval "require $type"
or croak $@; or croak $@;
# check now, so we don't need to do it later...
my $is_list = $type->isa('SOAP::WSDL::XSD::Typelib::Builtin::list');
*{ "$class\::set_$name" } = sub { *{ "$class\::set_$name" } = sub {
my ($self, $value) = @_; my ($self, $value) = @_;
# The structure below looks rather weird, but is optimized for performance.
#
# We could use sub calls for sure, but these are much slower. And the logic
# is not that easy:
#
# we accept: # we accept:
# a) objects # a) objects
# b) scalars # b) scalars
# c) list refs # c) list refs
# d) hash refs # d) hash refs
# e) mixed stuff of all of the above, so we have to # e) mixed stuff of all of the above, so we have to set our element to
# set our element to
# a) value if it's an object # a) value if it's an object
# b) New object with value for simple values # b) New object of expected class with value for simple values
# c 1) New object with value for list values and list type # c 1) New object with value for list values and list type
# c 2) List ref of new objects with value for list values and non-list type # c 2) List ref of new objects with value for list values and non-list type
# c + e) List ref of objects for list values (list of objects) and non-list type # c + e 1) List ref of objects for list values (list of objects) and non-list type
# c + e 2) List ref of new objects for list values (list of hashes) and non-list type
# where the hash ref is passed to new as argument
# d) New object with values passed to new for HASH references # d) New object with values passed to new for HASH references
# #
# Die on non-ARRAY/HASH references - if you can define semantics # We throw an error on
# a) list refs of list refs - don't know what to do with this (maybe use for lists of list types ?)
# b) wrong object types
# c) non-blessed non-ARRAY/HASH references - if you can define semantics
# for GLOB references, feel free to add them. # for GLOB references, feel free to add them.
$attribute_ref->{ ident $self } = blessed $value # d) we should also die for non-blessed non-ARRAY/HASH references in lists but don't do yet - oh my !
? $value
: ref $value my $is_ref = ref $value;
? ref $value eq 'ARRAY' $attribute_ref->{ ident $self } = ($is_ref)
? $type->isa('SOAP::WSDL::XSD::Typelib::Builtin::list') ? $is_ref eq 'ARRAY'
? $type->new({ value => $value }) ? $is_list # remembered from outside closure
? $type->new({ value => $value }) # list element - can take list ref as value
: [ map { : [ map {
blessed($_) ref $_
? ($_->isa('SOAP::WSDL::XSD::Typelib::Builtin::anyType')) ? ref $_ eq 'HASH'
? $type->new($_)
: ref $_ eq $type
? $_ ? $_
: croak 'cannot use non-XSD object as value' : croak "cannot use " . ref($_) . " reference as value for $name - $type required"
: $type->new({ value => $_ }) : $type->new({ value => $_ })
} @{ $value } } @{ $value }
] ]
: ref $value eq 'HASH' : $is_ref eq 'HASH'
? $type->new( $value ) ? $type->new( $value )
: die 'Cannot use non-ARRAY/HASH as data' : $is_ref eq $type
? $value
: die croak "cannot use $is_ref reference as value for $name - $type required"
: $type->new({ value => $value }); : $type->new({ value => $value });
}; };
*{ "$class\::add_$name" } = sub { *{ "$class\::add_$name" } = sub {
my ($self, $value) = @_; my $ident = ident $_[0];
my $ident = ident $self; warn "attempting to add empty value to " . ref $_[0]
if (not defined $value) { if (not defined $_[1]);
warn "attempting to add empty value to " . ref $self;
}
return $attribute_ref->{ $ident } = $value # first call
return $attribute_ref->{ $ident } = $_[1]
if not defined $attribute_ref->{ $ident }; if not defined $attribute_ref->{ $ident };
# listify previous value if it's no list # second call: listify previous value if it's no list
$attribute_ref->{ $ident } = [ $attribute_ref->{ $ident } ] $attribute_ref->{ $ident } = [ $attribute_ref->{ $ident } ]
if not ref $attribute_ref->{ $ident } eq 'ARRAY'; if not ref $attribute_ref->{ $ident } eq 'ARRAY';
# add to list # second and following: add to list
return push @{ $attribute_ref->{ $ident } }, $value; return push @{ $attribute_ref->{ $ident } }, $_[1];
}; };
}
*{ "$class\::START" } = sub { *{ "$class\::START" } = sub {
my ($self, $ident, $args_of) = @_; my ($self, $ident, $args_of) = @_;
# iterate over keys of arguments # iterate over keys of arguments
# and call set appropriate field in clase # and call set appropriate field in clase
map { ($ATTRIBUTES_OF{ $class }->{ $_ }) map { ($ATTRIBUTES_OF{ $class }->{ $_ })
@@ -105,30 +149,28 @@ sub _factory {
}xms }xms
? do {} ? do {}
: do { use Data::Dumper; : do { use Data::Dumper;
croak "unknown field $_ in $class. Valid fields are " croak "unknown field $_ in $class. Valid fields are:\n"
. join(', ', @{ $ELEMENTS_FROM{ $class } }) . "\n" . join(', ', @{ $ELEMENTS_FROM{ $class } }) . "\n"
. Dumper @_ }; . "Structure given:\n" . Dumper @_ };
# TODO maybe only warn for unknown fields ?
} keys %$args_of; } keys %$args_of;
return $self;
}; };
# this serialize method works fine for <all> and <sequence> # this serialize method works fine for <all> and <sequence>
# complextypes, as well as for <restriction><all> or # complextypes, as well as for <restriction><all> or
# <restriction><sequence>. # <restriction><sequence>.
# But what about choice, group, extension ? # But what about choice, extension ?
#
}
*{ "$class\::_serialize" } = sub { *{ "$class\::_serialize" } = sub {
my $ident = ident $_[0]; my $ident = ident $_[0];
# my $class = ref $_[0]; # my $class = ref $_[0];
# return concatenated return value of serialize call of all # return concatenated return value of serialize call of all
# elements retrieved from get_elements expanding list refs. # elements retrieved from get_elements expanding list refs.
# get_elements is inlined for performance. # get_elements is inlined for performance.
return join q{} , map { return join q{} , map {
my $element = $ATTRIBUTES_OF{ $class }->{ $_ }->{ $ident }; my $element = $ATTRIBUTES_OF{ $class }->{ $_ }->{ $ident };
# do we have some content
if (defined $element) { if (defined $element) {
$element = [ $element ] $element = [ $element ]
if not ref $element eq 'ARRAY'; if not ref $element eq 'ARRAY';
@@ -176,7 +218,82 @@ __END__
=head1 NAME =head1 NAME
SOAP::WSDL::XSD::Typelib::ComplexType - ComplexType XML Schema definitions SOAP::WSDL::XSD::Typelib::ComplexType - complexType base class
=head1 Subclassing
package MyComplexType;
use Class::Std::Storable
use base qw(SOAP::WSDL::XSD::Typelib::ComplexType);
__PACKAGE__->_factory(
\@elements_from,
\%attributes_of,
\%classes_of
);
When subclassing, the following methods are created in the subclass:
=head2 new
Constructor. For your convenience, new will accept data for the object's
properties in the following forms:
hash refs
1) of scalars
2) of list refs
3) of hash refs
4) of objects
5) mixed stuff of all of the above
new() will set the data via the set_FOO methods to the object's element
properties.
Data passed to new must comply to the object's structure or new() will
complain. Objects passed must be of the expected type, or new() will
complain, too.
Examples:
my $obj = MyClass->new({ MyName => $value });
my $obj = MyClass->new({
MyName => {
DeepName => $value
},
MySecondName => $value,
});
my $obj = MyClass->new({
MyName => [
{ DeepName => $value },
{ DeepName => $other_value },
],
MySecondName => $object,
MyThirdName => [ $object1, $object2 ],
});
To be correct, SOAP::WSDL::XSD::Typelib::ComplexType will create a START
method, not new() - but new() will be created from Class::Std::Storable and
behave like stated above.
=head2 set_FOO
A mutator method for every element property.
For your convenience, the set_FOO methods will accept all kind of data you
can think of (and all combinations of them) as input - with the exception
of GLOBS and filehandles.
This means you may set element properties by passing
a) objects
b) scalars
c) list refs
d) hash refs
e) mixed stuff of all of the above
Examples are similar to the examples provided for new() above.
=head1 Bugs and limitations =head1 Bugs and limitations
+45 -1
View File
@@ -64,26 +64,70 @@ sub end_tag {
=pod =pod
=head1 NAME
SOAP::WSDL::XSD::Typelib::Element - element base clase
=head1 SYNOPSIS =head1 SYNOPSIS
This example creates a class for this XML schema definition:
<element name="MyElement" type="xsd:string" nillable="1"
minOccurs="1" maxOccurs="1"/>
package MyElement; package MyElement;
use strict; use strict;
use Class::Std::Storable; use Class::Std::Storable;
use base ( use base (
'SOAP::WSDL::XSD::Typelib::Element', 'SOAP::WSDL::XSD::Typelib::Element',
'SOAP::WSDL::XSD::Typelib::Builtin::string',
); );
__PACKAGE__->__set_name('MyElementName'); __PACKAGE__->__set_name('MyElementName');
__PACKAGE__->__set_nillable(1); __PACKAGE__->__set_nillable(1);
__PACKAGE__->__set_minOccurs(1); __PACKAGE__->__set_minOccurs(1);
__PACKAGE__->__set_maxOccurs(1); __PACKAGE__->__set_maxOccurs(1);
__PACKAGE__->__set_ref(0);
Now we create this XML schema definition type class:
<element name="MyElement2" ref="tns:MyElement"/>
package MyElement2;
use strict;
use Class::Std::Storable;
use base (
'SOAP::WSDL::XSD::Typelib::Element',
'MyElement'
);
__PACKAGE__->__set_name('MyElementName');
__PACKAGE__->__set_nillable(0);
__PACKAGE__->__set_ref(1); __PACKAGE__->__set_ref(1);
=head1 NOTES
=over
=item * type="Foo"
Implemented via inheritance.
=item * ref="Foo"
Implemented via inheritance, too. Calling
__PACKAGE__->__set_ref(1) is highly encouraged, though it has no
effect yet - it will probably be needed for serialization to XML
Schema definitions some day.
=back
=head1 BUGS AND LIMITATIONS =head1 BUGS AND LIMITATIONS
=over =over
=item * minOccurs maxOccurs ref not implemented =item * minOccurs maxOccurs not implemented
These attributes are not yet supported, though they may be set as class These attributes are not yet supported, though they may be set as class
properties via __PACKAGE__->__set_FOO methods. properties via __PACKAGE__->__set_FOO methods.
+1 -1
View File
@@ -17,7 +17,7 @@ __END__
=head1 NAME =head1 NAME
SOAP::WSDL::XSD::Typelib::SimpleType - simple type base class SOAP::WSDL::XSD::Typelib::SimpleType - simpleType base class
=head1 DESCRIPTION =head1 DESCRIPTION
+1 -2
View File
@@ -15,8 +15,7 @@ my @modules = qw(
SOAP::WSDL::Port SOAP::WSDL::Port
SOAP::WSDL::PortType SOAP::WSDL::PortType
SOAP::WSDL::Types SOAP::WSDL::Types
SOAP::WSDL::SAX::WSDLHandler SOAP::WSDL::XSD::Builtin
SOAP::WSDL::XSD::Primitive
SOAP::WSDL::XSD::ComplexType SOAP::WSDL::XSD::ComplexType
SOAP::WSDL::XSD::SimpleType SOAP::WSDL::XSD::SimpleType
SOAP::WSDL::XSD::Element SOAP::WSDL::XSD::Element
+333
View File
@@ -0,0 +1,333 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More tests => 18; # qw/no_plan/; # TODO: change to tests => N;
use lib '../lib';
use XML::LibXML;
eval {
require Test::XML;
import Test::XML;
};
use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(
), "Object creation");
my $parser = XML::LibXML->new();
$parser->set_handler( $filter );
$parser->parse_string( xml() );
my $wsdl;
ok( $wsdl = $filter->get_data() , "get object tree");
my $types = $wsdl->first_types();
is $types->get_parent(), $wsdl , 'types parent';
my $serializer_options = {
readable => 1,
autotype => 1,
namespace => { 'urn:myNamespace' => 'tns',
"http://www.w3.org/2001/XMLSchema" => 'xsd' },
typelib => $wsdl->first_types(),
indent => "\t",
};
my $xml;
my $type = $types->find_type( 'urn:myNamespace', 'testSimpleType1' );
ok($xml = $type->serialize( 'test', 1 , $serializer_options ),
"serialize simple Type"
);
# print $xml;
SKIP: {
skip_without_test_xml();
is_xml( $xml, '<test type="tns:testSimpleType1">1</test>',
"content compare" );
};
$type = $types->find_type( 'urn:myNamespace', 'testSimpleList' );
ok($xml = $type->serialize( 'testList', [ 1, 2, 3 ] , $serializer_options ),
"serialize simple list type"
);
SKIP: {
skip_without_test_xml();
is_xml( $xml, '<testList type="tns:testSimpleList">1 2 3</testList>',
"content compare" );
};
$type = $types->find_element( 'urn:myNamespace', 'TestElement' );
ok($xml = $type->serialize( undef, 1 , $serializer_options ),
"serialize simple element");
SKIP: {
skip_without_test_xml();
is_xml( $xml, '<TestElement type="xsd:int">1</TestElement>',
"content compare" );
};
ok( $xml = $types->find_type( 'urn:myNamespace', 'length3')->serialize(
'TestComplex', { size => -13, unit => 'BLA' } ,
$serializer_options
),
"serialize complex type");
SKIP: {
skip_without_test_xml();
is_xml( $xml, q{
<TestComplex type="tns:length3">
<size type="xsd:non-positive-integer">-13</size>
<unit type="xsd:NMTOKEN">BLA</unit>
</TestComplex>},
"content compare" );
};
ok($xml = $types->find_element( 'urn:myNamespace', 'TestElementComplexType')
->serialize(
undef, { size => -13, unit => 'BLA' } , $serializer_options ),
"serialize element with complex type"
);
SKIP: {
skip_without_test_xml();
is_xml( $xml, q{
<TestElementComplexType type="tns:length3">
<size type="xsd:non-positive-integer">-13</size>
<unit type="xsd:NMTOKEN">BLA</unit>
</TestElementComplexType>
},
"content compare" );
};
ok($xml = $types->find_type( 'urn:myNamespace', 'complex')->serialize(
'complexComplex',
{ 'length' => { size => -13, unit => 'BLA' }, 'int' => 1 },
$serializer_options ),
"serialize complex type with complex content"
);
SKIP: {
skip_without_test_xml();
is_xml( $xml, q{
<complexComplex type="tns:complex">
<length type="tns:length3">
<size type="xsd:non-positive-integer">-13</size>
<unit type="xsd:NMTOKEN">BLA</unit>
</length>
<int type="xsd:int">1</int>
</complexComplex>
},
"content compare" );
}
ok($xml = $wsdl->find_message('urn:myNamespace', 'testRequest')
->get_part()->[0]->serialize(
undef,
{ test => { length => { size => -13, unit => 'BLA' } , int => 3 } },
$serializer_options ),
"serialize part"
);
SKIP: {
skip_without_test_xml();
is_xml( $xml, q{
<test type="tns:complex">
<length type="tns:length3">
<size type="xsd:non-positive-integer">-13</size>
<unit type="xsd:NMTOKEN">BLA</unit>
</length>
<int type="xsd:int">3</int>
</test>
},
"content compare")
};
my $opt = {
typelib => $types,
readable => 1,
autotype => 0,
namespace => { 'urn:myNamespace' => 'tns',
'http://www.w3.org/2001/XMLSchema' => 'xsd',
'http://schemas.xmlsoap.org/wsdl/' => 'wsdl',
},
indent => "",
wsdl => $wsdl,
};
# ok $wsdl->explain($opt) =~ m/#optional/m;
sub skip_without_test_xml {
skip("Test::XML not available", 1) if (not $Test::XML::VERSION);
}
sub xml
{
return q{<?xml version="1.0"?>
<definitions name="simpleType"
targetNamespace="urn:myNamespace"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="urn:myNamespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
>
<types>
<xsd:schema targetNamespace="urn:myNamespace">
<xsd:complexType name="length3">
<xsd:all>
<xsd:element name="size" type="xsd:non-positive-integer"/>
<xsd:element name="unit" type="xsd:NMTOKEN"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="complex">
<xsd:sequence>
<xsd:element name="length" type="tns:length3"/>
<xsd:element name="int" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="TestElement" type="xsd:int"/>
<xsd:element name="TestElementComplexType" type="tns:length3"/>
<xsd:simpleType name="testSimpleType1">
<xsd:restriction base="int">
<xsd:enumeration value="1"/>
<xsd:enumeration value="2"/>
<xsd:enumeration value="3"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="testSimpleList">
<xsd:annotation>
<xsd:documentation>
SimpleType Test
</xsd:documentation>
</xsd:annotation>
<xsd:list itemType="int">
</xsd:list>
</xsd:simpleType>
<xsd:simpleType name="testSimpleUnion">
<xsd:annotation>
<xsd:documentation>
SimpleType Union test
</xsd:documentation>
</xsd:annotation>
<xsd:union memberTypes="int float">
</xsd:union>
</xsd:simpleType>
</xsd:schema>
</types>
<message name="testRequest">
<part name="test" type="tns:complex"/>
</message>
<message name="testResponse">
<part name="test" type="tns:testSimpleType1"/>
</message>
<message name="testRequest2">
<part name="test" type="tns:testSimpleType1"/>
</message>
<message name="testResponse2">
<part name="test" type="tns:testSimpleType1"/>
</message>
<portType name="testPort">
<operation name="test">
<documentation>
Test-Methode
</documentation>
<input message="tns:testRequest"/>
<output message="tns:testResponse"/>
</operation>
<operation name="test2">
<documentation>
Test-Methode
</documentation>
<input message="tns:testRequest2"/>
<output message="tns:testResponse2"/>
</operation>
</portType>
<portType name="testPort2">
<operation name="test">
<documentation>
Test-Methode
</documentation>
<input message="tns:testRequest"/>
<output message="tns:testResponse"/>
</operation>
</portType>
<portType name="testPort3">
<operation name="test">
<documentation>
Test-Methode
</documentation>
<input message="tns:testRequest"/>
<output message="tns:testResponse"/>
</operation>
</portType>
<binding type="tns:testPort" name="testBinding">
<operation name="test">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<soap:operation soapAction="test">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</operation>
</binding>
<binding type="tns:testPort2" name="testBinding2">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="test">
<soap:operation soapAction="test">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</operation>
</binding>
<binding type="tns:testPort3" name="testBinding3">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="test">
<soap:operation soapAction="test">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</operation>
</binding>
<service name="testService">
<port name="testPort" binding="tns:testBinding">
<soap:address location="http://127.0.0.1/testPort" />
</port>
<port name="testPort2" binding="tns:testBinding2">
<soap:address location="http://127.0.0.1/testPort2" />
</port>
</service>
<service name="testService2">
<port name="testPort3" binding="tns:testBinding3">
<soap:address location="http://127.0.0.1/testPort3" />
</port>
</service>
</definitions>
};
}
+11 -7
View File
@@ -1,9 +1,15 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 18; # qw/no_plan/; # TODO: change to tests => N; use Test::More;
use lib '../lib'; use lib '../lib';
use XML::SAX::ParserFactory;
if (eval "require XML::LibXML") {
plan tests => 18;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
eval { eval {
require Test::XML; require Test::XML;
@@ -15,12 +21,10 @@ use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
my $filter; my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new( ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(
{ base => 'XML::SAX::Base' }
), "Object creation"); ), "Object creation");
my $parser = XML::SAX::ParserFactory->parser( my $parser = XML::LibXML->new();
Handler => $filter $parser->set_handler( $filter );
);
$parser->parse_string( xml() ); $parser->parse_string( xml() );
@@ -174,7 +178,7 @@ sub xml
targetNamespace="urn:myNamespace" targetNamespace="urn:myNamespace"
xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="urn:myNamespace" xmlns:tns="urn:myNamespace"
xmlns:xsd="http://www.w3c.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
> >
+9 -3
View File
@@ -1,7 +1,13 @@
use Test::More tests => 11; use Test::More;
use Data::Dumper;
use lib '../lib'; use lib '../lib';
use XML::LibXML;
if (eval "require XML::LibXML") {
plan tests => 11;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/); use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
+256
View File
@@ -0,0 +1,256 @@
use Test::More tests => 11;
use Data::Dumper;
use lib '../lib';
use XML::LibXML;
use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
my $parser = XML::LibXML->new();
$parser->set_handler( $filter );
eval { $parser->parse_string( xml() ) };
if ($@)
{
fail("parsing WSDL");
die "Can't test without parsed WSDL";
}
else
{
pass("parsing XML");
}
my $wsdl;
ok( $wsdl = $filter->get_data() , "get object tree");
my $schema = $wsdl->first_types();
my $opt = {
readable => 0,
autotype => 1,
namespace => $wsdl->get_xmlns(),
indent => "\t",
typelib => $schema,
};
is( $schema->find_type( 'myNamespace', 'testSimpleType1' )->serialize(
'test', 1 , $opt ),
q{<test type="tns:testSimpleType1">1</test>} , "serialize simple type");
is( $schema->find_type( 'myNamespace', 'testSimpleList' )->serialize(
'testList', [ 1, 2, 3 ] , $opt),
q{<testList type="tns:testSimpleList">1 2 3</testList>},
"serialize simple list type"
);
is( $schema->find_element( 'myNamespace', 'TestElement' )->serialize(
undef, 1 , $opt),
q{<TestElement type="xsd:int">1</TestElement>}, "Serialize element"
);
$opt->{ readable } = 0;
is( $schema->find_type( 'myNamespace', 'length3')->serialize(
'TestComplex', { size => -13, unit => 'BLA' } ,
$opt ),
q{<TestComplex type="tns:length3" >}
. q{<size type="xsd:non-positive-integer">-13</size>}
. q{<unit type="xsd:NMTOKEN">BLA</unit></TestComplex>}
, "serialize complex type" );
is( $schema->find_element( 'myNamespace', 'TestElementComplexType')->serialize(
undef, { size => -13, unit => 'BLA' } ,
$opt ),
q{<TestElementComplexType type="tns:length3" >}
. q{<size type="xsd:non-positive-integer">-13</size>}
. q{<unit type="xsd:NMTOKEN">BLA</unit></TestElementComplexType>},
"element with complex type"
);
is( $schema->find_type( 'myNamespace', 'complex')->serialize(
'complexComplex',
{ 'length' => { size => -13, unit => 'BLA' }, 'int' => 1 },
$opt ),
q{<complexComplex type="tns:complex" >}
. q{<length type="tns:length3" >}
. q{<size type="xsd:non-positive-integer">-13</size>}
. q{<unit type="xsd:NMTOKEN">BLA</unit></length>}
. q{<int type="xsd:int">1</int></complexComplex>},
"nested complex type"
);
is( $wsdl->find_message('myNamespace', 'testRequest')->first_part()->serialize(
undef, { test => { length => { size => -13, unit => 'BLA' } , int => 3 } },
$opt ),
q{<test type="tns:complex" >}
. q{<length type="tns:length3" >}
. q{<size type="xsd:non-positive-integer">-13</size>}
. q{<unit type="xsd:NMTOKEN">BLA</unit>}
. q{</length><int type="xsd:int">3</int></test>}
, "Message part"
);
exit;
sub xml
{
return q{<?xml version="1.0"?>
<definitions name="simpleType"
targetNamespace="myNamespace"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="myNamespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
>
<types>
<xsd:schema targetNamespace="myNamespace">
<xsd:complexType name="length3">
<xsd:sequence>
<xsd:element name="size" type="xsd:non-positive-integer"/>
<xsd:element name="unit" type="xsd:NMTOKEN"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="complex">
<xsd:sequence>
<xsd:element name="length" type="tns:length3"/>
<xsd:element name="int" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="TestElement" type="xsd:int"/>
<xsd:element name="TestElementComplexType" type="tns:length3"/>
<xsd:simpleType name="testSimpleType1">
<xsd:restriction base="int">
<xsd:enumeration value="1"/>
<xsd:enumeration value="2"/>
<xsd:enumeration value="3"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="testSimpleList">
<xsd:annotation>
<xsd:documentation>
SimpleType Test
</xsd:documentation>
</xsd:annotation>
<xsd:list itemType="int">
</xsd:list>
</xsd:simpleType>
<xsd:simpleType name="testSimpleUnion">
<xsd:annotation>
<xsd:documentation>
SimpleType Union test
</xsd:documentation>
</xsd:annotation>
<xsd:union memberTypes="int float">
</xsd:union>
</xsd:simpleType>
</xsd:schema>
</types>
<message name="testRequest">
<part name="test" type="tns:complex"/>
</message>
<message name="testResponse">
<part name="test" type="tns:testSimpleType1"/>
</message>
<message name="testRequest2">
<part name="test" type="tns:testSimpleType1"/>
</message>
<message name="testResponse2">
<part name="test" type="tns:testSimpleType1"/>
</message>
<portType name="testPort">
<operation name="test">
<documentation>
Test-Methode
</documentation>
<input message="testRequest"/>
<output message="testResponse"/>
</operation>
<operation name="test2">
<documentation>
Test-Methode
</documentation>
<input message="testRequest2"/>
<output message="testResponse2"/>
</operation>
</portType>
<portType name="testPort2">
<operation name="test">
<documentation>
Test-Methode
</documentation>
<input message="testRequest"/>
<output message="testResponse"/>
</operation>
</portType>
<portType name="testPort3">
<operation name="test">
<documentation>
Test-Methode
</documentation>
<input message="testRequest"/>
<output message="testResponse"/>
</operation>
</portType>
<binding type="testPort" name="testBinding">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<soap:operation soapAction="test">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</binding>
<binding type="testPort2" name="testBinding2">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<soap:operation soapAction="test">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</binding>
<binding type="testPort3" name="testBinding3">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<soap:operation soapAction="test">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</binding>
<service name="testService">
<port name="testPort" binding="testBinding">
<soap:address location="http://127.0.0.1/testPort" />
</port>
<port name="testPort2" binding="testBinding2">
<soap:address location="http://127.0.0.1/testPort2" />
</port>
<port name="testPort3" binding="testBinding3">
<soap:address location="http://127.0.0.1/testPort3" />
</port>
</service>
</definitions>
};
}
+403
View File
@@ -0,0 +1,403 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More tests => 5;
use lib '../lib';
use XML::LibXML;
eval {
require Test::XML;
import Test::XML;
};
use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
my $parser = XML::LibXML->new();
$parser->set_handler( $filter );
eval { $parser->parse_string( xml() ) };
if ($@)
{
fail("parsing WSDL");
die "Can't test without parsed WSDL: $@";
}
else
{
pass("parsing XML");
}
my $wsdl;
ok( $wsdl = $filter->get_data() , "get object tree");
my $schema = $wsdl->get_types()->[0]->get_schema()->[0] || die "No schema !";
my $opt = {
typelib => $wsdl->first_types,
readable => 1,
autotype => 0,
namespace => { 'http://www.example.org/MessageGateway2/' => 'tns',
'http://www.w3.org/2001/XMLSchema' => 'xsd',
'http://schemas.xmlsoap.org/wsdl/' => 'wsdl',
},
indent => "",
};
my $data = { EnqueueMessage => {
MMessage => {
MRecipientURI => 'anyURI',
MSenderAddress => 'a string',
MMessageContent => 'a string',
MSubject => 'a string',
MDeliveryReportRecipientURI => 'anyURI',
MKeepalive => {
MKeepaliveTimeout => 1234567,
MKeepaliveErrorPolicy => ' ( suppress | report ) ',
}
}
}
};
SKIP: { skip_without_test_xml();
is_xml( $wsdl->find_message(
"http://www.example.org/MessageGateway2/" ,'EnqueueMessageRequest'
)->first_part()->serialize( 'test', $data, $opt ),
xml_message()
, "Serialized message part"
);
}
sub skip_without_test_xml {
skip("Test::XML not available", 1) if (not $Test::XML::VERSION);
}
sub xml_message {
return
q{<EnqueueMessage xmlns="http://www.example.org/MessageGateway2/">
<MMessage>
<MRecipientURI>anyURI</MRecipientURI>
<MSenderAddress>a string</MSenderAddress>
<MMessageContent>a string</MMessageContent>
<MSubject>a string</MSubject>
<MDeliveryReportRecipientURI>anyURI</MDeliveryReportRecipientURI>
<MKeepalive>
<MKeepaliveTimeout>1234567</MKeepaliveTimeout>
<MKeepaliveErrorPolicy> ( suppress | report ) </MKeepaliveErrorPolicy>
</MKeepalive>
</MMessage>
</EnqueueMessage>
};
}
sub xml {
return q{<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="MessageGateway"
targetNamespace="http://www.example.org/MessageGateway2/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.example.org/MessageGateway2/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/MessageGateway2/">
<xsd:element name="EnqueueMessage" type="tns:TEnqueueMessage"
xmlns:tns="http://www.example.org/MessageGateway2/">
<xsd:annotation>
<xsd:documentation>Enqueue message request element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="TMessage">
<xsd:annotation>
<xsd:documentation>
A type containing all elements of a message to enqueue.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MRecipientURI" type="xsd:anyURI" minOccurs="1"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The recipient in URI notaitions. Valid URI schemas are: mailto:, sms:,
phone:. Not all URI schemas need to be implemented at the current
implementation stage.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MSenderAddress" type="xsd:string" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
E-Mail sender address. Ignored for all but mailto: recipient URIs.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MMessageContent" type="xsd:string" minOccurs="1"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Message Content.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MSubject" type="xsd:string" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Message Subject. Ignored for all but mailto: URIs
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MDeliveryReportRecipientURI" type="xsd:anyURI" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
URI to send a delivery report to. May be of one of the following schemes:
mailto:, http:, https:. Reports to mailto: URIs are sent as plaintext,
reports to http(s) URIs are sent as SOAP requests following the
MessageGatewayClient service definition.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MKeepalive" type="tns:TKeepalive" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Container for keepalive information. May be missing.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepalive">
<xsd:annotation>
<xsd:documentation>Type containing keeplive information.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MKeepaliveTimeout" type="xsd:double">
<xsd:annotation>
<xsd:documentation>
Keepalive timeout. The keepalive timeout spezifies how long the sending of
a message will be delayed waiting for keepalive updates. If a keepalive
update is received during this period, the timeout will be reset. If not,
the message will be sent after the timeout has expired.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MKeepaliveErrorPolicy" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Policy to comply to in case of system errors. Valid values are "suppress"
and "report". If the policy is set to "suppress", keepalive messages will
not be sent to their recipients in case of partial system failure, even if
the keepalive has expired. This may result in "false negatives", i.e.
messages may not be sent, even though their keepalive has expired. If the
value is "report", keepalive messages will be sent from any cluster node.
This may result in "false positive" alerts.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="suppress"></xsd:enumeration>
<xsd:enumeration value="report"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TMessageID">
<xsd:annotation>
<xsd:documentation>Type containing a message ID.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessageID" type="xsd:string" minOccurs="1" maxOccurs="1"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepliveMessage">
<xsd:annotation>
<xsd:documentation>
Type containing all elements of a keppalive update / remove request.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessageID" type="xsd:string" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The ID for the message to update / remove
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MAction" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The action to perform. Valid values are: "remove", "update". On "remove",
the message with the ID specified will be removed from the queue, thus it
will never be sent, even if it's timeout expires. On "update" the
keepalive timeout of the corresponding message will be reset.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="remove"></xsd:enumeration>
<xsd:enumeration value="update"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="KeepaliveMessage" type="tns:TKeepaliveMessageRequest">
<xsd:annotation>
<xsd:documentation>Keepalive message request element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="KeepaliveMessageResponse" type="tns:TMessageID">
<xsd:annotation>
<xsd:documentation>Response element for a keepalive request</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="EnqueueMessageResponse" type="tns:TMessageID">
<xsd:annotation>
<xsd:documentation>Enqueue message response element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="TEnqueueMessage">
<xsd:annotation>
<xsd:documentation>
A complex type containing one element: The message to enqueue.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessage" type="tns:TMessage">
<xsd:annotation>
<xsd:documentation>
Element containing a message to enqueue.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepaliveMessageRequest">
<xsd:annotation>
<xsd:documentation>
A complex type containing one element: The keepalive message to process.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MKeepaliveMessage" type="tns:TKeepliveMessage">
<xsd:annotation>
<xsd:documentation>
Element containing a keepalive message to process.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="EnqueueMessageRequest">
<wsdl:part name="parameters" element="tns:EnqueueMessage">
<wsdl:documentation>inputparameters for EnqueueMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="EnqueueMessageResponse">
<wsdl:part name="parameters" element="tns:EnqueueMessageResponse">
<wsdl:documentation>outputparameters for EnqueueMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="KeepaliveMessageRequest">
<wsdl:part name="parameters" element="tns:KeepaliveMessage">
<wsdl:documentation>input parameters for KeepaliveMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="KeepaliveMessageResponse">
<wsdl:part name="parameters" element="tns:KeepaliveMessageResponse">
<wsdl:documentation>output parameters for KeepaliveMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:portType name="MGWPortType">
<wsdl:documentation>
generic port type for all methods required for sending messages over the mosaic
message gatewa
</wsdl:documentation>
<wsdl:operation name="EnqueueMessage">
<wsdl:documentation>
This method is used to enqueue a normal (immediate send) or a delayed message with
keepalive functionality.
</wsdl:documentation>
<wsdl:input message="tns:EnqueueMessageRequest"></wsdl:input>
<wsdl:output message="tns:EnqueueMessageResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeepaliveMessage">
<wsdl:documentation>
This method is used to update or remove a
keepalive message.
</wsdl:documentation>
<wsdl:input message="tns:KeepaliveMessageRequest"></wsdl:input>
<wsdl:output message="tns:KeepaliveMessageResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MGWBinding" type="tns:MGWPortType">
<wsdl:documentation>Generic binding for all (SOAP) port</wsdl:documentation>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="EnqueueMessage">
<soap:operation soapAction="http://www.example.org/MessageGateway2/EnqueueMessage" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeepaliveMessage">
<soap:operation
soapAction="http://www.example.org/MessageGateway2/KeepaliveMessage" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MessageGateway">
<wsdl:documentation>
Web Service for sending messages over the mosaic message gatewa
</wsdl:documentation>
<wsdl:port name="HTTPPort" binding="tns:MGWBinding">
<wsdl:documentation>HTTP(S) port for the mosaic message gatewa</wsdl:documentation>
<soap:address location="https://www.example.org/MessageGateway/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>};
}
+7 -4
View File
@@ -1,11 +1,15 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 5; use Test::More;
use lib '../lib'; use lib '../lib';
use XML::SAX::ParserFactory;
use diagnostics; if (eval "require XML::LibXML") {
plan tests => 5;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
eval { eval {
require Test::XML; require Test::XML;
@@ -18,7 +22,6 @@ my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation"); ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
use XML::LibXML;
my $parser = XML::LibXML->new(); my $parser = XML::LibXML->new();
$parser->set_handler( $filter ); $parser->set_handler( $filter );
+255
View File
@@ -0,0 +1,255 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More qw/no_plan/; # TODO: change to tests => N;
use Data::Dumper;
use lib '../lib';
use XML::LibXML;
use diagnostics;
use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
my $parser = XML::LibXML->new();
$parser->set_handler( $filter );
eval { $parser->parse_string( xml() ) };
if ($@)
{
fail("parsing WSDL");
die "Can't test without parsed WSDL: $@";
}
else
{
pass("parsing XML");
}
my $wsdl;
ok( $wsdl = $filter->get_data() , "get object tree");
my $opt = {
namespace => $wsdl->get_xmlns(),
style => 'perl',
wsdl => $wsdl,
readable => 1,
};
my $txt;
ok( $txt = $wsdl->explain( $opt ) , "explain WSDL" );
# print $txt;
sub xml {
return q{<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://example.com/soap/services/ETest/impl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://example.com/soap/services/ETest/impl"
xmlns:intf="http://example.com/soap/services/ETest"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns1="urn:ETest"
xmlns:tns2="urn:acquisition"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="urn:ETest" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<complexType name="CreationBaseData">
<sequence>
<element name="createdBy" nillable="true" type="xsd:long" />
<element name="creationDate" nillable="true" type="xsd:dateTime" />
<element name="updateDateCenter" nillable="true" type="xsd:dateTime" />
<element name="updateDateLocal" nillable="true" type="xsd:dateTime" />
<element name="updatedBy" nillable="true" type="xsd:long" />
</sequence>
</complexType>
<complexType name="CreationData">
<complexContent>
<extension base="tns1:CreationBaseData">
<sequence>
<element name="creatorFullName" nillable="true" type="xsd:string" />
<element name="modifierFullName" nillable="true" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType abstract="true" name="EProductData">
<sequence>
<element name="EStatus" nillable="true" type="xsd:string" />
<element name="EStatusUpdatedate" nillable="true" type="xsd:dateTime" />
<element name="SFXID" nillable="true" type="xsd:string" />
<element name="activationFromDate" nillable="true" type="xsd:dateTime" />
<element name="activationToDate" nillable="true" type="xsd:dateTime" />
<element name="activityStatusDateFrom" nillable="true" type="xsd:dateTime" />
<element name="activityStatusDateTo" nillable="true" type="xsd:dateTime" />
<element name="canEditSFXID" type="xsd:boolean" />
<element name="concurrentNumberOfUsers" nillable="true" type="xsd:int" />
<element name="creationData" nillable="true" type="tns1:CreationData" />
<element name="deleteable" type="xsd:boolean" />
<element name="ETestCode" nillable="true" type="xsd:string" />
<element name="id" nillable="true" type="xsd:long" />
<element name="instanceCode" nillable="true" type="xsd:string" />
<element name="mainContact" nillable="true" type="xsd:string" />
<element name="metaLibID" nillable="true" type="xsd:string" />
<element name="otherID" nillable="true" type="xsd:string" />
<element name="otherSource" nillable="true" type="xsd:string" />
<element name="privateNote" nillable="true" type="xsd:string" />
<element name="procurementStatus" nillable="true" type="xsd:string" />
<element name="procurementStatusUpdateDate" nillable="true" type="xsd:dateTime" />
<element name="procurementStatusUpdatedate" nillable="true" type="xsd:dateTime" />
<element name="sourceInstanceCode" nillable="true" type="xsd:string" />
<element name="sponseringLibraryCode" nillable="true" type="xsd:string" />
<element name="sponseringLibraryName" nillable="true" type="xsd:string" />
<element name="updateTarget" nillable="true" type="xsd:string" />
<element name="workExpressionCode" nillable="true" type="xsd:string" />
</sequence>
</complexType>
<complexType name="EProductInformation">
<sequence>
<element name="acquisitions" nillable="true"
type="impl:ArrayOf_tns2_AcquisitionData" />
<element name="data" nillable="true" type="tns1:EProductData" />
</sequence>
</complexType>
</schema>
<schema targetNamespace="urn:acquisition" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<complexType name="AcquisitionCommonData">
<sequence>
<element name="budgets" nillable="true" type="xsd:string" />
<element name="campusCode" nillable="true" type="xsd:string" />
<element name="concurrentUsersNote" nillable="true" type="xsd:string" />
<element name="creationData" nillable="true" type="tns1:CreationData" />
<element name="id" nillable="true" type="xsd:long" />
<element name="instituteCode" nillable="true" type="xsd:string" />
</sequence>
</complexType>
<complexType name="AcquisitionData">
<sequence>
<element name="ILSSubscriptionNo" nillable="true" type="xsd:string" />
<element name="acquisitionCode" nillable="true" type="xsd:string" />
<element name="acquisitionCommonData" nillable="true"
type="tns2:AcquisitionCommonData" />
<element name="acquisitionMethod" nillable="true" type="xsd:string" />
<element name="acquisitionNumber" nillable="true" type="xsd:string" />
<element name="acquisitionStatus" nillable="true" type="xsd:string" />
<element name="acquisitionStatusDate" nillable="true" type="xsd:dateTime" />
<element name="advanceNoticeDate" nillable="true" type="xsd:dateTime" />
<element name="autoRenewal" nillable="true" type="xsd:boolean" />
<element name="consortialAgreement" type="xsd:boolean" />
<element name="discountOnPrice" nillable="true" type="xsd:int" />
<element name="id" nillable="true" type="xsd:long" />
<element name="instanceCode" nillable="true" type="xsd:string" />
<element name="materialType" nillable="true" type="xsd:string" />
<element name="noteForILS" nillable="true" type="xsd:string" />
<element name="noteForVendor" nillable="true" type="xsd:string" />
<element name="noticePeriodCode" nillable="true" type="xsd:string" />
<element name="numberOfCopies" nillable="true" type="xsd:int" />
<element name="orderDate" nillable="true" type="xsd:dateTime" />
<element name="orderForm" nillable="true" type="xsd:string" />
<element name="orderSendMethod" nillable="true" type="xsd:string" />
<element name="pooledConcurrentUsers" nillable="true" type="xsd:int" />
<element name="price" nillable="true" type="xsd:double" />
<element name="pricingCap" nillable="true" type="xsd:int" />
<element name="pricingCapFrom" nillable="true" type="xsd:dateTime" />
<element name="pricingCapTo" nillable="true" type="xsd:dateTime" />
<element name="pricingModel" nillable="true" type="xsd:string" />
<element name="printCancellationNote" nillable="true" type="xsd:string" />
<element name="printCancellationRestriction" type="xsd:boolean" />
<element name="printPurchaseOrderNo" nillable="true" type="xsd:string" />
<element name="purchaseOrderNo" nillable="true" type="xsd:string" />
<element name="renewallOrCancellationDate" nillable="true" type="xsd:dateTime" />
<element name="renewallOrCancellationDescisionNote" nillable="true"
type="xsd:string" />
<element name="renewallOrCancellationNoteForILS" nillable="true"
type="xsd:string" />
<element name="renewallOrCancellationNoteForVendor" nillable="true"
type="xsd:string" />
<element name="subscriptionNotification" nillable="true" type="xsd:int" />
<element name="subscriptionPeriodCode" nillable="true" type="xsd:string" />
<element name="subscriptionType" nillable="true" type="xsd:string" />
<element name="subscriptionTypeNote" nillable="true" type="xsd:string" />
<element name="vendorAdvancedNotice" nillable="true" type="xsd:int" />
<element name="vendorAdvancedNoticeVal" nillable="true" type="xsd:string" />
<element name="vendorCode" nillable="true" type="xsd:string" />
<element name="vendorName" nillable="true" type="xsd:string" />
<element name="vendorSubscriptionCode" nillable="true" type="xsd:string" />
</sequence>
</complexType>
</schema>
<schema targetNamespace="http://example.com/soap/services/ETest/impl"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<complexType name="ArrayOf_tns2_AcquisitionData">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="tns2:AcquisitionData[]" />
</restriction>
</complexContent>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="getETestResponse">
<wsdl:part name="getETestReturn" type="tns1:EProductInformation" />
</wsdl:message>
<wsdl:message name="getFixedETestResponse">
<wsdl:part name="getFixedETestReturn" type="tns1:EProductInformation" />
</wsdl:message>
<wsdl:message name="getFixedETestRequest"></wsdl:message>
<wsdl:message name="getETestRequest">
<wsdl:part name="indexName" type="xsd:string" />
<wsdl:part name="indexValue" type="xsd:string" />
<wsdl:part name="withStatus" type="xsd:string" />
</wsdl:message>
<wsdl:portType name="ETestWeb">
<wsdl:operation name="getETest" parameterOrder="indexName indexValue withStatus">
<wsdl:input message="impl:getETestRequest" name="getETestRequest" />
<wsdl:output message="impl:getETestResponse" name="getETestResponse" />
</wsdl:operation>
<wsdl:operation name="getFixedETest">
<wsdl:input message="impl:getFixedETestRequest" name="getFixedETestRequest" />
<wsdl:output message="impl:getFixedETestResponse"
name="getFixedETestResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ETestSoapBinding" type="impl:ETestWeb">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="getETest">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="getETestRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://example.com/soap/services/ETest" use="encoded" />
</wsdl:input>
<wsdl:output name="getETestResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://example.com/soap/services/ETest" use="encoded" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getFixedETest">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="getFixedETestRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://example.com/soap/services/ETest" use="encoded" />
</wsdl:input>
<wsdl:output name="getFixedETestResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://example.com/soap/services/ETest" use="encoded" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ETestWebService">
<wsdl:port binding="impl:ETestSoapBinding" name="ETest">
<wsdlsoap:address location="http://example.com/soap/services/ETest" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
};
}
+8 -3
View File
@@ -1,10 +1,15 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Test::More qw/no_plan/; # TODO: change to tests => N; use Test::More; # TODO: change to tests => N;
use Data::Dumper;
use lib '../lib'; use lib '../lib';
use XML::LibXML;
if (eval "require XML::LibXML") {
plan tests => 5;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
use diagnostics; use diagnostics;
+8 -11
View File
@@ -1,10 +1,8 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Pod::Simple::Text;
use Test::More qw/no_plan/; # TODO: change to tests => N; use Test::More qw/no_plan/; # TODO: change to tests => N;
use lib '../lib'; use lib '../lib';
use XML::SAX::ParserFactory;
eval { eval {
require Test::XML; require Test::XML;
@@ -31,11 +29,17 @@ ok( $soap->no_dispatch( 1 ) , "Set no_dispatch" );
ok( $soap->explain() ); ok( $soap->explain() );
SKIP: {
if (not eval "require Pod::Simple::Text") {
skip "cannot test parsing pod without Pod::Test::Simple", 1;
};
my $pod = Pod::Simple::Text->new(); my $pod = Pod::Simple::Text->new();
my $output; my $output;
$pod->output_string( \$output ); $pod->output_string( \$output );
$pod->parse_string_document( $soap->explain() ); ok $pod->parse_string_document( $soap->explain() ), 'parse explain pod';
}
# print $output; # print $output;
SKIP: { SKIP: {
@@ -48,10 +52,6 @@ SKIP: {
} }
) )
, q{<SOAP-ENV:Envelope , q{<SOAP-ENV:Envelope
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.example.org/MessageGateway2/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
<SOAP-ENV:Body ><EnqueueMessage xmlns="http://www.example.org/MessageGateway2/"><MMessage> <SOAP-ENV:Body ><EnqueueMessage xmlns="http://www.example.org/MessageGateway2/"><MMessage>
<MRecipientURI>mailto:test@example.com</MRecipientURI> <MRecipientURI>mailto:test@example.com</MRecipientURI>
@@ -64,6 +64,3 @@ sub skip_without_test_xml {
my $number = shift || 1; my $number = shift || 1;
skip("Test::XML not available", $number) if (not $Test::XML::VERSION); skip("Test::XML not available", $number) if (not $Test::XML::VERSION);
} }
__END__
+1 -1
View File
@@ -15,7 +15,7 @@ my $soap = SOAP::WSDL->new(
wsdl => 'file:///' . $path .'/t/acceptance/wsdl/008_complexType.wsdl' wsdl => 'file:///' . $path .'/t/acceptance/wsdl/008_complexType.wsdl'
)->wsdlinit(); )->wsdlinit();
my $wsdl = $soap->{ _WSDL }->{ wsdl_definitions }; my $wsdl = $soap->get_definitions;
my $schema = $wsdl->first_types(); my $schema = $wsdl->first_types();
my $type = $schema->find_type('Test' , 'testComplexTypeAll'); my $type = $schema->find_type('Test' , 'testComplexTypeAll');
my $element = $type->get_element()->[0]; my $element = $type->get_element()->[0];
+12 -15
View File
@@ -1,13 +1,14 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings;
use Test::More tests => 5; use Test::More tests => 5;
use lib 't/lib'; use lib 't/lib';
use lib '../lib'; use lib '../lib';
use lib 'lib'; use lib 'lib';
use XML::Simple;
use SOAP::WSDL::SAX::WSDLHandler; use SOAP::WSDL::SAX::WSDLHandler;
use Cwd; use Cwd;
use XML::LibXML::SAX;
use_ok(qw/SOAP::WSDL::SAX::MessageHandler/); use_ok(qw/SOAP::WSDL::SAX::MessageHandler/);
use SOAP::WSDL; use SOAP::WSDL;
@@ -15,22 +16,18 @@ use SOAP::WSDL::XSD::Typelib::Builtin;
my $path = cwd; my $path = cwd;
$path =~s|\/t\/?$||; # allow running from t/ and above (Build test) $path =~s|\/t\/?$||; # allow running from t/ and above (Build test)
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
my $filter; my $parser;
ok($filter = SOAP::WSDL::SAX::MessageHandler->new( {
ok $parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => FakeResolver->new(), class_resolver => FakeResolver->new(),
} ), "Object creation"); }), "Object creation";
my $parser = XML::LibXML->new(); # TODO factor out into bool test
$parser->set_handler( $filter );
$parser->parse_string( xml() ); $parser->parse( xml() );
# print $filter->get_data(); if($parser->get_data()->get_MMessage()->get_MDeliveryReportRecipientURI()) {
# print $filter->get_data()->get_MMessage()->_DUMP();
if($filter->get_data()->get_MMessage()->get_MDeliveryReportRecipientURI()) {
pass "bool context overloading"; pass "bool context overloading";
} }
else else
@@ -38,6 +35,8 @@ else
fail "bool context overloading" fail "bool context overloading"
} }
# TODO factor out into different test
my $soap = SOAP::WSDL->new( my $soap = SOAP::WSDL->new(
readable => 1, readable => 1,
wsdl => 'file:///' . $path .'/t/acceptance/wsdl/006_sax_client.wsdl', wsdl => 'file:///' . $path .'/t/acceptance/wsdl/006_sax_client.wsdl',
@@ -86,6 +85,4 @@ BEGIN {
: warn "no class found for $name"; : warn "no class found for $name";
}; };
}; };
}; };
+9 -5
View File
@@ -1,11 +1,15 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 16; use Test::More;
use lib '../lib'; use lib '../lib';
use XML::SAX::ParserFactory;
use diagnostics; if (eval "require XML::LibXML") {
plan tests => 16;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
eval { eval {
require Test::XML; require Test::XML;
@@ -18,7 +22,6 @@ my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation"); ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
use XML::LibXML;
my $parser = XML::LibXML->new(); my $parser = XML::LibXML->new();
$parser->set_handler( $filter ); $parser->set_handler( $filter );
@@ -56,7 +59,8 @@ for my $element (@{ $wsdl->first_types()->get_schema()->[1]->get_type() } ) {
next; next;
} }
my $name = 'MessageGateway::' . $element->get_name(); my $name = 'MessageGateway::' . $element->get_name();
ok eval $output, $name; ok eval $output, $name
or die $@, $output;
ok $name->can('serialize'), "$name\->can('serialize')"; ok $name->can('serialize'), "$name\->can('serialize')";
} }
+7 -4
View File
@@ -1,11 +1,15 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 5; use Test::More;
use lib '../lib'; use lib '../lib';
use XML::SAX::ParserFactory;
use diagnostics; if (eval "require XML::LibXML") {
plan tests => 5;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
eval { eval {
require Test::XML; require Test::XML;
@@ -18,7 +22,6 @@ my $filter;
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation"); ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
use XML::LibXML;
my $parser = XML::LibXML->new(); my $parser = XML::LibXML->new();
$parser->set_handler( $filter ); $parser->set_handler( $filter );
+412
View File
@@ -0,0 +1,412 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More tests => 19;
use lib '../lib';
use SOAP::WSDL::Expat::WSDLParser;
use SOAP::WSDL::Expat::MessageParser;
use File::Path;
use File::Basename;
my $path = dirname __FILE__;
my $wsdl;
ok( $wsdl = SOAP::WSDL::Expat::WSDLParser->new()
->parse_string( xml() ) , "get object tree");
$wsdl->create({
base_path => "$path/testlib",
typemap_prefix => "Test::Typemap::",
type_prefix => "Test::Type::",
element_prefix => "Test::Element::",
interface_prefix => "Test::Interface::",
});
eval "use lib '$path/testlib'";
use_ok qw(Test::Element::EnqueueMessage);
use_ok qw(Test::Type::TMessage);
use_ok qw(Test::Typemap::MessageGateway);
my $data = {
MMessage => {
MRecipientURI => 'anyURI',
MSenderAddress => 'a string',
MMessageContent => 'a string',
MSubject => 'a string',
MDeliveryReportRecipientURI => 'anyURI',
MKeepalive => {
MKeepaliveTimeout => 1234567,
MKeepaliveErrorPolicy => ' ( suppress | report ) ',
}
}
};
ok Test::Element::EnqueueMessage->new( $data ) , '(generated) object constructor';
my $message_parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => 'Test::Typemap::MessageGateway'
});
eval { $message_parser->parse_string( xml_message2() ) };
ok ( !$@, 'parse XML message');
TODO: {
local $TODO = 'support embedded atomic simpleType/complexType definitions';
eval { $message_parser->parse_string( xml_message() ) };
ok ( !$@, 'parse XML message using atomic type definitions');
};
SKIP: {
eval "require Test::Pod";
skip 'Cannot test generated POD without Test::POD' , 6 if $@;
foreach my $module (Test::Pod::all_pod_files( "$path/testlib")) {
Test::Pod::pod_file_ok( $module )
}
}
# cleanup
rmtree "$path/testlib";
# print $wsdl->explain();
sub xml_message {
return
q{<EnqueueMessage xmlns="http://www.example.org/MessageGateway2/">
<MMessage>
<MRecipientURI>anyURI</MRecipientURI>
<MSenderAddress>a string</MSenderAddress>
<MMessageContent>a string</MMessageContent>
<MSubject>a string</MSubject>
<MDeliveryReportRecipientURI>anyURI</MDeliveryReportRecipientURI>
<MKeepalive>
<MKeepaliveTimeout>1234567</MKeepaliveTimeout>
<MKeepaliveErrorPolicy> ( suppress | report ) </MKeepaliveErrorPolicy>
</MKeepalive>
</MMessage>
</EnqueueMessage>
};
}
sub xml_message2 {
return
q{<EnqueueMessage xmlns="http://www.example.org/MessageGateway2/">
<MMessage>
<MRecipientURI>anyURI</MRecipientURI>
<MSenderAddress>a string</MSenderAddress>
<MMessageContent>a string</MMessageContent>
<MSubject>a string</MSubject>
<MDeliveryReportRecipientURI>anyURI</MDeliveryReportRecipientURI>
</MMessage>
</EnqueueMessage>
};
}
sub xml {
return q{<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="MessageGateway"
targetNamespace="http://www.example.org/MessageGateway2/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.example.org/MessageGateway2/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/MessageGateway2/">
<xsd:element name="EnqueueMessage" type="tns:TEnqueueMessage"
xmlns:tns="http://www.example.org/MessageGateway2/">
<xsd:annotation>
<xsd:documentation>Enqueue message request element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="TMessage">
<xsd:annotation>
<xsd:documentation>
A type containing all elements of a message to enqueue.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MRecipientURI" type="xsd:anyURI" minOccurs="1"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The recipient in URI notaitions. Valid URI schemas are: mailto:, sms:,
phone:. Not all URI schemas need to be implemented at the current
implementation stage.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MSenderAddress" type="xsd:string" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
E-Mail sender address. Ignored for all but mailto: recipient URIs.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MMessageContent" type="xsd:string" minOccurs="1"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Message Content.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MSubject" type="xsd:string" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Message Subject. Ignored for all but mailto: URIs
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MDeliveryReportRecipientURI" type="xsd:anyURI" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
URI to send a delivery report to. May be of one of the following schemes:
mailto:, http:, https:. Reports to mailto: URIs are sent as plaintext,
reports to http(s) URIs are sent as SOAP requests following the
MessageGatewayClient service definition.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MKeepalive" type="tns:TKeepalive" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Container for keepalive information. May be missing.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepalive">
<xsd:annotation>
<xsd:documentation>Type containing keeplive information.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MKeepaliveTimeout" type="xsd:double">
<xsd:annotation>
<xsd:documentation>
Keepalive timeout. The keepalive timeout spezifies how long the sending of
a message will be delayed waiting for keepalive updates. If a keepalive
update is received during this period, the timeout will be reset. If not,
the message will be sent after the timeout has expired.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MKeepaliveErrorPolicy" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Policy to comply to in case of system errors. Valid values are "suppress"
and "report". If the policy is set to "suppress", keepalive messages will
not be sent to their recipients in case of partial system failure, even if
the keepalive has expired. This may result in "false negatives", i.e.
messages may not be sent, even though their keepalive has expired. If the
value is "report", keepalive messages will be sent from any cluster node.
This may result in "false positive" alerts.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="suppress"></xsd:enumeration>
<xsd:enumeration value="report"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TMessageID">
<xsd:annotation>
<xsd:documentation>Type containing a message ID.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessageID" type="xsd:string" minOccurs="1" maxOccurs="1"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepliveMessage">
<xsd:annotation>
<xsd:documentation>
Type containing all elements of a keppalive update / remove request.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessageID" type="xsd:string" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The ID for the message to update / remove
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MAction" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The action to perform. Valid values are: "remove", "update". On "remove",
the message with the ID specified will be removed from the queue, thus it
will never be sent, even if it's timeout expires. On "update" the
keepalive timeout of the corresponding message will be reset.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="remove"></xsd:enumeration>
<xsd:enumeration value="update"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="KeepaliveMessage" type="tns:TKeepaliveMessageRequest">
<xsd:annotation>
<xsd:documentation>Keepalive message request element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="KeepaliveMessageResponse" type="tns:TMessageID">
<xsd:annotation>
<xsd:documentation>Response element for a keepalive request</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="EnqueueMessageResponse" type="tns:TMessageID">
<xsd:annotation>
<xsd:documentation>Enqueue message response element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="TEnqueueMessage">
<xsd:annotation>
<xsd:documentation>
A complex type containing one element: The message to enqueue.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessage" type="tns:TMessage">
<xsd:annotation>
<xsd:documentation>
Element containing a message to enqueue.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepaliveMessageRequest">
<xsd:annotation>
<xsd:documentation>
A complex type containing one element: The keepalive message to process.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MKeepaliveMessage" type="tns:TKeepliveMessage">
<xsd:annotation>
<xsd:documentation>
Element containing a keepalive message to process.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="EnqueueMessageRequest">
<wsdl:part name="parameters" element="tns:EnqueueMessage">
<wsdl:documentation>inputparameters for EnqueueMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="EnqueueMessageResponse">
<wsdl:part name="parameters" element="tns:EnqueueMessageResponse">
<wsdl:documentation>outputparameters for EnqueueMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="KeepaliveMessageRequest">
<wsdl:part name="parameters" element="tns:KeepaliveMessage">
<wsdl:documentation>input parameters for KeepaliveMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="KeepaliveMessageResponse">
<wsdl:part name="parameters" element="tns:KeepaliveMessageResponse">
<wsdl:documentation>output parameters for KeepaliveMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:portType name="MGWPortType">
<wsdl:documentation>
generic port type for all methods required for sending messages over the mosaic
message gatewa
</wsdl:documentation>
<wsdl:operation name="EnqueueMessage">
<wsdl:documentation>
This method is used to enqueue a normal (immediate send) or a delayed message with
keepalive functionality.
</wsdl:documentation>
<wsdl:input message="tns:EnqueueMessageRequest"></wsdl:input>
<wsdl:output message="tns:EnqueueMessageResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeepaliveMessage">
<wsdl:documentation>
This method is used to update or remove a
keepalive message.
</wsdl:documentation>
<wsdl:input message="tns:KeepaliveMessageRequest"></wsdl:input>
<wsdl:output message="tns:KeepaliveMessageResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MGWBinding" type="tns:MGWPortType">
<wsdl:documentation>Generic binding for all (SOAP) port</wsdl:documentation>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="EnqueueMessage">
<soap:operation soapAction="http://www.example.org/MessageGateway2/EnqueueMessage" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeepaliveMessage">
<soap:operation
soapAction="http://www.example.org/MessageGateway2/KeepaliveMessage" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MessageGateway">
<wsdl:documentation>
Web Service for sending messages over the message gatewa
</wsdl:documentation>
<wsdl:port name="HTTPPort" binding="tns:MGWBinding">
<wsdl:documentation>HTTP(S) port for the message gateway</wsdl:documentation>
<soap:address location="https://www.example.org/MessageGateway/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>};
}
@@ -1,14 +1,20 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 18; use Test::More;
use lib '../lib'; use lib '../lib';
use XML::LibXML;
use SOAP::WSDL::SAX::WSDLHandler; use SOAP::WSDL::SAX::WSDLHandler;
use SOAP::WSDL::SAX::MessageHandler; use SOAP::WSDL::SAX::MessageHandler;
use File::Path; use File::Path;
use File::Basename; use File::Basename;
if (eval "require XML::LibXML") {
plan tests => 18;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
my $path = dirname __FILE__; my $path = dirname __FILE__;
my $filter = SOAP::WSDL::SAX::WSDLHandler->new(); my $filter = SOAP::WSDL::SAX::WSDLHandler->new();
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More tests => 12;
use lib '../lib';
use SOAP::WSDL::Expat::WSDLParser;
use File::Find;
use File::Basename;
my $path = dirname __FILE__;
my $wsdl;
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
ok( $wsdl = $parser->parse_file( "$path/../example/wsdl/globalweather.xml" ) );
$wsdl->create({
base_path => "$path/testlib",
typemap_prefix => "Test::Typemap::",
type_prefix => "Test::Type::",
element_prefix => "Test::Element::",
interface_prefix => "Test::Interface::",
});
# Check for created files (and dirs) - value is the number of entries
# with this (local) name
my %expected = (
'GetCitiesByCountry.pm' => 1,
'GetCitiesByCountryResponse.pm' => 1,
'GetWeather.pm' => 1,
'GetWeatherResponse.pm' => 1,
'string.pm' => 1,
'Element' => 1,
'Interface' => 1,
'GlobalWeather.pm' => 2,
'Typemap' => 1,
'Test' => 1,
);
File::Find::finddepth(
sub {
return if $_ eq '.';
ok $expected{ $_ }--, $_;
unlink $_ if -f $_;
rmdir $_ if -d $_;
},
"$path/testlib",
);
rmdir "$path/testlib";
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More;
use lib '../lib';
use SOAP::WSDL::SAX::WSDLHandler;
use SOAP::WSDL::SAX::MessageHandler;
use File::Path;
use File::Basename;
if (eval "require XML::LibXML") {
plan tests => 1;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
my $path = dirname __FILE__;
my $filter = SOAP::WSDL::SAX::WSDLHandler->new();
my $parser = XML::LibXML->new();
$parser->set_handler( $filter );
$parser->parse_file( "$path/../example/wsdl/globalweather.xml" );
my $wsdl;
ok( $wsdl = $filter->get_data() , "get object tree");
$wsdl->create({
base_path => "$path/testlib",
typemap_prefix => "Test::Typemap::",
type_prefix => "Test::Type::",
element_prefix => "Test::Element::",
interface_prefix => "Test::Interface::",
});
rmtree "$path/testlib";
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More tests => 10;
use File::Path;
use File::Basename;
use lib '../lib';
use_ok(qw/SOAP::WSDL::Expat::WSDLParser/);
my $path = dirname __FILE__;
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
eval { $parser->parsefile( "$path/acceptance/wsdl/03_complexType-element-ref.wsdl" ) };
if ($@)
{
fail("parsing WSDL");
die "Can't test without parsed WSDL: $@";
}
else
{
pass("parsing XML");
}
my $definitions = $parser->get_data();
my $type = $definitions->first_types()->find_type('urn:Test', 'testComplexTypeRef');
my $element = $definitions->first_types()->find_element('urn:Test', 'TestElement');
my $output = '';
ok $element->to_class({ wsdl => $definitions, prefix => 'Test::', output => \$output })
, 'generate element code';
ok eval $output, 'eval generated code';
$output = '';
ok $type->to_class({ wsdl => $definitions, prefix => 'Test::', output => \$output })
, 'generate complexType code with element ref=""';
ok eval $output, 'eval generated code';
my $obj = Test::testComplexTypeRef->new({
TestRef => 'test_ref',
Test2 => 'test2',
});
is $obj, '<TestRef >test_ref</TestRef><Test2 >test2</Test2 >', 'serialization';
$element = $definitions->first_types()->find_element('urn:Test', 'TestRef');
$output = '';
ok $element->to_class({ wsdl => $definitions, prefix => 'Test::', output => \$output })
, 'generate top level element ref code';
ok eval $output, 'eval generated code' . $@;
$obj = Test::TestRef->new({ value => 'test_ref' });
is $obj, '<TestRef xmlns="urn:Test" >test_ref</TestRef>', 'serialization';
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More;
use File::Path;
use File::Basename;
use lib '../lib';
if (eval "require XML::LibXML") {
plan tests => 11;
}
else {
plan skip_all => "Cannot test without XML::LibXML";
}
my $path = dirname __FILE__;
use_ok(qw/SOAP::WSDL::SAX::WSDLHandler/);
my $filter;
my $parser = XML::LibXML->new();
ok($filter = SOAP::WSDL::SAX::WSDLHandler->new(), "Object creation");
$parser->set_handler( $filter );
eval { $parser->parse_file( "$path/acceptance/wsdl/03_complexType-element-ref.wsdl" ) };
if ($@)
{
fail("parsing WSDL");
die "Can't test without parsed WSDL: $@";
}
else
{
pass("parsing XML");
}
my $definitions = $filter->get_data();
my $type = $definitions->first_types()->find_type('urn:Test', 'testComplexTypeRef');
my $element = $definitions->first_types()->find_element('urn:Test', 'TestElement');
my $output;
ok $element->to_class({ wsdl => $definitions, prefix => 'Test::', output => \$output })
, 'generate element code';
ok eval $output, 'eval generated code';
$output = '';
ok $type->to_class({ wsdl => $definitions, prefix => 'Test::', output => \$output })
, 'generate complexType code with element ref=""';
ok eval $output, 'eval generated code';
my $obj = Test::testComplexTypeRef->new({
TestRef => 'test_ref',
Test2 => 'test2',
});
is $obj, '<TestRef >test_ref</TestRef><Test2 >test2</Test2 >', 'serialization';
$element = $definitions->first_types()->find_element('urn:Test', 'TestRef');
$output = '';
ok $element->to_class({ wsdl => $definitions, prefix => 'Test::', output => \$output })
, 'generate top level element ref code';
ok eval $output, 'eval generated code' . $@;
# print $output;
$obj = Test::TestRef->new({ value => 'test_ref' });
is $obj, '<TestRef xmlns="urn:Test" >test_ref</TestRef>', 'serialization';
+7 -15
View File
@@ -2,26 +2,18 @@ use Test::More;
eval "use Test::Pod 1.00"; eval "use Test::Pod 1.00";
plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
use Cwd; # perl Build test or make test run from top-level dir.
if ( -d '../t/' ) {
my $dir = cwd; @directories = ('../lib/');
if ( $dir =~ /t$/ )
{
@directories = ('../lib/', '../bin/');
} }
else else {
{ @directories = (); # empty - will work automatically
@directories = ();
} }
my @files = all_pod_files( my @files = all_pod_files(@directories);
@directories
);
plan tests => scalar(@files); plan tests => scalar(@files);
foreach my $module (@files) foreach my $module (@files){
{
pod_file_ok( $module ) pod_file_ok( $module )
} }
-9
View File
@@ -5,7 +5,6 @@ use Test::More tests => 2;
use lib '../lib'; use lib '../lib';
use lib 'lib'; use lib 'lib';
use lib 't/lib'; use lib 't/lib';
use XML::LibXML;
use SOAP::WSDL::SAX::MessageHandler; use SOAP::WSDL::SAX::MessageHandler;
use_ok(qw/SOAP::WSDL::Expat::MessageParser/); use_ok(qw/SOAP::WSDL::Expat::MessageParser/);
@@ -13,7 +12,6 @@ use_ok(qw/SOAP::WSDL::Expat::MessageParser/);
use MyComplexType; use MyComplexType;
use MyElement; use MyElement;
use MySimpleType; use MySimpleType;
use Benchmark;
my $xml = q{<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" my $xml = q{<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
@@ -26,13 +24,6 @@ my $parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => 'FakeResolver' class_resolver => 'FakeResolver'
}); });
my $libxml = XML::LibXML->new();
my $handler = SOAP::WSDL::SAX::MessageHandler->new({
class_resolver => 'FakeResolver',
});
$libxml->set_handler( $handler );
$parser->parse( $xml ); $parser->parse( $xml );
is $parser->get_data(), q{<MyAtomicComplexTypeElement xmlns="urn:Test" >} is $parser->get_data(), q{<MyAtomicComplexTypeElement xmlns="urn:Test" >}
+335
View File
@@ -0,0 +1,335 @@
package TopElement;
use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element;
use SOAP::WSDL::XSD::Typelib::ComplexType;
use Memoize;
memoize('_get_handlers');
use base qw(SOAP::WSDL::XSD::Typelib::Element
SOAP::WSDL::XSD::Typelib::ComplexType
);
{
my %TestElement_of :ATTR();
my $CLASS_OF_REF = { TestElement => 'TestElement' };
__PACKAGE__->_factory( [ 'TestElement' ],
{ 'TestElement' => \%TestElement_of, },
{ TestElement => 'TestElement' },
);
sub get_xmlns { 'urn:Test' };
__PACKAGE__->__set_name('TopElement');
__PACKAGE__->__set_nillable(1);
sub _get_handlers {
my $self = shift;
my $parser = shift;
return {
Start => $parser->start_tag({
class_of => $CLASS_OF_REF,
handler_of => {
TestElement => TestElement->_get_handlers( $parser ),
}
}),
End => $parser->end_top_tag( ),
Char => undef,
};
}
}
1;
package TestElement;
use Class::Std::Storable;
use SOAP::WSDL::XSD::Typelib::Element;
use SOAP::WSDL::XSD::Typelib::ComplexType;
use Memoize;
memoize('_get_handlers');
use base qw(
SOAP::WSDL::XSD::Typelib::Element
SOAP::WSDL::XSD::Typelib::ComplexType
);
{
my %test_of :ATTR();
my %test2_of :ATTR();
my $CLASS_OF_REF = {
test => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
test2 => 'SOAP::WSDL::XSD::Typelib::Builtin::string'
};
__PACKAGE__->_factory( [ 'test', 'test2' ],
{ test => \%test_of, test2 => \%test2_of, },
$CLASS_OF_REF,
);
sub get_xmlns { 'urn:Test' };
__PACKAGE__->__set_name('TestElement');
__PACKAGE__->__set_nillable(1);
sub _get_handlers {
my $self = shift;
my $parser = shift;
return {
Start => $parser->start_tag({
class_of => $CLASS_OF_REF,
handler_of =>
{
map { ( $_ => $CLASS_OF_REF->{$_}->_get_handlers( $parser ) )}
keys %{ $CLASS_OF_REF }
},
}),
End => $parser->end_tag(),
Char => undef,
};
}
}
1;
package TestResolver;
sub get_class {
my $path = join('/', @{ $_[1] });
my $class = {
'TestElement' => 'TestElement',
'TestElement/test' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'TestElement/test2' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'TopElement' => 'TopElement',
'TopElement/TestElement' => 'TestElement',
'TopElement/TestElement/test' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'TopElement/TestElement/test2' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
};
return $class->{ $path };
}
1;
package main;
use Test::More qw/no_plan/; # TODO: change to tests => N;
use strict;
use warnings;
use lib '../../lib';
use_ok('SOAP::WSDL::Expat::MessageParser');
use_ok('SOAP::WSDL::Expat::MessageSubParser');
my $obj;
ok($obj = SOAP::WSDL::Expat::MessageSubParser->new(), "Object creation");
#my $test = $obj->start_tag({
# order => [],
# class_of => {
# test => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# test2 => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# },
# handler_of => {
# test => {
# Char => $obj->characters(),
# },
# test2 => {
# Char => $obj->characters(),
# },
# }
#});
#
#my $handlers = {
# Start => $test,
# End => $obj->end_tag(),
#};
#
#my $parser = $obj->initialize( $handlers );
#
#$parser->parsestring('<test>Test</test>');
#is $obj->get_data(), 'Test', 'Parse simple XML';
#
#my $element = $obj->start_tag({
# order => [],
# class_of => {
# TestElement => 'TestElement',
# },
# handler_of => {
# TestElement => {
# Start => $obj->start_tag({
# order => [],
# class_of => {
# test => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# test2 => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# },
# handler_of => {
# test => {
# Char => $obj->characters(),
# },
# test2 => {
# Char => $obj->characters(),
# },
# }
# }),
# End => $obj->end_tag(),
# Char => undef,
# }
# }
#});
#
#
#$handlers = {
# Start => $element,
# End => $obj->end_tag(),
# Char => undef,
#};
#
#$parser = $obj->initialize( TestElement->_get_parser( $obj ) );
#
#my $xml = '<TestElement xmlns="urn:Test">
# <test>Test</test>
# <test2>Test2</test2>
#</TestElement>';
#
#$parser->parsestring($xml);
#
#is $obj->get_data()
# , '<TestElement xmlns="urn:Test" ><test >Test</test ><test2 >Test2</test2 ></TestElement>'
# , 'Parse && serialize ComplexType Element';
#
#my $mp = SOAP::WSDL::Expat::MessageParser->new({
# class_resolver => 'TestResolver',
#});
#
#$mp->parse( $xml );
#use Benchmark;
#
#timethese 1000 , {
# mp => sub { $mp->parse($xml) },
# 'sub_p' => sub { $obj->initialize( $handlers )->parse( $xml ) },
#
#};
#my $top = $obj->start_tag({
# order => [],
# class_of => {
# TopElement => 'TopElement',
# },
# handler_of => {
# TopElement => {
# Start => $obj->start_tag({
# order => [ 'TestElement', ],
# class_of => {
# TestElement => 'TestElement',
# },
# handler_of => {
# TestElement => {
# Start => $obj->start_tag({
# order => ['test', 'test2'],
# class_of => {
# test => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# test2 => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
# },
# handler_of => {
# test => {
# Char => $obj->characters(),
# },
# test2 => {
# Char => $obj->characters(),
# },
# },
# occurs_of => {
# test => { max => 1 },
# }
# }),
# End => $obj->end_tag(),
# Char => undef,
# }
# }
# })
# }
# }
#});
my $top = $obj->start_tag({
class_of => {
TopElement => 'TopElement',
},
handler_of => {
TopElement => TopElement->_get_handlers( $obj ),
}
});
my $parser = $obj->initialize( { Start => $top , End => $obj->end_tag() , Char => undef } );
my $xml = '
<TopElement xmlns="urn:Test">
<TestElement>
<test>Test</test>
<test2>Test2</test2>
</TestElement>
<TestElement>
<test>Test</test>
<test2>Test2</test2>
</TestElement>
<TestElement>
<test>Test</test>
<test2>Test2</test2>
</TestElement>
<TestElement>
<test>Test</test>
<test2>Test2</test2>
</TestElement>
<TestElement>
<test>Test</test>
<test2>Test2</test2>
</TestElement>
<TestElement>
<test>Test</test>
<test2>Test2</test2>
</TestElement>
</TopElement>';
$parser->parsestring($xml);
# print $obj->get_data();
__END__
# TODO factor out into benchmark suite
use XML::Simple;
use Benchmark;
my $mp = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => 'TestResolver',
});
$mp->parse( $xml );
$top = $obj->start_tag({
class_of => {
TopElement => 'TopElement',
},
handler_of => {
TopElement => TopElement->_get_handlers( $obj ),
}
});
my $top_end = $obj->end_top_tag();
$parser = $obj->initialize( { Start => $top , End => $top_end, , Char => undef } );
$parser->parse( $xml ),
print "DATA:" . $obj->get_data(), "\n";
# $XML::Simple::PREFERRED_PARSER = 'XML::SAX::Expat';
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
timethese 500 , {
'typemap' => sub { $mp->parse($xml) },
'sub_tree' => sub {
my $parser = $obj->initialize( { Start => $top , End => $top_end, , Char => undef } );
$parser->parse( $xml ),
},
'XML::Simple' => sub { XMLin( $xml ); }
};
+411
View File
@@ -0,0 +1,411 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use diagnostics;
use Test::More tests => 7;
use Data::Dumper;
use lib '../lib';
eval {
require Test::XML;
import Test::XML;
};
use_ok(qw/SOAP::WSDL::Expat::WSDLParser/);
my $parser;
ok $parser = SOAP::WSDL::Expat::WSDLParser->new(), "Object creation";
$parser->parse( xml() );
eval { $parser->parse( xml() ) };
if ($@)
{
fail("parsing WSDL");
die "Can't test without parsed WSDL: " , Dumper $@;
}
else
{
pass("parsing XML");
}
my $wsdl;
ok $wsdl = $parser->get_data() , "get object tree";
my $schema = $wsdl->first_types()->get_schema()->[1] || die "No schema !";
my $element = $schema->find_element(
'http://www.example.org/MessageGateway2/'
, 'EnqueueMessage'
);
ok $element, 'find element';
is $element->get_xmlns()->{ 'http://www.example.org/MessageGateway2/' }, 'tns', 'Namespace definition';
my $opt = {
typelib => $wsdl->first_types,
readable => 1,
autotype => 0,
namespace => { 'http://www.example.org/MessageGateway2/' => 'tns',
'http://www.w3.org/2001/XMLSchema' => 'xsd',
'http://schemas.xmlsoap.org/wsdl/' => 'wsdl',
},
indent => "",
};
my $data = { EnqueueMessage => {
MMessage => {
MRecipientURI => 'anyURI',
MSenderAddress => 'a string',
MMessageContent => 'a string',
MSubject => 'a string',
MDeliveryReportRecipientURI => 'anyURI',
MKeepalive => {
MKeepaliveTimeout => 1234567,
MKeepaliveErrorPolicy => ' ( suppress | report ) ',
}
}
}
};
SKIP: { skip_without_test_xml();
is_xml( $wsdl->find_message(
"http://www.example.org/MessageGateway2/" ,'EnqueueMessageRequest'
)->first_part()->serialize( 'test', $data, $opt ),
xml_message()
, "Serialized message part"
);
}
sub skip_without_test_xml {
skip("Test::XML not available", 1) if (not $Test::XML::VERSION);
}
sub xml_message {
return
q{<EnqueueMessage xmlns="http://www.example.org/MessageGateway2/">
<MMessage>
<MRecipientURI>anyURI</MRecipientURI>
<MSenderAddress>a string</MSenderAddress>
<MMessageContent>a string</MMessageContent>
<MSubject>a string</MSubject>
<MDeliveryReportRecipientURI>anyURI</MDeliveryReportRecipientURI>
<MKeepalive>
<MKeepaliveTimeout>1234567</MKeepaliveTimeout>
<MKeepaliveErrorPolicy> ( suppress | report ) </MKeepaliveErrorPolicy>
</MKeepalive>
</MMessage>
</EnqueueMessage>
};
}
sub xml {
return q{<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="MessageGateway"
targetNamespace="http://www.example.org/MessageGateway2/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.example.org/MessageGateway2/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/MessageGateway2/">
<xsd:element name="EnqueueMessage" type="tns:TEnqueueMessage"
xmlns:tns="http://www.example.org/MessageGateway2/"
>
<xsd:annotation>
<xsd:documentation>Enqueue message request element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="TMessage">
<xsd:annotation>
<xsd:documentation>
A type containing all elements of a message to enqueue.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MRecipientURI" type="xsd:anyURI" minOccurs="1"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The recipient in URI notaitions. Valid URI schemas are: mailto:, sms:,
phone:. Not all URI schemas need to be implemented at the current
implementation stage.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MSenderAddress" type="xsd:string" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
E-Mail sender address. Ignored for all but mailto: recipient URIs.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MMessageContent" type="xsd:string" minOccurs="1"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Message Content.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MSubject" type="xsd:string" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Message Subject. Ignored for all but mailto: URIs
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MDeliveryReportRecipientURI" type="xsd:anyURI" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
URI to send a delivery report to. May be of one of the following schemes:
mailto:, http:, https:. Reports to mailto: URIs are sent as plaintext,
reports to http(s) URIs are sent as SOAP requests following the
MessageGatewayClient service definition.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MKeepalive" type="tns:TKeepalive" minOccurs="0"
maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Container for keepalive information. May be missing.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepalive">
<xsd:annotation>
<xsd:documentation>Type containing keeplive information.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MKeepaliveTimeout" type="xsd:double">
<xsd:annotation>
<xsd:documentation>
Keepalive timeout. The keepalive timeout spezifies how long the sending of
a message will be delayed waiting for keepalive updates. If a keepalive
update is received during this period, the timeout will be reset. If not,
the message will be sent after the timeout has expired.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MKeepaliveErrorPolicy" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Policy to comply to in case of system errors. Valid values are "suppress"
and "report". If the policy is set to "suppress", keepalive messages will
not be sent to their recipients in case of partial system failure, even if
the keepalive has expired. This may result in "false negatives", i.e.
messages may not be sent, even though their keepalive has expired. If the
value is "report", keepalive messages will be sent from any cluster node.
This may result in "false positive" alerts.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="suppress"></xsd:enumeration>
<xsd:enumeration value="report"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TMessageID">
<xsd:annotation>
<xsd:documentation>Type containing a message ID.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessageID" type="xsd:string" minOccurs="1" maxOccurs="1"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepliveMessage">
<xsd:annotation>
<xsd:documentation>
Type containing all elements of a keppalive update / remove request.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessageID" type="xsd:string" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The ID for the message to update / remove
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="MAction" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The action to perform. Valid values are: "remove", "update". On "remove",
the message with the ID specified will be removed from the queue, thus it
will never be sent, even if it's timeout expires. On "update" the
keepalive timeout of the corresponding message will be reset.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="remove"></xsd:enumeration>
<xsd:enumeration value="update"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="KeepaliveMessage" type="tns:TKeepaliveMessageRequest">
<xsd:annotation>
<xsd:documentation>Keepalive message request element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="KeepaliveMessageResponse" type="tns:TMessageID">
<xsd:annotation>
<xsd:documentation>Response element for a keepalive request</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="EnqueueMessageResponse" type="tns:TMessageID">
<xsd:annotation>
<xsd:documentation>Enqueue message response element</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="TEnqueueMessage">
<xsd:annotation>
<xsd:documentation>
A complex type containing one element: The message to enqueue.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MMessage" type="tns:TMessage">
<xsd:annotation>
<xsd:documentation>
Element containing a message to enqueue.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TKeepaliveMessageRequest">
<xsd:annotation>
<xsd:documentation>
A complex type containing one element: The keepalive message to process.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="MKeepaliveMessage" type="tns:TKeepliveMessage">
<xsd:annotation>
<xsd:documentation>
Element containing a keepalive message to process.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="EnqueueMessageRequest">
<wsdl:part name="parameters" element="tns:EnqueueMessage">
<wsdl:documentation>inputparameters for EnqueueMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="EnqueueMessageResponse">
<wsdl:part name="parameters" element="tns:EnqueueMessageResponse">
<wsdl:documentation>outputparameters for EnqueueMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="KeepaliveMessageRequest">
<wsdl:part name="parameters" element="tns:KeepaliveMessage">
<wsdl:documentation>input parameters for KeepaliveMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:message name="KeepaliveMessageResponse">
<wsdl:part name="parameters" element="tns:KeepaliveMessageResponse">
<wsdl:documentation>output parameters for KeepaliveMessag</wsdl:documentation>
</wsdl:part>
</wsdl:message>
<wsdl:portType name="MGWPortType">
<wsdl:documentation>
generic port type for all methods required for sending messages over the mosaic
message gatewa
</wsdl:documentation>
<wsdl:operation name="EnqueueMessage">
<wsdl:documentation>
This method is used to enqueue a normal (immediate send) or a delayed message with
keepalive functionality.
</wsdl:documentation>
<wsdl:input message="tns:EnqueueMessageRequest"></wsdl:input>
<wsdl:output message="tns:EnqueueMessageResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeepaliveMessage">
<wsdl:documentation>
This method is used to update or remove a
keepalive message.
</wsdl:documentation>
<wsdl:input message="tns:KeepaliveMessageRequest"></wsdl:input>
<wsdl:output message="tns:KeepaliveMessageResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MGWBinding" type="tns:MGWPortType">
<wsdl:documentation>Generic binding for all (SOAP) port</wsdl:documentation>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="EnqueueMessage">
<soap:operation soapAction="http://www.example.org/MessageGateway2/EnqueueMessage" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeepaliveMessage">
<soap:operation
soapAction="http://www.example.org/MessageGateway2/KeepaliveMessage" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MessageGateway">
<wsdl:documentation>
Web Service for sending messages over the mosaic message gatewa
</wsdl:documentation>
<wsdl:port name="HTTPPort" binding="tns:MGWBinding">
<wsdl:documentation>HTTP(S) port for the mosaic message gatewa</wsdl:documentation>
<soap:address location="https://www.example.org/MessageGateway/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>};
}
+3 -15
View File
@@ -1,4 +1,4 @@
use Test::More tests => 10; use Test::More tests => 7;
use strict; use strict;
use warnings; use warnings;
use diagnostics; use diagnostics;
@@ -26,22 +26,10 @@ ok( $soap = SOAP::WSDL->new(
wsdl => 'file:///' . $path . '/acceptance/wsdl/' . $name . '.wsdl' wsdl => 'file:///' . $path . '/acceptance/wsdl/' . $name . '.wsdl'
), 'Instantiated object' ); ), 'Instantiated object' );
ok( $soap->wsdlinit(), 'parsed WSDL' );
ok( ($soap->servicename('testService') ), 'set service' ); ok( ($soap->servicename('testService') ), 'set service' );
ok( ($soap->portname('testPort') ) ,'set portname'); ok( ($soap->portname('testPort2') ) ,'set portname');
ok( $soap->wsdlinit(), 'parsed WSDL' );
ok( ($soap->portname() eq 'testPort' ),
"Found first port definition" );
ok( ($soap->portname('testPort2') ),
"Found second port definition (based on URL)" );
ok( ($soap->portname('testPort3') ),
"Found third port definition (based on Name)" );
ok( $soap->wsdlinit( servicename => 'testService', portname => 'testPort'), 'parsed WSDL' ); ok( $soap->wsdlinit( servicename => 'testService', portname => 'testPort'), 'parsed WSDL' );
$soap->_wsdl_init_methods();
ok( ($soap->portname() eq 'testPort' ), 'found port passed to wsdlinit'); ok( ($soap->portname() eq 'testPort' ), 'found port passed to wsdlinit');
+3 -7
View File
@@ -59,13 +59,11 @@ TODO: {
eval eval
{ {
$xml = $soap->serializer->method( $xml = $soap->call('test',
$soap->call('test',
testAll => { testAll => {
Test1 => 'Test 1', Test1 => 'Test 1',
Test2 => [ 'Test 2', 'Test 3' ] Test2 => [ 'Test 2', 'Test 3' ]
} }
)
); );
}; };
@@ -74,13 +72,11 @@ ok( ($@ =~m/illegal\snumber\sof\selements/),
); );
eval { eval {
$xml = $soap->serializer->method( $xml = $soap->call('test',
$soap->call('test',
testAll => { testAll => {
Test1 => 'Test 1', Test1 => 'Test 1',
} }
) );
)
}; };
ok($@, 'Died on illegal number of elements (not enough)'); ok($@, 'Died on illegal number of elements (not enough)');
+43
View File
@@ -0,0 +1,43 @@
use Test::More tests => 4;
use strict;
use warnings;
use lib '../lib';
use lib 't/lib';
use lib 'lib';
use Cwd;
use File::Basename;
my $path = cwd();
my $name = basename $0;
$name =~s/\.t$//;
$name =~s/^t\///;
$path =~s{(/t)?/SOAP/WSDL}{}xms;
use_ok(qw/SOAP::WSDL/);
print "# SOAP::WSDL Version: $SOAP::WSDL::VERSION\n";
my $xml;
my $soap;
#2
ok( $soap = SOAP::WSDL->new(
wsdl => 'file://' . $path . '/t/acceptance/wsdl/' . $name . '.wsdl',
readable => 1,
no_dispatch => 1,
), 'Instantiated object' );
ok ($xml = $soap->call('test',
testAll => {
Test2 => 'Test2',
TestRef => 'TestRef'
}
), 'Serialized complexType' );
is $xml, q{<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ><SOAP-ENV:Body><testAll>
<TestRef>TestRef</TestRef>
<Test2>Test2</Test2>
</testAll>
</SOAP-ENV:Body></SOAP-ENV:Envelope>}
, 'element ref="" serialization';
+5 -8
View File
@@ -35,8 +35,6 @@ ok( $soap->wsdlinit(
servicename => 'testService', servicename => 'testService',
), 'parsed WSDL' ); ), 'parsed WSDL' );
$soap->no_dispatch(1); $soap->no_dispatch(1);
$soap->serializer()->envprefix('SOAP-ENV');
$soap->serializer()->encprefix('SOAP-ENC');
#4 #4
ok $xml = $soap->call('test', ok $xml = $soap->call('test',
@@ -46,15 +44,15 @@ ok $xml = $soap->call('test',
} }
), 'Serialized complexType'; ), 'Serialized complexType';
TODO: {
local $TODO = "not implemented yet";
#5 #5
eval eval
{ {
$xml = $soap->serializer->method( $xml = $soap->call('test',
$soap->call('test',
testSequence => { testSequence => {
Test1 => 'Test 1', Test1 => 'Test 1',
} }
)
); );
}; };
ok( ($@), ok( ($@),
@@ -64,15 +62,14 @@ ok( ($@),
#6 #6
eval eval
{ {
$xml = $soap->serializer->method( $xml = $soap->call('test',
$soap->call('test',
testSequence => { testSequence => {
Test1 => 'Test 1', Test1 => 'Test 1',
Test2 => [ 1, 2, 3, ] Test2 => [ 1, 2, 3, ]
} }
)
); );
}; };
ok( ($@), ok( ($@),
"Died on illegal number of elements" "Died on illegal number of elements"
); );
};
+11 -1
View File
@@ -1,4 +1,4 @@
use Test::More tests => 6; use Test::More tests => 8;
use strict; use strict;
use warnings; use warnings;
use lib '../lib'; use lib '../lib';
@@ -39,6 +39,16 @@ ok ($xml = $soap->call('test',
testElement1 => 'Test' testElement1 => 'Test'
), 'Serialized (simple) element' ); ), 'Serialized (simple) element' );
ok ($xml = $soap->call('testRef',
testElementRef => 'Test'
), 'Serialized (simple) element' );
is $xml
, q{<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ><SOAP-ENV:Body><testElementRef xmlns="urn:Test">Test</testElementRef>
</SOAP-ENV:Body></SOAP-ENV:Envelope>}
, 'element ref serialization result'
;
TODO: { TODO: {
local $TODO="implement min/maxOccurs checks"; local $TODO="implement min/maxOccurs checks";
-83
View File
@@ -1,83 +0,0 @@
#!/usr/bin/perl -w
use strict;
use Test::More tests=> 5;
use Time::HiRes qw( gettimeofday tv_interval );
use lib '../..';
use Data::Dumper;
use Cwd;
use File::Basename;
use_ok qw/ SOAP::WSDL /;
use Benchmark;
print "# Testing SOAP::WSDL ". $SOAP::WSDL::VERSION."\n";
print "# Performance test with simple WSDL file\n";
my $soap;
my $data = {
sayHello => {
name => 'Mein Name',
givenName => 'Vorname',
}
};
my $name = basename( $0 );
$name =~s/\.(t|pl)$//;
my $path = cwd;
$path=~s{(/t)?/SOAP/WSDL}{}xms;
my $cacheDir;
if ($^O =~ m/Win/)
{
$cacheDir = 'C:/Temp/WSDL';
}
else
{
$cacheDir = '/tmp/';
}
my $t0 = [gettimeofday];
ok(
$soap=SOAP::WSDL->new(
wsdl => "file://$path/t/acceptance/wsdl/10_helloworld.asmx.xml",
no_dispatch => 1
),
"Create SOAP::WSDL object (".tv_interval ( $t0, [gettimeofday]) ."ms)" );
$soap->proxy('http://helloworld/helloworld.asmx');
$t0 = [gettimeofday];
eval{
$soap->wsdlinit(
caching => 1,
cache_directory => $cacheDir,
servicename => 'Service1' ) };
unless ($@) {
pass("wsdl file init (".tv_interval ( $t0, [gettimeofday]) ."s)");
} else {
fail( $@ );
}
$soap->readable(1);
$t0 = [gettimeofday];
ok( $soap->call("sayHello" , %{ $data }),
"1 x call pre-work (".tv_interval ( $t0, [gettimeofday]) ."s)") ;
$t0 = [gettimeofday];
ok($soap->call(sayHello => %{ $data }),
"1 x call pre-work (".tv_interval ( $t0, [gettimeofday]) ."s)" );
timethis 1000, sub { $soap->call(sayHello => %{ $data }) };
__END__
$t0 = [gettimeofday];
for (my $i=1; $i<100; $i++)
{
$soap->call(sayHello => %{ $data });
}
ok(1, "100 x call pre-work (".tv_interval ( $t0, [gettimeofday]) ."s)");
chdir $cwd;
@@ -0,0 +1,32 @@
use Test::More tests => 4;
use strict;
use warnings;
use lib '../lib';
use Date::Parse;
use Date::Format;
sub timezone {
my @time = strptime shift;
my $tz = strftime('%z', @time);
substr $tz, -2, 0, ':';
return $tz;
}
use_ok('SOAP::WSDL::XSD::Typelib::Builtin::dateTime');
print "# timezone is " . timezone( scalar localtime(time) ) . "\n";
my $obj;
my %dates = (
'2007-12-31 12:32' => '2007-12-31T12:32:00',
'2007-08-31 00:32' => '2007-08-31T00:32:00',
'30 Aug 2007' => '2007-08-30T00:00:00',
);
while (my ($date, $converted) = each %dates ) {
$obj = SOAP::WSDL::XSD::Typelib::Builtin::dateTime->new();
$obj->set_value( $date );
is $obj->get_value() , $converted . timezone($date), 'conversion with timezone';
}
$obj->set_value('2007-12-31T00:00:00.0000000+01:00');
@@ -0,0 +1,25 @@
use Test::More tests => 3;
use strict;
use warnings;
use lib '../lib';
use_ok('SOAP::WSDL::XSD::Typelib::Builtin::time');
my $obj;
$obj = SOAP::WSDL::XSD::Typelib::Builtin::time->new();
$obj->set_value( '12:23:03' );
is $obj->get_value() , '12:23:03+01:00', 'conversion';
$obj->set_value( '12:23:03.12345+01:00' ), ;
is $obj->get_value() , '12:23:03.12345+01:00', 'no conversion';
# exit;
#~ use Benchmark;
#~ timethese 10000, {
#~ xml => sub { $obj->set_value('2037-12-31T00:00:00.0000000+01:00') },
#~ string => sub { $obj->set_value('2037-12-31') },
#~ }
@@ -0,0 +1,36 @@
use Test::More tests => 6;
use strict;
use warnings;
use lib '../lib';
use Date::Format;
use Date::Parse;
use_ok('SOAP::WSDL::XSD::Typelib::Builtin::date');
my $obj;
sub timezone {
my @time = strptime shift;
my $tz = strftime('%z', @time);
substr $tz, -2, 0, ':';
return $tz;
}
my %dates = (
'2007/12/31' => '2007-12-31',
'2007:08:31' => '2007-08-31',
'30 Aug 2007' => '2007-08-30',
);
while (my ($date, $converted) = each %dates ) {
$obj = SOAP::WSDL::XSD::Typelib::Builtin::date->new();
$obj->set_value( $date );
is $obj->get_value() , $converted . timezone($date), 'conversion';
}
$obj->set_value('2007-12-31T00:00:00.0000000+01:00');
is $obj->get_value() , '2007-12-31+01:00', 'conversion from XML dateTime';
$obj->set_value( '2037-12-31' );
is $obj->get_value() , '2037-12-31', 'no conversion on match';
+5 -14
View File
@@ -1,18 +1,13 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<definitions name="urn:Test" <definitions name="urn:Test" targetNamespace="urn:Test" xmlns:tns="urn:Test"
targetNamespace="urn:Test"
xmlns:tns="urn:Test"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
>
<types> <types>
<xsd:schema targetNamespace="urn:Test"> <xsd:schema targetNamespace="urn:Test">
<xsd:complexType name="testComplexTypeAll"> <xsd:complexType name="testComplexTypeAll">
<xsd:annotation> <xsd:annotation>
<xsd:documentation> <xsd:documentation>ComplexType Test</xsd:documentation>
ComplexType Test
</xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:all> <xsd:all>
<xsd:element name="Test1" type="xsd:string" /> <xsd:element name="Test1" type="xsd:string" />
@@ -22,9 +17,7 @@
<xsd:complexType name="testComplexTypeSequence"> <xsd:complexType name="testComplexTypeSequence">
<xsd:annotation> <xsd:annotation>
<xsd:documentation> <xsd:documentation>ComplexType Test</xsd:documentation>
ComplexType Test
</xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:sequence> <xsd:sequence>
<xsd:element name="Test1" type="xsd:string" minOccurs="1" /> <xsd:element name="Test1" type="xsd:string" minOccurs="1" />
@@ -42,9 +35,7 @@
</message> </message>
<portType name="testPort"> <portType name="testPort">
<operation name="test"> <operation name="test">
<documentation> <documentation>Test-Methode</documentation>
Test-Methode
</documentation>
<input message="tns:testRequest" /> <input message="tns:testRequest" />
<output message="tns:testResponse" /> <output message="tns:testResponse" />
@@ -0,0 +1,53 @@
<?xml version="1.0"?>
<definitions name="urn:Test" targetNamespace="urn:Test" xmlns:tns="urn:Test"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema targetNamespace="urn:Test">
<xsd:element name="TestElement" type="xsd:string" />
<xsd:element name="TestRef" ref="tns:TestElement" />
<xsd:complexType name="testComplexTypeRef">
<xsd:annotation>
<xsd:documentation>ComplexType Test</xsd:documentation>
</xsd:annotation>
<xsd:all>
<xsd:element name="TestRef" ref="tns:TestElement" />
<xsd:element name="Test2" type="xsd:string" minOccurs="1" />
</xsd:all>
</xsd:complexType>
</xsd:schema>
</types>
<message name="testRequest">
<part name="testAll" type="tns:testComplexTypeRef" />
</message>
<message name="testResponse">
<part name="testAll" type="tns:testComplexTypeRef" />
</message>
<portType name="testPort">
<operation name="test">
<documentation>Test-Methode</documentation>
<input message="tns:testRequest" />
<output message="tns:testResponse" />
</operation>
</portType>
<binding type="tns:testPort" name="testBinding">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="test">
<soap:operation soapAction="test">
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</soap:operation>
</operation>
</binding>
<service name="testService">
<port name="testPort" binding="tns:testBinding">
<soap:address location="http://127.0.0.1/testPort" />
</port>
</service>
</definitions>
+24
View File
@@ -10,11 +10,16 @@
<xsd:schema targetNamespace="urn:Test"> <xsd:schema targetNamespace="urn:Test">
<xsd:element name="testElement1" type="xsd:string" /> <xsd:element name="testElement1" type="xsd:string" />
<xsd:element name="testElement2" type="xsd:int" /> <xsd:element name="testElement2" type="xsd:int" />
<xsd:element name="testElementRef" ref="tns:testElement1" />
</xsd:schema> </xsd:schema>
</types> </types>
<message name="testRequest"> <message name="testRequest">
<part name="testAll" element="tns:testElement1"/> <part name="testAll" element="tns:testElement1"/>
</message> </message>
<message name="testRefRequest">
<part name="testAll" element="tns:testElementRef"/>
</message>
<message name="testResponse"> <message name="testResponse">
<part name="testAll" type="tns:testElement1"/> <part name="testAll" type="tns:testElement1"/>
</message> </message>
@@ -27,6 +32,14 @@
<input message="tns:testRequest"/> <input message="tns:testRequest"/>
<output message="tns:testResponse"/> <output message="tns:testResponse"/>
</operation> </operation>
<operation name="testRef">
<documentation>
Test-Methode
</documentation>
<input message="tns:testRefRequest"/>
<output message="tns:testResponse"/>
</operation>
</portType> </portType>
<binding type="tns:testPort" name="testBinding"> <binding type="tns:testPort" name="testBinding">
@@ -40,6 +53,17 @@
<soap:body use="literal"/> <soap:body use="literal"/>
</output> </output>
</soap:operation> </soap:operation>
</operation>
<operation name="testRef">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<soap:operation soapAction="testRef">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</soap:operation>
</operation> </operation>
</binding> </binding>
<service name="testService"> <service name="testService">