Skip to content

Commit

Permalink
Item8729: rewrite of serializer
Browse files Browse the repository at this point in the history
   
   * access to all node properties of a response (uri, prefix, type, attributes).
   * evaluation of sub-xpath expressions during formatting 



git-svn-id: http://svn.foswiki.org/trunk/SoapPlugin@6789 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
MichaelDaum authored and MichaelDaum committed Mar 19, 2010
1 parent 1562435 commit 8925014
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 34 deletions.
23 changes: 19 additions & 4 deletions data/System/SoapPlugin.txt
@@ -1,4 +1,4 @@
%META:TOPICINFO{author="micha" comment="save topic" date="1268764919" format="1.1" reprev="1.5" version="1.5"}%
%META:TOPICINFO{author="micha" date="1269028908" format="1.1" version="1.6"}%
---+!! %TOPIC%
%SHORTDESCRIPTION%

Expand Down Expand Up @@ -31,9 +31,6 @@ The xml response of a service endpoint can be parsed and formatted using basic x
| valueof="..." | xpath expression to filter the output |
| depth="int" | the depth to which an XML response object should be traversed while rendering it using =format=, =header=, =footer= and =separator= |

If the node selected by the =valueof= xpath expression is not a scalar value, e.g. addresses a node in the xml response which contains further child nodes, then the result is rendered recursively using =format=, =header=, =footer= and =separator= while traversing the xml output. When visiting a node, its key and its value are inserted using the =$key= and =$value= variables part of the =format= string.

Standard escapes may be used in all format strings, that is =$percnt=, =$nop=, =$n= and =$dollar=.

Any additional parameter like for example =EMPLOYEEID= in =%<nop>SOAP{"client-id" method="getVacationOfEmployee" EMPLOYEEID="1606"}%= will be passed over to the server and are not interpreted by the !SoapPlugin itself. This also
means that any required parameter to a webservice method must not overlap with those documented above as part of
Expand All @@ -55,6 +52,22 @@ the =%SOAP= command.

So the parameters to =%SOAPFORMAT= are mostly the same as those for =%SOAP= except =method=. This is not needed as SOAPFORMAT formats the response already received by accessing the server/method of the previous =%SOAP= call.

If the node selected by the =valueof= xpath expression is not a scalar value, e.g. addresses a node in the xml response which contains further child nodes, then the result is rendered recursively using =format=, =header=, =footer= and =separator= while traversing the xml output.

When visiting a node, the following variables can be used to access its properties:

* =$name=: (or =$key=): the name of the node
* =$value=: the value of the node; this expands recursively when the value is not a final child node
* =$type=: the type of the node according to the WSDL definition
* =$uri=: the URI that will be used as the namespace
* =$prefix=: the prefix used when associating the node with a specific namespace
* =$attr(...)=: the value of the named attribute
* =$index=: the index of this node in a list of sibling nodes
* =$depth=: the distance from the root node of the contained xml document
* =$valueof(...)=: the value of the node as specified by the enclosed xpath expression; note: in contrast to the =valueof= parameter of the =%SOAP/SOAPFORMAT= tag itself, this only returns the first matching value

Standard escapes may be used in all format strings, that is =$percnt=, =$nop=, =$n= and =$dollar=.

---++ Configuring Clients

Each client specifies an service that Foswiki might talk to using SOAP. These have to be defined upfront using
Expand Down Expand Up @@ -133,6 +146,8 @@ Every message created by !SoapPlugin adds a set of foswiki-specific headers whic
| Release: | %$RELEASE% |
| Version: | %$VERSION% |
| Change History: | <!-- versions below in reverse order -->&nbsp; |
| 19 Mar 2010: | rewrite of serializer; implemented =$valueof()= etc |
| 16 Mar 2010: | initial release |
| Dependencies: | %$DEPENDENCIES% |
| Home page: | Foswiki:Extensions/%TOPIC% |
| Support: | Foswiki:Support/%TOPIC% |
Expand Down
2 changes: 1 addition & 1 deletion lib/Foswiki/Plugins/SoapPlugin.pm
Expand Up @@ -16,7 +16,7 @@ use strict;
use Foswiki::Func ();

