Provided by: libxml-compile-soap-perl_3.28+ds-1_all bug

NAME

       XML::Compile::SOAP - base-class for SOAP implementations

INHERITANCE

        XML::Compile::SOAP is extended by
          XML::Compile::SOAP11
          XML::Compile::SOAP12

SYNOPSIS

        ** SOAP1.[12] and WSDL1.1 over HTTP

        # !!! The next steps are only required when you do not have
        # !!! a WSDL. See XML::Compile::WSDL11 if you have a WSDL.
        # !!! Without WSDL file, you need to do a lot manually

        use XML::Compile::SOAP11::Client;
        my $client = XML::Compile::SOAP11::Client->new;
        $client->schemas->importDefinitions(...);

        use XML::Compile::Util qw/pack_type/;
        my $h1el = pack_type $myns, $some_element;
        my $b1el = "{$myns}$other_element";  # same, less clean

        my $encode_query = $client->compileMessage
          ( 'SENDER'
          , style    => 'document'           # default
          , header   => [ h1 => $h1el ]
          , body     => [ b1 => $b1el ]
          , destination    => [ h1 => 'NEXT' ]
          , mustUnderstand => 'h1'
          );

        my $decode_response = $client->compileMessage
          ( 'RECEIVER'
          , header   => [ h2 => $h2el ]
          , body     => [ b2 => $b2el ]
          , faults   => [ ... ]
          );

        my $transport = XML::Compile::Transport::SOAPHTTP
           ->new(address => $server);
        my $http = $transport->compileClient(action => ...);

        my @query    = (h1 => ..., b1 => ...);
        my $request  = $encode_query->(@query);
        my ($response, $trace) = $http->($request);
        my $answer   = $decode_response->($response);

        use Data::Dumper;
        warn Dumper $answer;     # discover a HASH with h2 and b2!

        if($answer->{Fault}) ... # when an error was reported

        # Simplify your life: combine above into one call
        # Also in this case: if you have a WSDL, this is created
        # for you.   $wsdl->compileClient('MyFirstCall');

        my $call   = $client->compileClient
          ( kind      => 'request-response'  # default
          , name      => 'MyFirstCall'
          , encode    => $encode_query
          , decode    => $decode_response
          , transport => $http
          );

        # !!! Usage, with or without WSDL file the same

        my $result = $call->(@query)          # SCALAR only the result
        print $result->{h2}->{...};
        print $result->{b2}->{...};

        my ($result, $trace) = $call->(...);  # LIST will show trace
        # $trace is an XML::Compile::SOAP::Trace object

