home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / Chip_2000-05_cd1.bin / zkuste / Perl / ActivePerl-5.6.0.613.msi / 䆊䌷䈹䈙䏵-䞅䞆䞀㡆䞃䄦䠥 / _a2c56a9795dd2047341ee25e67a96ebb < prev    next >
Text File  |  2000-03-15  |  9KB  |  291 lines

  1. package SOAP::OutputStream;
  2.  
  3. use strict;
  4. use vars qw($VERSION);
  5. use SOAP::Defs;
  6.  
  7. $VERSION = '0.23';
  8.  
  9. ########################################################################
  10. # constructor
  11. ########################################################################
  12. sub new {
  13.     my ($class) = @_;
  14.     my $self = {
  15.         tag             => undef,   # the closing tag we write at term
  16.         packager        => undef,   # if we're not a package, this points to an ancestor who is
  17.                                     # and implements the functions for maintaining objrefs
  18.         soap_prefix     => '',      # this allows us to turn on/off namespace support
  19.         envelope        => 0,       # manages ids and namespaces
  20.         depth           => 1,       # use a one-based depth simply for consistency
  21.                                     # with expat on the other side
  22.         print_fcn       => undef,
  23.         seal_package    => undef,   # do we need to seal our package on term or not?
  24.     };
  25.     bless $self, $class;
  26. }
  27.  
  28. ########################################################################
  29. # interface ISoapStream
  30. ########################################################################
  31. sub simple_accessor {
  32. #   my ($self, $accessor_uri, $accessor_name, $typeuri, $typename, $content) = @_;
  33.     &_simple_accessor;
  34. }
  35.  
  36. sub compound_accessor {
  37. #    my ($self, $accessor_uri, $accessor_name, $typeuri, $typename, $is_package) = @_;
  38.     &_compound_accessor;
  39. }
  40.  
  41. sub reference_accessor {
  42. #    my ($self, $accessor_uri, $accessor_name, $object) = @_;
  43.     &_reference_accessor;
  44. }
  45.  
  46. sub term {
  47. #   my ($self) = @_;
  48.     &_term;
  49. }
  50.  
  51. ########################################################################
  52. # implementation
  53. ########################################################################
  54. sub _simple_accessor {
  55.     my ($self, $accessor_uri, $accessor_name, $typeuri, $typename, $content) = @_;
  56.  
  57.     my $attrs = '';
  58.  
  59.     my $nsprefix = '';
  60.     if (defined $accessor_uri) {
  61.         (my $nsdecl, $nsprefix) = $self->{envelope}->_get_ns_decl_and_prefix($accessor_uri);
  62.         $attrs .= $nsdecl if $nsdecl;
  63.     }
  64.     my $tag = $nsprefix . $accessor_name;
  65.  
  66.     if (defined $typename) {
  67.         my $nsprefix = '';
  68.         if (defined $typeuri) {
  69.             (my $nsdecl, $nsprefix) = $self->{envelope}->_get_ns_decl_and_prefix($typeuri);
  70.         
  71.             $attrs .= $nsdecl if $nsdecl;
  72.         }
  73.         $attrs .= qq[ xsi:type="$nsprefix$typename"];
  74.     }
  75.  
  76.     $self->_print(qq[<$tag$attrs>$content</$tag>]);
  77. }
  78.  
  79. sub _compound_accessor {
  80.     my ($self, $accessor_uri, $accessor_name, $typeuri, $typename, $is_package) = @_;
  81.  
  82.     my $sp = $self->{soap_prefix};
  83.  
  84.     my $attrs = '';
  85.  
  86.     my $packager = $is_package ? $self->_create_new_package() : $self->{packager};
  87.     my $envelope = $self->{envelope};
  88.  
  89.     my $new_depth = $self->{depth} + 1;
  90.  
  91.     my $stream = SOAP::OutputStream->new();
  92.     $stream->{packager}       = $packager;
  93.     $stream->{envelope}       = $self->{envelope};
  94.     $stream->{depth}          = $new_depth;
  95.     $stream->{print_fcn}      = $self->{print_fcn};
  96.     $stream->{soap_prefix}    = $self->{soap_prefix};
  97.     $stream->{seal_package}   = $is_package;
  98.  
  99.     my $nsprefix = '';
  100.     if (defined $accessor_uri) {
  101.         (my $nsdecl, $nsprefix) = $self->{envelope}->_push_ns_decl_and_prefix($accessor_uri, $new_depth);
  102.         $attrs .= $nsdecl if $nsdecl;
  103.     }
  104.     my $tag = $nsprefix . $accessor_name;
  105.  
  106.     $stream->{tag} = $tag;
  107.  
  108.     if (defined $typename) {
  109.         my $nsprefix = '';
  110.         if (defined $typeuri) {
  111.             (my $nsdecl, $nsprefix) = $self->{envelope}->_push_ns_decl_and_prefix($typeuri, $new_depth);
  112.         
  113.             $attrs .= $nsdecl if $nsdecl;
  114.         }
  115.         $attrs .= qq[ xsi:type="$nsprefix$typename"];
  116.     }
  117.  
  118.     $self->_print(qq[<$tag$attrs>]);
  119.  
  120.     $stream;
  121. }
  122.  
  123. sub _reference_accessor {
  124.     my ($self, $accessor_uri, $accessor_name, $object) = @_;
  125.  
  126.     my $sp = $self->{soap_prefix};
  127.  
  128.     my $attrs = '';
  129.     if (defined $object) {
  130.         my $id = $self->{packager}->register($self->{envelope}, $object);
  131.  
  132.         $attrs = qq[ ${sp}$soap_href="#$id"];
  133.     }
  134.     else {
  135.         $attrs .= ' xsi:null="1"';
  136.     }
  137.  
  138.     my $nsprefix = '';
  139.     if (defined $accessor_uri) {
  140.         (my $nsdecl, $nsprefix) = $self->{envelope}->_get_ns_decl_and_prefix($accessor_uri);
  141.         $attrs .= $nsdecl if $nsdecl;
  142.     }
  143.     my $tag = $nsprefix . $accessor_name;
  144.  
  145.     if ($accessor_uri) {
  146.         $self->_clean_up_namespace_dictionary($self->{depth} + 1);
  147.     }
  148.  
  149.     $self->_print(qq[<$tag$attrs />]);
  150. }
  151.  
  152. sub _term {
  153.     my ($self) = @_;
  154.  
  155.     if ($self->{seal_package}) {
  156.         $self->{packager}->seal($self->{envelope});
  157.     }
  158.  
  159.     my $tag = $self->{tag};
  160.     $self->_print(qq[</$tag>]);
  161.  
  162.     $self->_clean_up_namespace_dictionary($self->{depth});
  163. }
  164.  
  165. ########################################################################
  166. # misc
  167. ########################################################################
  168. sub _create_new_package {
  169.     my ($self) = @_;
  170.     SOAP::Packager->new($self->{soap_prefix},
  171.                         $self->{depth},
  172.                         $self->{print_fcn});
  173. }
  174.  
  175. sub _clean_up_namespace_dictionary {
  176.     my ($self, $depth) = @_;
  177.     $self->{envelope}->_clean_up_namespace_dictionary($depth);
  178. }
  179.  
  180. sub _print {
  181.     my ($self, $s) = @_;
  182.     
  183.     $self->{print_fcn}->($s);
  184. }
  185.  
  186. 1;
  187. __END__
  188.  
  189.  
  190. =head1 NAME
  191.  
  192. SOAP::OutputStream - Writes SOAP fragments
  193.  
  194. =head1 SYNOPSIS
  195.  
  196.     # note that we need SOAP::Envelope to bootstrap
  197.     use SOAP::Envelope;
  198.  
  199.     sub output_fcn {
  200.         my $string = shift;
  201.         print $string;
  202.     }
  203.  
  204.     my $namespaces_to_preload = ["urn:foo", "urn:bar"];
  205.     my $env = SOAP::Envelope->new(\&output_fcn,
  206.                                   $namespaces_to_preload);
  207.     my $body = $env->body();
  208.     
  209.     # here is where we actually use SOAP::OutputStream
  210.     my $child = $body->compound_accessor("urn:quux", "reverse_string", undef, undef, 0);
  211.  
  212.     $child->simple_accessor(undef, "s", undef, undef, "dlrow olleH");
  213.  
  214.     $child->term();
  215.     $body->term();
  216.     $env->term();
  217.  
  218. This creates the following XML:
  219.  
  220. <s:Envelope xmlns:s="urn:schemas-xmlsoap-org:soap.v1" 
  221.             xmlns:xsi="http://www.w3.org/1999/XMLSchema" 
  222.             xmlns:n1="urn:foo" 
  223.             xmlns:n2="urn:bar">
  224.   <s:Body>
  225.     <n3:reverse_string xmlns:n3="urn:quux">
  226.       <s>dlrow olleH</s>
  227.     </n3:reverse_string>
  228.   </s:Body>
  229. </s:Envelope>
  230.  
  231.  
  232. =head1 DESCRIPTION
  233.  
  234. SOAP::OutputStream encapsulates the details of writing SOAP packets into a few easy
  235. to use functions. In order to bootstrap a SOAP stream (and get your first
  236. SOAP::OutputStream reference), you'll need to use SOAP::Envelope, as shown in
  237. the example above.
  238.  
  239. =head2 The simple_accessor function
  240.  
  241. This function writes a simple accessor (e.g., a string or number, as opposed
  242. to a compound type). It takes two sets of URI/typenames, one for the accessor
  243. and one for the optional xsd:type attribute. At a minimum, you must specify the
  244. accessor_name and content.
  245.  
  246. =head2 The compound_accessor function
  247.  
  248. This function opens a new compound accessor (by writing an open XML tag), and
  249. returns a new SOAP::OutputStream that you should use to write the contents of that
  250. accessor. This function always creates nested elements. If you want to create
  251. an independent element, call reference_accessor instead. The is_package parameter
  252. allows you to open a new package at this node; the OutputStream will write all
  253. further independent elements at this level in the XML document, creating a
  254. standalone XML fragment within the SOAP envelope. The OutputStream will complain
  255. if all references within the package cannot be resolved when this node is closed.
  256. See the SOAP spec for details on packages.
  257.  
  258. =head2 The reference_accessor function
  259.  
  260. This function creates a reference (SOAP:href) node, and stores the specified
  261. object until the current package is closed, at which time a serializer is obtained
  262. for the object (based on its type) and is asked to serialize itself to
  263. a new stream at the level of the package. Note that if you're not using
  264. packages explicitly, then the system will perform this resolution and
  265. serialization when you switch from creating Headers to creating the Body,
  266. and once again when the Body is terminated. The object referenced is guaranteed
  267. to only be serialized once (assuming you've obeyed the SOAP rules for packages
  268. and Header/Body object reference sharing).
  269.  
  270. =head2 The term function
  271.  
  272. Call this function when you want to close the node you're working with.
  273. This does several things - it seals the package if the node you're using
  274. was created as a package, and it writes an end tag (along with doing some
  275. other internal bookeeping that's pretty important). Don't forget to call
  276. this function before opening a new sibling node.
  277.  
  278. =head1 DEPENDENCIES
  279.  
  280. SOAP::Defs
  281.  
  282. =head1 AUTHOR
  283.  
  284. Keith Brown
  285.  
  286. =head1 SEE ALSO
  287.  
  288. SOAP::Envelope
  289.  
  290. =cut
  291.