our $VERSION = '$Rev$';
our $RELEASE = '0.3';
our $RELEASE = '0.4';
our $SHORTDESCRIPTION = 'SOAP for Foswiki';
our $NO_PREFS_IN_TOPIC = 1;
our $baseWeb;
Expand Down
95 changes: 66 additions & 29 deletions lib/Foswiki/Plugins/SoapPlugin/Core.pm
Expand Up @@ -24,6 +24,7 @@ our %clients;
our %knownSoms;

use constant DEBUG => 0; # toggle me
#use Data::Dumper ();

###############################################################################
sub writeDebug {
Expand Down Expand Up @@ -143,10 +144,7 @@ sub formatResult {
return '<verbatim>'.$content.'</verbatim>';
}

$som->match('//Envelope/Body');
my @data = ($params->{valueof})?$som->valueof($params->{valueof}):$som->valueof();
my $data = (scalar(@data) > 1)?\@data:$data[0];
my $result = stringify($data, $params);
my $result = stringify($som, $params);

$result =~ s/\$perce?nt/\%/go;
$result =~ s/\$nop\b//go;
Expand Down Expand Up @@ -177,39 +175,78 @@ sub handleSOAPFORMAT {

###############################################################################
sub stringify {
my ($data, $params, $depth) = @_;
my ($som, $params, $data, $depth) = @_;

$depth ||= 1;
return '' if $params->{depth} && $params->{depth} < $depth;
my $currentPath = $params->{valueof}||'';
unless ($data) {
my @data;
@data = $som->dataof($currentPath);
$som->match($currentPath);
$data = \@data;
};

#writeDebug("called stringify(depth=$depth)");

my $maxDepth = $params->{depth} || 10;
return '' if $maxDepth < $depth;
return '' unless defined $data;

my @lines = ();
if (ref(\$data) eq "SCALAR") {
#writeDebug("SCALAR");
return $data;
} elsif (ref($data) eq "ARRAY") {
#writeDebug("ARRAY");
my $index = 1;
foreach my $value (@$data) {
my $line = $params->{format};
$line = '$value' unless defined $line;
$line =~ s/\$key/$index/g;
$line =~ s/\$value/stringify($value, $params, $depth +1)/ge;
$index++;
push @lines, $line;
}
} elsif (ref($data) eq "HASH") {
#writeDebug("HASH");
foreach my $key (keys %$data) {
my $line = $params->{format};
$line = '$key=$value' unless defined $line;
$line =~ s/\$key/$key/ge;
$line =~ s/\$value/stringify($data->{$key}, $params, $depth +1)/ge;
push @lines, $line;


my $currentIndex = $params->{_index} || 1;
foreach my $dataItem (@$data) {
my $line = $params->{format};
$line = '$value' unless defined $line;

$line =~ s/\$(key|name)/($dataItem->name()||'')/ge;
$line =~ s/\$type/($dataItem->type()||'')/ge;
$line =~ s/\$uri/($dataItem->uri()||'')/ge;
$line =~ s/\$prefix/($dataItem->prefix()||'')/ge;
$line =~ s/\$attr\((.*?)\)/($dataItem->attr($1)||'')/ge;
$line =~ s/\$index/$currentIndex/g;
$line =~ s/\$depth/$depth/g;
$line =~ s/\$valueof\((.*?)\)/($som->valueof($1||'')||'')/ge;

if ($line =~ /\$value\b/) {
my $value = $dataItem->value() ||'';

#print STDERR "value=$value ref=".ref($value)."\n";

my @values = ();
if (!ref($value) || ref($value) eq "SCALAR") {
push @values, $value;
} elsif (ref($value) eq "ARRAY") {
my $index = 1;
foreach my $item (@$value) {
if (ref($item) eq "SCALAR") {
push @values, $item;
} else {
$params->{_index} = $index;
push @values, stringify($som, $params, [SOAP::Data->new(name=>$index, value=>$item)], $depth+1);
$index++;
}
}
} elsif (ref($value) eq "HASH") {
my $index = 1;
foreach my $key (keys %$value) {
$params->{_index} = $index;
push @values, stringify($som, $params, [SOAP::Data->new(name=>$key, value=>$value->{$key})], $depth+1);
$index++;
}
} else {
push @values, ref($value);
}
$value = join('', @values);
$line =~ s/\$value\b/$value/g;
}
}

$currentIndex++;
push @lines, $line;
}
return '' if $params->{hidenull} && !@lines;

return $params->{header}.join($params->{separator}, @lines).$params->{footer};
}

Expand Down

0 comments on commit 8925014

Please sign in to comment.