DESCRIPTION

       This module handles the SOAP protocol.  The first implementation is SOAP1.1
       (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/), which is still most often used.  The
       SOAP1.2 definition (http://www.w3.org/TR/soap12/) is provided via the separate
       distribution XML::Compile::SOAP12.

       Be aware that there are three kinds of SOAP:

       1.  Document style (literal) SOAP, where there is a WSDL file which explicitly types all
           out-going and incoming messages.  Very easy to use.

       2.  RPC style SOAP literal.  The body of the message has an extra element wrapper, but the
           content is also well defined.

       3.  RPC style SOAP encoded.  The sent data is nowhere described formally.  The data is
           constructed in some ad-hoc way.

       Don't forget to have a look at the examples in the examples/ directory included in the
       distribution.

       Please support my development work by submitting bug-reports, patches and (if available) a
       donation.

METHODS

   Constructors
       $obj->new(%options)
           Create a new SOAP object.  You have to instantiate either the SOAP11 or SOAP12 sub-
           class of this, because there are quite some differences (which can be hidden for you)

            -Option    --Default
             media_type  application/soap+xml
             schemas     created internally

           media_type => MIMETYPE
           schemas => "XML::Compile::Cache" object
             Use this when you have already processed some schema definitions.  Otherwise, you
             can add schemas later with "$soap->schemas->importDefinitions()" The Cache object
             must have "any_element" and "any_attribute" set to 'ATTEMPT'

       XML::Compile::SOAP->register($uri, $envns)
           Declare an operation type, being an (WSDL specific) $uri and envelope namespace.

   Accessors
       $obj->mediaType()
       $obj->schemas()
           Returns the XML::Compile::Cache object which contains the knowledge about the types.

       $obj->version()

   Single message
       $obj->compileMessage( <'SENDER'|'RECEIVER'>, %options )
           The payload is defined explicitly, where all headers and bodies are described in
           detail.  When you have a WSDL file, these ENTRIES are generated automatically, but can
           be modified and extended (WSDL files are often incomplete)

           To make your life easy, the ENTRIES use a label (a free to choose key, the part name
           in WSDL terminology), to ease relation of your data with the type where it belongs to.
           The element of an entry (the value) is defined as an "any" element in the schema, and
           therefore you will need to explicitly specify the element to be processed.

           As %options, you can specify any listed here, but also anything which is accepted by
           XML::Compile::Schema::compile(), like "sloppy_integers => 1" and hooks.  These are
           applied to all header and body elements (not to the SOAP wrappers)

            -Option        --Default
             body            []
             destination     []
             faults          []
             header          undef
             mustUnderstand  []
             procedure       undef
             role            ULTIMATE
             roles           []

           body => ENTRIES|HASH
             ARRAY of PAIRS, defining a nice LABEL (free of choice but unique, also w.r.t. the
             header and fault ENTRIES) and an element type name or CODE reference.  The LABEL
             will appear in the Perl HASH only, to be able to refer to a body element in a simple
             way.

           destination => ARRAY-OF-PAIRS
             Writers only.  Indicate who the target of the header entry is.  By default, the end-
             point is the destination of each header element.

             The ARRAY contains a LIST of key-value pairs, specifying an entry label followed by
             an actor (soap1.1) or role (soap1.2) URI.  You may use the predefined actors/roles,
             like 'NEXT'.  See roleURI() and roleAbbreviation().

           faults => ENTRIES|HASH
             The SOAP1.1 and SOAP1.2 protocols define fault entries in the answer.  Both have a
             location to add your own additional information: the type(-processor) is to
             specified here, but the returned information structure is larger and differs per
             SOAP implementation.

           header => ENTRIES|HASH
             ARRAY of PAIRS, defining a nice LABEL (free of choice but unique) and an element
             type name.  The LABEL will appear in the Perl HASH, to refer to the element in a
             simple way.

             The element type is used to construct a reader or writer.  You may also create your
             own reader or writer, and then pass a compatible CODE reference.

           mustUnderstand => STRING|ARRAY-OF-STRING
             Writers only.  The specified header entry labels specify which elements must be
             understood by the destination.  These elements will get the "mustUnderstand"
             attribute set to 1 (soap1.1) or "true" (soap1.2).

           procedure => TYPE
             Required in rpc style, when there is no "body" which contains the procedure name
             (when the RPC info does not come from a WSDL)

           role => URI|ARRAY-OF-URI
             Readers only.  One or more URIs, specifying the role(s) you application has in the
             process.  Only when your role contains "ULTIMATE", the body is parsed.  Otherwise,
             the body is returned as uninterpreted XML tree.  You should not use the role "NEXT",
             because every intermediate node is a "NEXT".

             All understood headers are parsed when the "actor" (soap1.1) or "role" (soap1.2)
             attribute address the specified URI.  When other headers emerge which are not
             understood but carry the "mustUnderstood" attribute, an fault is returned
             automatically.  In that case, the call to the compiled subroutine will return
             "undef".

           roles => ARRAY-OF-URI
             Alternative for option "role"

       $obj->messageStructure($xml)
       XML::Compile::SOAP->messageStructure($xml)
           Returns a HASH with some collected information from a complete SOAP message
           (XML::LibXML::Document or XML::LibXML::Element).  Currenty, the HASH contains a
           "header" and a "body" key, with each an ARRAY of element names which where found in
           the header resp. body.

   Helpers
   Transcoding
       $obj->replyMustUnderstandFault($type)
           Produce an error structure to be returned to the sender.

       $obj->roleAbbreviation($uri)
           Translate a role $uri into a simple string, if predefined.  See roleURI().

       $obj->roleURI($uri|STRING)
           Translates actor/role/destination abbreviations into URIs. Various SOAP protocol
           versions have different pre-defined STRINGs, which can be abbreviated for readibility.
           Returns the unmodified $uri in all other cases.

           SOAP11 only defines "NEXT".  SOAP12 defines "NEXT", "NONE", and "ULTIMATE".

DETAILS

   SOAP introduction
       Although the specifications of SOAP1.1 and WSDL1.1 are thin, the number of special
       constructs are many. And, of course, all are poorly documented.  SOAP 1.2 has a much
       better specification, but is not used a lot.  I have not seen WSDL2 in real life.

       WSDL defines two kinds of messages: document style SOAP and rpc style SOAP.  In document
       style SOAP, the messages are described in great detail in the WSDL: the message components
       are all defined in Schema's. The worst things you can (will) encounter are "any" schema
       elements which require additional manual processing.

       "RPC Literal" behaves very much the same way as document style soap, but has one extra
       wrapper inside the Body of the message.

       "Encoded SOAP-RPC", however, is a very different ball-game.  It is simple to use with
       strongly typed languages, to exchange data when you create both the client software and
       the server software.  You can simply autogenerate the data encoding.  Clients written by
       third parties have to find the documentation on how to use the encoded  RPC call in some
       other way... in text, if they are lucky; the WSDL file does not contain the prototype of
       the procedures, but that doesn't mean that they are free-format.

       Encoded RPC messages are shaped to the procedures which are being called on the server.
       The body of the sent message contains the ordered list of parameters to be passed as 'in'
       and 'in/out' values to the remote procedure.  The body of the returned message lists the
       result value of the procedure, followed by the ordered 'out' and 'in/out' parameters.

   Supported servers
       Only the commercial hype speaks about SOAP in very positive words.  However, the "industry
       quality" of these modern "technologies" clearly demonstrates the lack of education and
       experience most programmers and designers have.  This is clearly visible in many, many
       bugs you will encounter when working with schemas and WSDLs.

       Interoperability of SOAP clients and servers is more "trial and error" and "manually
       fixing" than it should be.  For instance, a server may report internal server errors back
       to the client... but a WSDL does not tell you which namespace/schema is used for these
       errors.  Both BEA and SharePoint servers produce illegal SOAP responses!  It is a sad
       story.

       To be able to install some fixes, you can specify a server type via
       XML::Compile::SOAP::Operation::new(server_type), XML::Compile::WSDL11::new(server_type),
       or [3.06] XML::Compile::WSDL11::operations(server_type).

       The following server types are currently understood:

       •   "BEA", Oracle

       •   "SharePoint", MicroSoft

       •   "XML::Compile::Daemon"

       Examples:

         my $wsdl = XML::Compile::WSDL11->new($wsdlfn, server_type => 'SharePoint');
         my $op   = XML::Compile::SOAP11::Operation->new(..., server_type => 'BEA');
         my @op   = XML::Compile::WSDL11->operations(server_type => 'SharePoint')

       [3.17] Be warned: the licenses of some server_type schema's are unknown or unclear.  At
       least, they touch commercial products hence can better not be released in a (Debian) Linux
       distribution, even not as non-free.  Therefore, you need to install XML::Compile::Licensed
       from CPAN yourself.

   Naming types and elements
       XML uses namespaces: URIs which are used as constants, grouping a set of type and element
       definitions.  By using name-spaces, you can avoid name clashes, which have frustrated many
       projects in the past when they grew over a certain size... at a certain size, it becomes
       too hard to think of good distinguishable names.  In such case, you must be happy when you
       can place those names in a context, and use the same naming in separate contexts without
       confusion.

       That being said: XML supports both namespace- and non-namespace elements and schema's; and
       of cause many mixed cases.  It is by far preferred to use namespace schemas only. In a
       schema XSD file, look for the "targetNamespace" attribute of the "schema" element: if
       present, it uses namespaces.

       In XML data, it is seen as a hassle to write the full length of the URI each time that a
       namespace is addressed.  For this reason, prefixes are used as abbreviations for the
       namespace URI.  In programs, you can simply assign short variable names to long URIs, so
       we do not need that trick.

       Within your program, you use

         $MYNS = 'long URI of namespace';
         ... $type => "{$MYNS}typename" ...

       or nicer

         use XML::Compile::Util qw/pack_type/;
         use constant MYNS => 'some uri';
         ... $type => pack_type(MYNS, 'typename') ...

       The XML::Compile::Util module provides a helpful methods and constants, as does the
       XML::Compile::SOAP::Util.

   Client and Server implementations
       To learn how to create clients in SOAP, read the DETAILS section in
       XML::Compile::SOAP::Client.  The client implementation is platform independent.

       Servers can be created with the external XML::Compile::SOAP::Daemon distribution. Those
       servers are based on Net::Server. Can be used to create a test-server in a few minutes...
       or production server.

       Don't forget to have a look at the examples in the examples/ directory included in the
       distribution.

   Use of wildcards (any and anyAttribute)
       Start reading about wildcards in XML::Compile. When you receive a message which contains
       "ANY" elements, an attempt will be made to decode it automatically. Sending messages which
       contain "ANY" fields is harder... you may try hooks or something more along these lines:

          my $doc = XML::LibXML::Document->new('1.0', 'UTF-8');
          my $type    = pack_type $ns, $local;
          my $node    = $wsdl->writer($type)->($doc, $value);
          my $message = { ..., $type => $node };

          my $call = $wsdl->compileClient('myOpToCall');
          my ($answer, $trace) = $call->(_doc => $doc, message => $message);

       Here, $type is the type of the element which needs to be filled in on a spot where the
       schema defines an "ANY" element. You need to include the full typename as key in the HASH
       (on the right spot) and a fully prepared $node, an XML::LibXML::Element, as the value.

       You see that the $doc which is created to produce the special node in the message is also
       passed to the $call. The call produces the message which is sent and needs to use the same
       document object as the node inside it. The chances are that when you forget to pass the
       $doc it still works... but you may get into characterset problems and such.

SEE ALSO

       This module is part of XML-Compile-SOAP distribution version 3.28, built on August 01,
       2022. Website: http://perl.overmeer.net/CPAN/

LICENSE

       Copyrights 2007-2022 by [Mark Overmeer <markov@cpan.org>]. For other contributors see
       ChangeLog.

       This program is free software; you can redistribute it and/or modify it under the same
       terms as Perl itself.  See http://dev.perl.org/licenses/