File Coverage

blib/lib/XPC.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #
2             # XPC.pm - XML Procedure Call Classes
3             #
4             # Designed to work in conjunction with the XML::Parser Style => 'Object'.
5             #
6             # Copyright (C) 2001 Gregor N. Purdy.
7             # All rights reserved.
8             #
9             # This is free software; you can redistribute it and/or modify it under
10             # the same terms as Perl itself.
11             #
12              
13              
14             package XPC;
15              
16             #use XML::Writer;
17 2     2   13116 use XML::Parser;
  0            
  0            
18              
19             use vars qw($VERSION);
20              
21             $VERSION = 0.2;
22              
23              
24             #
25             # new()
26             #
27              
28             sub new
29             {
30             my $class = shift;
31             my $self;
32              
33             if (@_) {
34             my $xml = shift;
35              
36             my $parser = new XML::Parser(Style => 'Objects');
37             eval {
38             $self = $parser->parse($xml);
39             };
40              
41             if ($@) {
42             print STDERR "XPC: XML =\n";
43             print STDERR $xml;
44             print STDERR "\n";
45             die "XPC: Unable to parse XML into XPC instance!\n";
46             }
47             } else {
48             $self = new XPC::xpc;
49             }
50              
51             return $self;
52             }
53              
54              
55             #
56             # new_call()
57             #
58              
59             sub new_call
60             {
61             my $class = shift;
62             my $self = $class->new();
63             $self->add_call(@_);
64             return $self;
65             }
66              
67              
68             ##############################################################################
69             #
70             # CHARACTER DATA:
71             #
72             ##############################################################################
73              
74              
75             #
76             # XPC::Characters
77             #
78              
79             package XPC::Characters;
80              
81             sub data
82             {
83             my $self = shift;
84              
85             return $self->{Text};
86             }
87              
88             sub new
89             {
90             my ($class, $data) = @_;
91              
92             return bless { Text => $data }, $class;
93             }
94              
95              
96             ##############################################################################
97             #
98             # ROOT:
99             #
100             ##############################################################################
101              
102             package XPC::xpc;
103              
104              
105             #
106             # version()
107             #
108              
109             sub version
110             {
111             my $self = shift;
112             return $self->{version} if defined $self->{version};
113             }
114              
115              
116             #
117             # new()
118             #
119              
120             sub new
121             {
122             my ($class, $version) = @_;
123             my $self = bless { Kids => [ ] }, $class;
124             $self->{version} = $version if defined $version;
125             return $self;
126             }
127              
128              
129             #
130             # add_call()
131             #
132              
133             sub add_call
134             {
135             my ($self) = shift;
136              
137             $self->add_request(XPC::call->new(@_));
138             }
139              
140              
141             #
142             # add_response()
143             #
144              
145             sub add_response
146             {
147             my ($self, $response) = @_;
148              
149             die "XPC::xpc::add_response(): Cannod add undef response!\n" unless defined $response;
150              
151             push @{$self->{Kids}}, $response;
152             }
153              
154              
155             #
156             # add_request()
157             #
158              
159             sub add_request
160             {
161             my ($self, $request) = @_;
162              
163             push @{$self->{Kids}}, $request;
164             }
165              
166              
167             #
168             # as_string()
169             #
170              
171             sub as_string
172             {
173             my $self = shift;
174              
175             # print STDERR "XPC::xpc:as_string(): Generating string...\n";
176              
177             my $version = $self->version;
178             my @kids = @{$self->{Kids}};
179              
180             my $body;
181              
182             foreach my $kid (@kids) {
183             next unless defined $kid; # TODO: How does this happen?
184             $body .= $kid->as_string;
185             }
186              
187             if (defined $version and $version ne '') {
188             if (defined $body) {
189             return "\n$body\n";
190             } else {
191             return "\n"; # TODO: Degenerate case
192             }
193             } else {
194             if (defined $body) {
195             return "\n$body\n";
196             } else {
197             return "\n"; # TODO: Degenerate case
198             }
199             }
200             }
201              
202              
203             #
204             # results()
205             #
206              
207             sub results
208             {
209             my ($self, $index) = @_;
210              
211             my @kids = @{$self->{Kids}};
212             my @results = grep { ref $_ eq 'XPC::result'; } @kids;
213             return @results;
214             }
215              
216              
217             #
218             # result()
219             #
220              
221             sub result
222             {
223             my ($self, $index) = @_;
224             return ($self->results)[$index];
225             }
226              
227              
228             #
229             # faults()
230             #
231              
232             sub faults
233             {
234             my ($self, $index) = @_;
235              
236             my @kids = @{$self->{Kids}};
237             my @faults = grep { ref $_ eq 'XPC::fault'; } @kids;
238             return @faults;
239             }
240              
241              
242             #
243             # fault()
244             #
245              
246             sub fault
247             {
248             my ($self, $index) = @_;
249             return ($self->faults)[$index];
250             }
251              
252              
253             ##############################################################################
254             #
255             # QUERIES:
256             #
257             ##############################################################################
258              
259             package XPC::query;
260              
261              
262             #
263             # procedure()
264             #
265             # OPTIONAL
266             #
267              
268             sub procedure
269             {
270             my $self = shift;
271             return $self->{procedure} if defined $self->{procedure};
272             }
273              
274              
275             #
276             # id()
277             #
278              
279             sub id
280             {
281             my $self = shift;
282             return $self->{id} if defined $self->{id};
283             }
284              
285              
286             #
287             # new()
288             #
289              
290             sub new
291             {
292             my ($class, $procedure, $id) = @_;
293             my $self = bless { Kids => [ ] }, $class;
294             $self->{id} = $id if defined $id;
295             $self->{procedure} = $procedure if defined $procedure;
296             return $self;
297             }
298              
299              
300             ##############################################################################
301             #
302             # CALLS:
303             #
304             ##############################################################################
305              
306             package XPC::call;
307              
308              
309             #
310             # procedure()
311             #
312             # MANDATORY
313             #
314              
315             sub procedure
316             {
317             shift->{procedure};
318             }
319              
320              
321             #
322             # id()
323             #
324             # OPTIONAL
325             #
326              
327             sub id
328             {
329             my $self = shift;
330             return $self->{id} if defined $self->{id};
331             }
332              
333              
334             #
335             # new()
336             #
337              
338             sub new
339             {
340             my ($class, $procedure, $id) = @_;
341             my $self = bless { procedure => $procedure, Kids => [ ] }, $class;
342             $self->{id} = $id if defined $id;
343             return $self;
344             }
345              
346              
347             #
348             # add_param()
349             #
350             # TODO
351             #
352              
353              
354             #
355             # as_string()
356             #
357              
358             sub as_string
359             {
360             my $self = shift;
361              
362             my $procedure = $self->procedure;
363              
364             my $body;
365              
366             foreach my $kid (@kids) {
367             $body .= $kid->as_string;
368             }
369              
370             if (defined $body) {
371             return " \n$body \n";
372             } else {
373             return " \n";
374             }
375             }
376              
377              
378             ##############################################################################
379             #
380             # CALL PARAMETERS:
381             #
382             ##############################################################################
383              
384             package XPC::param;
385              
386              
387             #
388             # name()
389             #
390             # OPTIONAL
391             #
392              
393             sub name
394             {
395             shift->{name};
396             }
397              
398              
399             #
400             # new()
401             #
402              
403             sub new
404             {
405             my ($class, $name) = @_;
406             my $self = bless { Kids => [ ] }, $class;
407             $self->{name} = $name if defined $name;
408             return $self;
409             }
410              
411              
412             ##############################################################################
413             #
414             # PROTOTYPES:
415             #
416             ##############################################################################
417              
418             package XPC::prototype;
419              
420              
421             #
422             # id()
423             #
424             # OPTIONAL
425             #
426              
427             sub id
428             {
429             shift->{id};
430             }
431              
432              
433             #
434             # procedure()
435             #
436             # REQUIRED
437             #
438              
439             sub procedure
440             {
441             shift->{procedure};
442             }
443              
444              
445             #
446             # comment()
447             #
448             # TODO:
449             #
450              
451              
452             ##############################################################################
453             #
454             # PROTOTYPE PARAMETER DEFINITIONS:
455             #
456             ##############################################################################
457              
458             package XPC::param_def;
459              
460              
461             #
462             # name()
463             #
464             # OPTIONAL
465             #
466              
467             sub name
468             {
469             shift->{name};
470             }
471              
472              
473             #
474             # type()
475             #
476             # REQUIRED
477             #
478              
479             sub type
480             {
481             shift->{type};
482             }
483              
484              
485             #
486             # subtype()
487             #
488              
489             sub subtype
490             {
491             shift->{subtype};
492             }
493              
494              
495             ##############################################################################
496             #
497             # PROTOTYPE RESULT DEFINITIONS:
498             #
499             # TODO
500             #
501             ##############################################################################
502              
503             package XPC::result_def;
504              
505              
506              
507             ##############################################################################
508             #
509             # RESULTS:
510             #
511             ##############################################################################
512              
513             package XPC::result;
514              
515              
516             #
517             # id()
518             #
519             # OPTIONAL
520             #
521              
522             sub id
523             {
524             shift->{id};
525             }
526              
527              
528             #
529             # name()
530             #
531             # OPTIONAL
532             #
533             # TODO: Get rid of this?
534             #
535              
536             sub name
537             {
538             shift->{name};
539             }
540              
541              
542             #
543             # new_scalar()
544             #
545              
546             sub new_scalar
547             {
548             my $class = shift;
549              
550             my $self = bless { Kids => [ ] }, $class;
551              
552             die sprintf("XPC::result::new_scalar(): Cannot create scalar result with %d arguments!\n", scalar @_) if (@_ != 1);
553              
554             push @{$self->{Kids}}, XPC::scalar->new(@_);
555              
556             return $self;
557             }
558              
559              
560             #
561             # as_string()
562             #
563              
564             sub as_string
565             {
566             my $self = shift;
567              
568             my $value;
569             foreach my $kid (@{$self->{Kids}}) {
570             next if ref $kid eq 'XPC::Characters';
571              
572             $value .= $kid->as_string;
573             }
574              
575             if (defined $value) {
576             return " \n $value\n \n";
577             } else {
578             die "XPC::result::as_string(): Mystery! No Kids!\n";
579             }
580             }
581              
582              
583             #
584             # value()
585             #
586             # TODO: Return structs and arrays, too.
587             #
588              
589             sub value
590             {
591             my $self = shift;
592              
593             my @kids = grep { ref $_ eq 'XPC::scalar' } @{$self->{Kids}};
594             return '' unless @kids;
595             return $kids[0]->value;
596             }
597              
598              
599              
600             ##############################################################################
601             #
602             # FAULTS:
603             #
604             ##############################################################################
605              
606             package XPC::fault;
607              
608              
609             #
610             # id()
611             #
612             # OPTIONAL
613             #
614              
615             sub id
616             {
617             shift->{id};
618             }
619              
620              
621             #
622             # code()
623             #
624             # MANDATORY
625             #
626              
627             sub code
628             {
629             shift->{code};
630             }
631              
632              
633             #
634             # message()
635             #
636              
637             sub message
638             {
639             my $self = shift;
640             my $data = $self->{Kids}->[0]->data;
641              
642             $data =~ s/^\s*//;
643             $data =~ s/\s*$//;
644              
645             return $data;
646             }
647              
648              
649             #
650             # new()
651             #
652              
653             sub new
654             {
655             my ($class, $code, $message, $id) = @_;
656              
657             $message =~ s/^\s*//;
658             $message =~ s/\s*$//;
659              
660             my $self = bless { code => $code,
661             Kids => [ XPC::Characters->new($message) ]
662             }, $class;
663              
664             $self->{id} = $id if defined $id;
665              
666             die "Hah!" unless $message eq $self->message;
667              
668             return $self;
669             }
670              
671              
672             #
673             # as_string()
674             #
675              
676             sub as_string
677             {
678             my $self = shift;
679             my $id = $self->id;
680             my $code = $self->code;
681             my $message = $self->message;
682              
683             if (defined $id) {
684             return " \n $message\n \n";
685             } else {
686             return " \n $message\n \n";
687             }
688             }
689              
690              
691             ##############################################################################
692             #
693             # SCALAR VALUES:
694             #
695             ##############################################################################
696              
697             package XPC::scalar;
698              
699              
700             #
701             # type()
702             #
703              
704             sub type
705             {
706             shift->{type};
707             }
708              
709              
710             #
711             # new()
712             #
713              
714             sub new
715             {
716             my ($class, $value, $type) = @_;
717              
718             my $self = bless { Kids => [ ] }, $class;
719              
720             push @{$self->{Kids}}, XPC::Characters->new($value);
721              
722             $self->{type} = $type if defined $type;
723              
724             return $self;
725             }
726              
727              
728             #
729             # as_string()
730             #
731              
732             sub as_string
733             {
734             my $self = shift;
735             my $type = $self->type;
736              
737             my $attrs = '';
738              
739             $attrs .= " type='$type'" if defined $type;
740              
741             return "" . $self->{Kids}[0]->data . "";
742             }
743              
744              
745             #
746             # value()
747             #
748              
749             sub value
750             {
751             my $self = shift;
752             return $self->{Kids}[0]->data;
753             }
754              
755              
756             ##############################################################################
757             #
758             # ARRAY VALUES:
759             #
760             # TODO
761             #
762             ##############################################################################
763              
764             package XPC::array;
765              
766              
767             ##############################################################################
768             #
769             # STRUCTURE VALUES:
770             #
771             # TODO
772             #
773             ##############################################################################
774              
775             package XPC::struct;
776              
777              
778             ##############################################################################
779             #
780             # STRUCTURE MEMBER VALUES:
781             #
782             # TODO
783             #
784             ##############################################################################
785              
786             package XPC::member;
787              
788              
789             #
790             # name()
791             #
792              
793             sub name
794             {
795             shift->{name};
796             }
797              
798              
799              
800             ##############################################################################
801             #
802             # XML VALUES:
803             #
804             # TODO: This presents a problem for this style of parsing, since we could have
805             # any elements whatsoever here.
806             #
807             ##############################################################################
808              
809             package XPC::xml;
810              
811              
812             ##############################################################################
813             #
814             # COMMENTS:
815             #
816             # TODO
817             #
818             ##############################################################################
819              
820             package XPC::comment;
821              
822              
823              
824             ##############################################################################
825             ##############################################################################
826              
827             1;
828              
829              
830             =head1 NAME
831              
832             XPC - XML Procedure Call
833              
834              
835             =head1 SYNOPSIS
836              
837             use XPC;
838              
839             and then
840              
841             my $xpc = XPC->new(<
842            
843            
844            
845            
846             END_XPC
847              
848             or
849              
850             my $xpc = XPC->new();
851             $xpc->add_call('localtime');
852              
853             or
854              
855             my $xpc = XPC->new_call('localtime');
856              
857             and then later
858              
859             print XML_FILE $xpc->as_string();
860              
861              
862             =head1 DESCRIPTION
863              
864             This class represents an XPC request or response. It uses XML::Parser to
865             parse XML passed to its constructor.
866              
867              
868             =head1 MOTIVATION
869              
870             A Commentary on the XML-RPC Specification and Definition of XPC Version 0.2
871              
872              
873             =head2 Introduction
874              
875             The following commentary is based upon the specification from the UserLand web
876             site. The version referenced for this commentary has a notation on it that it
877             was "Updated 10/16/99 DW" (see L).
878              
879             These comments are stylistic in nature, and it is well recognized by the
880             author that style in program and protocol design are very personal. This
881             commentary will, however, point out the rationale of the proposed changes to
882             the specification's design.
883              
884              
885             =head2 Procedure Call Structural Simplifications
886              
887             The example in the "Request example" section looks like this:
888              
889            
890             examples.getStateName
891            
892            
893             41
894            
895            
896            
897              
898             We note by looking at the remainder of the specification that there are only
899             two top-level elements allowed in XML-RPC: C and C.
900             Since methods are I subject of RPC, and since all top-level elements
901             in the design are about methods, there is no need to have the redundant
902             qualifier "method" in the names of these elements. Thus, the example would
903             be modified to look like this:
904              
905            
906             examples.getStateName
907            
908            
909             41
910            
911            
912            
913              
914             Now, the content of the C element is constrained to be very simple
915             text (from the "Payload format" section, which says "... identifier characters,
916             upper and lower-case A-Z, the numeric characters, 0-9, underscore, dot, colon
917             and slash"). It is also mandatory. This is precisely the reason XML includes
918             the ability to add attributes to elements (it is technically redundant, but
919             very convenient). So, we really should turn this example into:
920              
921            
922            
923            
924             41
925            
926            
927            
928              
929             Once the C element has been removed from the design, the C
930             element becomes superfluous, since its only purpose was to group the
931             parameters and separate them from the method name. Now, the C element
932             I the element that groups the parameters, leaving us with:
933              
934            
935            
936             41
937            
938            
939              
940              
941             =head2 Header Nomenclature
942              
943             One final comment on terminology: RPC stands for Remote I Call, so
944             we should probably not use the term "method" when we mean "procedure" or
945             something else. Since the "procedures" can return values, which corresponds
946             in some languages to the term "function", we have a rivalry for the term to
947             use. "Procedure" matches the acronym nicely, but for some folks "Function"
948             would have a better connotation. Fans of Eiffel might even prefer "Feature",
949             or "Query" for calls returning a value and "Routine" or "Command" for those
950             not. Given the variety of possibilities, here we stay with the simple
951             policy of matching the acronym:
952              
953            
954            
955             41
956            
957            
958              
959              
960             =head2 Scalar Values
961              
962             Typically, an interface definition determines the number, names and types of
963             parameters to a procedure call. It is incumbent upon the caller to conform
964             to that specification. Therefore, the declaration for any procedure to be
965             called as part of an interface I indicate the expected types of the
966             parameters, which means that the caller should not have to indicate the type
967             of value it is passing (and, the value I isn't passed in general, but
968             rather a I of the value is passed). XML-RPC should not
969             be blind to typing issues. These issues should not appear in the calling
970             standard, but rather in an interface definition standard (about which more
971             later). Removing the type information from the example results in:
972              
973            
974            
975             41
976            
977            
978              
979             Since the element really now just means "scalar" (see the specification
980             section "Scalar EvalueEs"), let's call it that:
981              
982            
983            
984             41
985            
986            
987              
988             If for some reason not contemplated here type information is necessary for
989             scalars, then having a simple C attribute of the C element
990             would suffice, especially since the set of allowable values is fixed,
991             small, and consists of only short string values (C, C, C,
992             C, C, C, and C).
993              
994             If we only ever expected simple, short scalar values, we could make one more
995             change, to:
996              
997            
998            
999            
1000            
1001            
1002            
1003              
1004             but, it is presumed that it would be possible to have a very long scalar
1005             string value, for which the former representation would be better.
1006              
1007              
1008             =head2 Named Parameters
1009              
1010             Some procedures may be implemented in a language that makes it very easy to
1011             implement named parameters. Supporting this would be easy:
1012              
1013            
1014            
1015             41
1016            
1017            
1018              
1019              
1020             =head2 Scalar Types
1021              
1022             Whether types apply to calls and interfaces or just to interfaces, they are
1023             an important part of the specification.
1024              
1025             The specification defines C and C to be synonyms for a 'four-byte
1026             signed integer'. Since the value will be represented in the call as text,
1027             this description really isn't an appropriate specification, since it is
1028             written in terms of a binary representation. We suggest here a single term
1029             for this data type, C, and that it be defined in terms of a range
1030             of acceptable values: -2,147,483,648 to +2,147,483,647 (just the range of
1031             vales that can be stored in a two's complement 32-bit binary representation).
1032              
1033             The C data type is distinct from the C data type, yet its
1034             domain {C<0>, C<1>} is a subset of the C domain instead of the more
1035             consistent {C, C}. If C is going to be treated as its own
1036             type, it should have its own domain.
1037              
1038             The specification defines C to be 'double-precision signed floating
1039             point number'. Note that in the 1999-01-21 questions-and-answers section
1040             near the end of the document, it is revealed that the full generality of
1041             the data type commonly meant by such a description is not available. Niether
1042             infinities, nor C (the Not-a-Number value) are permitted. Not even
1043             exponential notation is allowed. Very simple strings matching the Perl
1044             regular expression:
1045              
1046             /^([+-])(\d*)(\.)(\d*)$/
1047              
1048             are the only ones permitted according to the answer given, although one
1049             suspects that what was meant was something closer to this:
1050              
1051             /^([+-])?(\d*)((\.)(\d*))?$/
1052              
1053             because the first expression requires the sign to be present, and permits
1054             "C<+.>" and "C<-.>" as valid strings (although to what values they would map is
1055             a mystery).
1056              
1057             Note: The second expression makes the leading sign and trailing decimal point
1058             and digits optional, but still isn't perfect, since it allows the empty string
1059             as a value.
1060              
1061             This type should be called C instead of C to get away
1062             from the physical description. C is another potentially reasonable
1063             name for this type.
1064              
1065             Also, the FAQ answer says the range of allowable values is implementation-
1066             dependant, but the specification refers to "double-precision
1067             floating-point", which does have an expected set of behaviors for most people.
1068              
1069             The specification mentions "ASCII" in the type definition for string, but
1070             XML permits all of Unicode. Shouldn't one expect to be able to pass around
1071             string values with all the characters thus permitted? Shouldn't servers and
1072             clients be written to handle this broader character set, and convert as
1073             necessary internally? Otherwise, we are taking a big step back from the
1074             promise of XML and the web.
1075              
1076             The C data type name is awkward. They didn't refer to the
1077             IEEE 754 floating point standard in the name of the C type (which
1078             would have been C if they had). Unless the specification
1079             is going to allow multiple C variants, the qualifier is just an
1080             annoyance. In addition, most people call this type C, even if their
1081             computer languages sometimes just call it C (as in many SQL
1082             implementations). So, here we propose that this type just be called C
1083             and that the type description refer to the ISO 8601 standard.
1084              
1085             Finally, the C type (added 1999-01-21) really should be C with
1086             the encoding standard (Base-64) referenced in the type description.
1087              
1088              
1089             =head2 Structures
1090              
1091             Structures continue the same idiom used elsewhere in the specification: the
1092             avoidance of element attributes. Here is the example used in the specification
1093             (modified to acommodate the recommendations already made here):
1094              
1095            
1096            
1097             lowerBound
1098             18
1099            
1100            
1101             upperBound
1102             139
1103            
1104            
1105              
1106             The C element here should be converted into an attribute of the C
1107             element, leaving:
1108              
1109            
1110            
1111             18
1112            
1113            
1114             139
1115            
1116            
1117              
1118              
1119             =head2 Arrays
1120              
1121             The C element is defined with a superfluous C child element. This
1122             element serves no function, so it should be removed. Here is the example from
1123             the specification (again, modified based on previous recommendations):
1124              
1125            
1126            
1127             12
1128             Egypt
1129             false
1130             -31
1131            
1132            
1133              
1134             Removing the unneeded C element leaves us with:
1135              
1136            
1137             12
1138             Egypt
1139             false
1140             -31
1141            
1142              
1143             We have recommended getting rid of C and using C, but the
1144             specification allows a C to contain a scalar value I a C
1145             I an C. We can still do without the C element, though:
1146              
1147            
1148             12
1149            
1150             Egypt
1151             false
1152             -31
1153            
1154            
1155              
1156              
1157             =head2 Responses
1158              
1159             The example in the document is:
1160              
1161            
1162            
1163            
1164            
1165            
1166            
1167             faultCode
1168             4
1169            
1170            
1171             faultString
1172             Too many parameters.
1173            
1174            
1175            
1176            
1177            
1178              
1179             This has much unnecessary nesting. It is I simpler to store the fault
1180             code as an attribute of the C element and to have the fault description
1181             be the body of the C element:
1182              
1183            
1184            
1185            
1186             Too many parameters.
1187            
1188            
1189              
1190              
1191             =head2 Adding a Consistent Top-Level Element
1192              
1193             It would be nice if one could always be sure that XML data involved in the
1194             XML-RPC protocol had a particular root element.
1195              
1196             Another benefit of doing this is that a given request I include
1197             multiple calls, which for certain types of interactions could be of great
1198             performance benefit. If you need to make many related calls, the network
1199             latency would be a real drag on performance, but batching up the calls into
1200             one big bundle amortizes the transport time, increasing performance. A top-
1201             level element of C is used here to stand for "XML Procedure Call".
1202              
1203            
1204             ...
1205             ...
1206             ...
1207            
1208              
1209             As soon as we decide to put multiple calls in a transmission, it begs the
1210             issue of tieing responses to calls. We could use order for this, but we
1211             could also provide an attribute to C and C called C that
1212             is optionally provided by the caller, and if present, is copied into the
1213             response element for that call.
1214              
1215             HTTP POST REQUEST CONTENT:
1216              
1217            
1218             ...
1219             ...
1220             ...
1221            
1222              
1223             HTTP RESPONSE CONTENT:
1224              
1225            
1226             ...
1227             ...
1228             ...
1229            
1230              
1231             Another benefit of having a consistent top-level element is that we can use
1232             it to specify the protocol version:
1233              
1234            
1235             ...
1236            
1237              
1238             Finally, using a consistent top-level element permits the response to contain
1239             a copy of the request if desired.
1240              
1241             HTTP POST REQUEST CONTENT:
1242              
1243            
1244             ...
1245             ...
1246             ...
1247            
1248              
1249             HTTP RESPONSE CONTENT:
1250              
1251            
1252             ...
1253             ...
1254             ...
1255             ...
1256             ...
1257             ...
1258            
1259              
1260              
1261             =head2 Extended Types
1262              
1263             Given that XML-RPC is an XML application, it is disconcerting to see its
1264             design be so blind to XML issues such as Unicode values (discussed above) and
1265             tree-structured data. Suppose a procedure was to accept XML as a parameter or
1266             to return XML as its result. How would this be accomplished with XML-RPC? The
1267             answer seems to be "stuff it in a string scalar". But, to be a proper string,
1268             all the markup would have to be escaped:
1269              
1270            
1271            
1272            
1273             <bar>Here's some text in an element.</bar>
1274            
1275            
1276            
1277              
1278             However, if we add to the C, C and C types a new
1279             type C, then we can do the natural thing:
1280              
1281            
1282            
1283            
1284             Here's some text in an element.
1285            
1286            
1287            
1288              
1289             We could even use XML Namespaces if needed to resolve element name collisions
1290             if they arise (namespaces are commonly used for this reason in XSLT
1291             transforms).
1292              
1293             Technically speaking, allowing parameters and results to contain XML makes the
1294             other XML-RPC types redundant, but providing shortcuts for these common cases
1295             does make sense.
1296              
1297              
1298             =head2 Interface Specifications
1299              
1300             In order to provide true discoverability, there needs to be a way for a client
1301             to ask the server what operations it supports, and to get back interface
1302             information for the supported procedures.
1303              
1304             Sending an empty C element should cause the server to return an array
1305             of procedure names:
1306              
1307             HTTP POST REQUEST CONTENT:
1308              
1309            
1310            
1311            
1312              
1313             HTTP RESPONSE CONTENT:
1314              
1315            
1316            
1317            
1318             foo
1319             bar
1320            
1321            
1322            
1323              
1324             Sending a C element with a procedure name filled in should return a
1325             response containing a prototype:
1326              
1327             HTTP POST REQUEST CONTENT:
1328              
1329            
1330            
1331            
1332              
1333             HTTP RESPONSE CONTENT:
1334              
1335            
1336            
1337            
1338             The 'foo' procedure! Given an integer, returns an array with that
1339             many elements, with each element containing the integer number of
1340             its position within the array.
1341            
1342            
1343            
1344            
1345            
1346              
1347             Requesting information on an unknown procedure results in a C return:
1348              
1349             HTTP POST REQUEST CONTENT:
1350              
1351            
1352            
1353            
1354              
1355             HTTP RESPONSE CONTENT:
1356              
1357            
1358            
1359             Unknown procedure name 'quux'!
1360            
1361            
1362              
1363              
1364             =head2 Conclusion
1365              
1366             The "Strategies/Goals" section of the specification lists these items
1367             (paraphrased):
1368              
1369              
1370             =over 4
1371              
1372             =item *
1373              
1374             Leverage the ability of CGI to pass many firewalls to build an RPC
1375             mechanism that can cross many platforms and many network boundaries.
1376              
1377             =item *
1378              
1379             Cleanliness.
1380              
1381             =item *
1382              
1383             Extensibility.
1384              
1385             =item *
1386              
1387             Easy implementation.
1388              
1389             =back
1390              
1391              
1392             The first of these seems to be met without difficulty by leveraging the HTTP
1393             protocol.
1394              
1395             Cleanliness is of course a subjective measure, and this document has pointed
1396             out many points on which we think cleanliness can be improved.
1397              
1398             The original specification doesn't seem to address extensibility other than
1399             to list it as a goal. This document's addition of the XML type provides much
1400             extensibility.
1401              
1402             Ease of implementation should not be radically decreased by the modified
1403             version of XML-RPC proposed here, except in the handling of Unicode text.
1404             This is likely the main reason ASCII was specified in the original protocol
1405             definition.
1406              
1407              
1408             =head1 ADDITIONAL INFORMATION
1409              
1410             The following sections provide details behind the proposed XPC.
1411              
1412             =head2 Document Type Definition for Proposed XPC
1413              
1414             This appendix shows the complete simple DTD for XPC. It is no more complicated
1415             than the XML-RPC DTD (see L
1416             or L).
1417              
1418            
1419            
1420            
1421            
1422            
1423              
1424            
1425            
1426            
1427            
1428              
1429            
1430            
1431            
1432            
1433            
1434            
1435              
1436            
1437            
1438            
1439            
1440              
1441            
1442            
1443            
1444              
1445            
1446            
1447            
1448            
1449             #IMPLIED >
1450              
1451            
1452            
1453            
1454              
1455            
1456            
1457              
1458            
1459            
1460            
1461            
1462              
1463            
1464            
1465              
1466              
1467            
1468            
1469            
1470            
1471              
1472            
1473            
1474            
1475            
1476            
1477              
1478            
1479            
1480            
1481            
1482              
1483            
1484            
1485            
1486            
1487            
1488            
1489              
1490            
1491            
1492            
1493            
1494            
1495            
1496              
1497            
1498              
1499              
1500             =head2 XML Schema for Proposed XPC
1501              
1502            
1503              
1504              
1505             =head2 An XML-RPC E---E XPC Gateway
1506              
1507             The following XSLT transform will convert XML-RPC requests into XPC requests:
1508              
1509            
1510              
1511              
1512             The following XSLT transform will convert XPC responses into XML-RPC responses
1513             (where it is possible):
1514              
1515            
1516              
1517              
1518             The following XSLT transform will convert XPC requests into XML-RPC requests
1519             (where it is possible):
1520              
1521            
1522              
1523              
1524             The following XSLT transform will convert XML-RPC responses into XPC responses:
1525              
1526            
1527              
1528              
1529             =head1 AUTHOR
1530              
1531             Gregor N. Purdy Egregor@focusresearch.comE
1532              
1533              
1534             =head1 COPYRIGHT
1535              
1536             Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
1537              
1538             This is free software; you can redistribute it and/or modify it under
1539             the same terms as Perl itself.
1540