RPC-XML
view release on metacpan or search on metacpan
lib/RPC/XML/Parser/XMLParser.pm view on Meta::CPAN
# from simply new-ing a datatype all the way to building the final object.
sub tag_end ## no critic (ProhibitExcessComplexity)
{
my ($robj, $self, $elem) = @_;
my ($op, $newobj, $class, $list, $name);
# This should always be one of the stack machine ops defined above
$op = pop @{$robj->[M_STACK]};
my $cdata = q{};
if ($robj->[M_SPOOLING_BASE64_DATA])
{
$cdata = $robj->[M_CDATA];
seek $cdata, 0, 0;
}
elsif ($robj->[M_CDATA])
{
$cdata = join q{} => @{$robj->[M_CDATA]};
}
# Decide what to do from here
if (VALIDTYPES->{$elem}) ## no critic (ProhibitCascadingIfElse)
{
# This is the closing tag of one of the data-types.
$class = $elem;
# Cheaper than the regex that was here, and more locale-portable
if ($class eq 'dateTime.iso8601')
{
$class = 'datetime_iso8601';
}
# Some minimal data-integrity checking
if ($class eq 'int' or $class eq 'i4' or $class eq 'i8')
{
if ($cdata !~ /^[-+]?\d+$/)
{
return error($robj, $self, 'Bad integer data read');
}
}
elsif ($class eq 'double')
{
if ($cdata !~
# Taken from perldata(1)
/^[+-]?(?=\d|[.]\d)\d*(?:[.]\d*)?(?:[Ee](?:[+-]?\d+))?$/x)
{
return error($robj, $self, 'Bad floating-point data read');
}
}
elsif ($class eq 'nil')
{
# We now allow parsing of <nil/> at all times.
# By definition though, it must be, well... nil.
if ($cdata !~ /^\s*$/)
{
return error($robj, $self, '<nil /> element must be empty');
}
}
$class = "RPC::XML::$class";
# The string at the end is only seen by the RPC::XML::base64 class
$newobj = $class->new($cdata, 'base64 is encoded, nil is allowed');
push @{$robj->[M_STACK]}, $newobj, DATAOBJECT;
if ($robj->[M_SPOOLING_BASE64_DATA])
{
$robj->[M_SPOOLING_BASE64_DATA] = 0;
$robj->[M_CDATA] = undef; # Won't close FH, $newobj still holds it
}
}
elsif ($elem eq 'value')
{
# For <value></value>, there should already be a dataobject, or else
lib/RPC/XML/Parser/XMLParser.pm view on Meta::CPAN
if ($op == DATAOBJECT)
{
($op, $newobj) = splice @{$robj->[M_STACK]}, -2;
if ($op != VALUEMARKER)
{
return stack_error($robj, $self, $elem);
}
}
else
{
$newobj = RPC::XML::string->new($cdata);
}
push @{$robj->[M_STACK]}, $newobj, DATAOBJECT;
}
elsif ($elem eq 'param')
{
# Almost like above, since this is really a NOP anyway. But it also
# puts PARAMENT on the stack, so that the closing tag of <params />
# can check for bad content.
if ($op != DATAOBJECT)
lib/RPC/XML/Parser/XMLParser.pm view on Meta::CPAN
}
# Get the name off the stack to clear the way for the STRUCTMEM marker
# under it
($op, $name) = splice @{$robj->[M_STACK]}, -2;
# Push the name back on, with the value and the new marker (STRUCTMEM)
push @{$robj->[M_STACK]}, $name, $newobj, STRUCTMEM;
}
elsif ($elem eq 'name')
{
# Fairly simple: just push the current content of CDATA on w/ a marker
push @{$robj->[M_STACK]}, $cdata, STRUCTNAME;
}
elsif ($elem eq 'struct')
{
# Create the hash table in-place, then pass the ref to the constructor
$list = {};
# First off the stack needs to be STRUCTMEM or STRUCT
if (! ($op == STRUCTMEM or $op == STRUCT))
{
return error(
$robj, $self, 'Element mismatch, expected to see member'
lib/RPC/XML/Parser/XMLParser.pm view on Meta::CPAN
}
elsif ($elem eq 'methodName')
{
if ($robj->[M_STACK]->[$#{$robj->[M_STACK]}] != METHOD)
{
return error(
$robj, $self,
"$elem tag must immediately follow a methodCall tag"
);
}
push @{$robj->[M_STACK]}, $cdata, NAMEVAL;
}
elsif ($elem eq 'methodCall')
{
# A methodCall closing should have on the stack an optional PARAMLIST
# marker, a NAMEVAL marker, then the METHOD token from the
# opening tag.
if ($op == PARAMLIST)
{
($op, $list) = splice @{$robj->[M_STACK]}, -2;
}
( run in 0.536 second using v1.01-cache-2.11-cpan-454fe037f31 )