How can I get attributes from complex SOAP::DATA structure in SOAP::Lite? - perl

I can't get a simple attribute value from SOAP response using SOAP::Lite.
Below the code and output of SOAP::Data. I'm trying to get value of the attribute //response/dirn/attr/uuid
my $cm = new SOAP::Lite
uri => 'http://www.cisco.com/AXL/API/1.0',
proxy => "https://10.0.0.1:8443/axl/";
my $res = $cm->getPhone(
SOAP::Data->name(phoneName => 'SEP00270D3D7A4C'),
);
for my $i ($res->valueof('//device/lines/line')) {
print Dumper($i);
#print $i->{dirn}->{attr}->{'uuid'}."\n"; # line below give me an error
}
Here the output of Data::Dumper. I actually have the requested value, but I can't get it through SOAP::Data
$VAR1 = \bless( {
'_signature' => [],
'_value' => [
bless( {
'_name' => 'dirn',
'_signature' => [],
'_value' => [
''
],
'_prefix' => '',
'_attr' => {
'uuid' => '{615C3550-1EFD-56C7-3788-2AA8725880E3}' #!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}, 'SOAP::Data' ),
],
'_attr' => {}
}, 'SOAP::Data' );
I spent about several hours trying to get this attribute value. I've already thinking about using output of Data::Dumper to get the value as fast and dirty hack.
Thanks in advance
P.S.: SOAP Server is Cisco CUCM 6.1.5

$$i->value->attr->{uuid}

$i->{'_value'}[0]{'uuid'}
I think, though, I'm not sure about the [0].

I have same issue, but can not find an "quick and easy" solution to it. I developed a Perl library module to use certain vendor Web Service (WSDL). I had done many of such Web Service interfaces, but until now - all of the data was returned as XML "elements". On the contrary, this particular Web Service returns most of the data as XML elements, but also sets some - as XML attributes. I can not get values returned as attributes - since SOAP::Data methods (valueof(), body(), etc.) only return values of XML elements, but not associated attributes.
This problem is a little different from the one posted before - in that I do not know up front the XML structure that is being returned (given web service provides many different methods, and each - has different response).
So question is - how it is possible to get all of the XML data (both elements and attributes) for a generic response SOAP data

I went through the same thing recently and found the answer, refer to my question and my updated answer in the comments section.
Extract specific XML element in CDATA taken from SOAP::Lite Response Hash

Related

Get Values out of Complex Perl Hash Structures

With the following Code I can fetch Data stored in a Hash from a Database and print it out:
use Data::Dumper;
my $fdx = $s->field(); # get Hashreference from Database
print Dumper($fdx); # print out Hash
The (important part of the) Output looks like this:
$VAR1 = bless( {
'selectable' => 'true',
'_PARENT_OBJECT' => bless( {
'dirtyFlag' => 1,
'path' => undef,
'testItems' => [],
'data' => {
'TEST_10' => {
'atm_rundatahistory' => {
'1523964918' => {
'atm_prid' => {
'content' => '',
'label' => 'Problem Report IDs',
'raw' => ''
}, ...
'1523964410' => {
'atm_prid' => {
'label' => 'Problem Report IDs',
'raw' => '23361234',
'content' => '23361234'
}, ...
'Test_10' is one of hundreds of Tests, '1523964918' is one of many unix timestamps, so basically its a 32 Bit Integer, but I dont know which numbers the timestamps contain.
How do I print out / access the values for 'content' (in this case '23361234') of the most inner Hashes, for all Tests and unix timestamps, if they exist?
from here on I will describe my thoughts and what I have tried, its not necessary to read any further for this question.
I think the code I am looking for is something like:
foreach my $val($fdx{_PARENT_OBJECT}{data}{"TEST_*"}{atm_rundatahistory}{"********"}{atm_prid}{content})
print("\n$val");
However I don't know the exact Syntax, and neither do I know which placeholders to set for "Test_10", since there are many tests numbers, e.g. "...Test_132...Test_134" and the Unix timestamps can be any 32 Bit Integer, so I guess I can use start as a placeholder? e.g. "********".
After some hours of searching on the web, I haven't found a understandable tutorial on how to access values from complex Perl hash structures, I guess there are some simple syntax-rules to know and you can get any value of even very complex data structures without to much effort.
I've already read perldoc_perlreftut. If there is any other easy to understandable tutorial for these kind of problems, please recommend them to me. I don't really know how I can learn to handle such complex data structures in Perl myself.

Net::Kashflow - doesn't work with utf8 descriptions

I know this is a very old Perl module (5 or so years ago since the last update). I've found it useful for a project I'm doing though, that needs to be in Perl. Rather than starting from the bottom up, I've found this helpful to do the basics. I've already fixed up a few bugs with it - but this one I can't figure out
The module in question is: https://github.com/simoncozens/Net-KashFlow
An example usage with the problem is:
my $kf = Net::KashFlow->new(username => q|foo#bar.com|, password => "xxxx" );
my $i = $kf->create_invoice({
CustomerReference => "0123-1111111", CustomerID => 50108952,
CurrencyCode => "EUR"
}) || die $!;
$i->add_line({
Quantity => 1,
Description => "íéó foo bar test",
Rate => 10,
VatAmount => 4,
VatRate => 0,
CurrencyCode => "GBP"
});
This item gets added, but the "Description" value gets converted to:
7enzIGZvbyBiYXIgdGVzdA==
If you use normal a-z 0-9 it works fine (and shows correctly). The issue seems to be that its encoding into base64, and then not being decoded correctly at the other end. My guess is that KashFlow are not going to "fix" this, so it really needs to be done this end. I'm not really familiar with the SOAP::Lite module (again, a pretty old module it seems!), but that's what it uses.
This is the part I think that deals with adding a new "line" to the invoice:
InsertInvoiceLine => {
endpoint => 'https://securedwebapp.com/api/service.asmx',
soapaction => 'KashFlow/InsertInvoiceLine',
namespace => 'KashFlow',
parameters => [
SOAP::Data->new(name => 'UserName', type => 'xsd:string', attr => {}),
SOAP::Data->new(name => 'Password', type => 'xsd:string', attr => {}),
SOAP::Data->new(name => 'InvoiceID', type => 'xsd:int', attr => {}),
SOAP::Data->new(name => 'InvLine', type => 'tns:InvoiceLine', attr => {}),=> {})
], # end parameters
}, # end InsertInvoiceLine
You can see the structure here:
https://securedwebapp.com/api/service.asmx?op=InsertInvoiceLine
After researching this, it was suggested that you tell SOAP::Lite to not convert utf8 into base64, using (I assume), something like:
The structure is:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<InsertInvoiceLine xmlns="KashFlow">
<UserName>string</UserName>
<Password>string</Password>
<InvoiceID>int</InvoiceID>
<InvLine>
<Quantity>decimal</Quantity>
<Description>string</Description>
<Rate>decimal</Rate>
<ChargeType>int</ChargeType>
<VatRate>decimal</VatRate>
<VatAmount>decimal</VatAmount>
<ProductID>int</ProductID>
<Sort>int</Sort>
<ProjID>int</ProjID>
<LineID>int</LineID>
<ValuesInCurrency>integer</ValuesInCurrency>
</InvLine>
</InsertInvoiceLine>
</soap:Body>
</soap:Envelope>
So looks like its Body > InsertInvoiceLine > InvLine > Description .. but I'm unsure how I can tell it not to encode that particular string.
Any advise would be much appreciated. While its not a major show stopper (as all the data is in the system), it would be much nicer/easier to see the item names as expected :)
Thanks!
I think this is probably SOAP::Lite deciding to convert things to base64 when it thinks they aren't a particular subset of ASCII. You'll find this heuristic in SOAP/Lite.pm in SOAP::Serializer:
$self->typelookup({
'base64Binary' =>
[10, sub {$_[0] =~ /[^\x09\x0a\x0d\x20-\x7f]/ }, 'as_base64Binary'],
'zerostring' =>
[12, sub { $_[0] =~ /^0\d+$/ }, 'as_string'],
... many other types ...
'string' =>
[100, sub {1}, 'as_string'],
});
This comes into play when SOAP::Lite doesn't know an object's type because no one has told it. I'm guessing that in the bowels of your program it's serializing Description and typelookup sticks its dirty mitts in.
And from here you are on your own because SOAP::Lite is no fun. I would start by hacking on SOAP::Lite a bit to see what you can trace. Copy the SOAP/Lite.pm file somewhere and put that location in your #INC. That way you don't mess around with the original file.
If you never want the base64, it might be as simple as deleting that line in typelookup, although declaring the Description type would be more proper (but also a rabbit's hole of work, potentially). The fast fix can stand in while you work on the right fix.
There's also the Perlmonk's meditation How to convince SOAP::Lite to return UTF-8 data in responses as UTF-8?.

CakePHP RESTful API routing with custom querystring params

I'm using CakePHP 2.x for a RESTful API, I want to be able to handle requests in the following form
api/activity/17?page=1&limit=10
Typically CakePHP I think likes each param to be separated by the forward slash char and then each of these is mapped into the variables defined in the 2nd array argument of router::connect above. For exampple:
api/activity/17/1/10
In my case though this won't work so I am trying to pass a custom query string which I will then decode in my controller. My router connect is as follows:
So I am using router::connect as follow:
Router::connect('/api/activity/:queryString', [
'controller' => 'users',
'action' => 'activity',
'[method]' => 'GET',
'ext' => 'json',
],
[
'queryString' => '[0-9]+[\?]...[not complete]'
]);
I can't get the regular expression to accept the '?' which I am exscaping in the regex above. How can I achieve this or otherwise is there a better or easier way of sending the URL in the format I require.
You can get the URL parameters (among other methods) via $this->request->query;
So, in your example, add the following in method view() of app/Model/Activity.php:
<?php
// file app/Model/Activity.php
public function view($id)
{
// URL is /activity/17?page=1&limit=10
echo $this->request->query['page']; // echo's: 1
echo $this->request->query['limit']; // echo's: 10
}
See 'Accessing Querystring parameters' in the CakePHP book

How to connecting RapidApp to PostgreSQL, with utf-8 enabled

I'm creating a simple CRUD interface to a database, and I'm trying RapidApp.
I have an existing database, which I connect to with existing Moose-based code. There is a complication in that there is UTF-8 text in the database (eg 'Encyclopédie médico-chirurgicale. Técnicas quirúrgicas. Aparato digestivo')
My Moose-based code works just fine: data goes in & data comes out... and everyone is happy.
In my existing Moose code, the connector is:
$schema = My::Service::Schema->connect(
'dbi:Pg:dbname=my_db;host=my.host.name;port=1234',
'me',
'secret',
{ pg_enable_utf8 => 1 }
);
When I set about connecting RapidApp, I first tried a simple rdbic.pl command, but that doesn't pick up the UTF-8 strings. In an attempt to enforce UTF-8-ness, I've created the following:
use Plack::Runner;
use Plack::App::RapidApp::rDbic;
my $cnf = {
connect_info => {
dsn => 'dbi:Pg:dbname=my_db;host=my.host.name;port=1234',
user => 'me',
password => 'secret',
{ pg_enable_utf8 => 1 },
},
schema_class => 'My::Service::Schema'
};
my $App = Plack::App::RapidApp::rDbic->new( $cnf );
my $psgi = $App->to_app;
my $runner = Plack::Runner->new;
$runner->parse_options('--port', '5678');
$runner->run($psgi);
(which is pretty much rdbic.pl, compressed to one specific thing)
However - I'm getting mal-formed strings (eg: 'Encyclopédie médico-chirurgicale. Técnicas quirúrgicas. Aparato digestivo')
Having fought to get the correct text INTO the database, I know the database is correct... so how do I connect RapidApp to get UTF-8 back out?
Your schema will need to be configured to support UTF-8. Here's a helpful set of things to try:
How to properly use UTF-8-encoded data from Schema inside Catalyst app?

Get tweet by ID with Twitter::Net

I have a most simple task: I try to read programmatically a tweet given its ID. For the access to the Twitter API, I use Perl's Twitter::Net API .
In lack of a clear documentation of which methods Twitter::Net provides (the docu is very verbose on the search method, as if that would be the only method of interest, but it doesn't even provide a list of all supported methods), I had to work with trial and error.
Twitter's REST API doc says:
GET statuses/show/:id - returns a single Tweet, specified by the id
parameter. The Tweet's author will also be embedded within the tweet.
I create a Twitter::Net instance, using my credentials and the REST 1.1 trait,
my $nt = Net::Twitter->new(
traits => [ qw/API::RESTv1_1/ ],
consumer_key => '...',
consumer_secret => '...',
access_token => '...',
access_token_secret => '...',
ssl => 1
);
Now I tried
my $t = $nt->show( <tweet_id> );
with no success:
Tweets11.pm: Can't locate object method "show" via package "Net::Twitter_v4_01002_with__API_RESTv1_1__OAuth" at Tweets11.pm line 25.
Similar message with statuses instead of show.
How to afford this very simple task with Perl's Twitter::Net?
Per the docs for Twitter::Net, the method you want is actually show_status:
show_status
show_status(id)
Parameters: id, trim_user, include_entities, include_my_retweet
Required: id
Returns a single status, specified by the id parameter. The status's author will be returned inline.
Returns: Status