PHP XML converter response - php

im quite new on XML, i am currently work in PHP and i have a request to other server which normaly and always return the callback with XML
In any case i would not talk about how i get the response, but how to convert the XML reponse.
They are two type of the XML response, we could call it as $response
first :
<BASEELEMENT SCHEMA="RESULT" METHOD="ADD-MBX">
<RETURN_VALUE>4</RETURN_VALUE>
<ERROR_DESCRIPTION>
<![CDATA[Error (7004): Login name already exists. Please use another login name.]]>
</ERROR_DESCRIPTION>
</BASEELEMENT>
and the second one is :
<baseelement schema="TIMEOUT" method="ADD-MBX"></baseelement>
i have searched and i got how to convert the xml reponse to obejct or array, which is
$response = new \SimpleXMLElement($response);
after convert :
object(SimpleXMLElement)#256 (3) {
["#attributes"]=>
array(2) {
["SCHEMA"]=>
string(6) "RESULT"
["METHOD"]=>
string(7) "ADD-MBX"
}
["RETURN_VALUE"]=>
string(1) "4"
["ERROR_DESCRIPTION"]=>
object(SimpleXMLElement)#257 (0) {
}
}
as we can see the ERROR_DESCRIPTION become 0.
So i would like to ask, is there any xml converter else simplexml_load_string() or new \SimpleXMLElement()
i cant use that function because i could not get the ERROR_DESCRIPTION
thank you :)

Loading it as you are with -
$response = new \SimpleXMLElement($response);
You can fetch the value quite simply as...
echo (string)($response->ERROR_DESCRIPTION).PHP_EOL;
If you want the full content (as in an XML version)...
echo $response->ERROR_DESCRIPTION->asXML().PHP_EOL;
Using XPath, you can fetch the values by...
echo (string)$response->xpath("//ERROR_DESCRIPTION")[0].PHP_EOL;
The output you are seeing shows that ERROR_DESCRIPTION is an object of SimpleXMLElement type, not that it isn't loaded.

Related

Puphpeteer - Get text and href-attribute from link

I am using "#nesk/puphpeteer": "^2.0.0" Link to Github-Repo and want get the text and the href-attribute from a link.
I tried the following:
<?php
require_once '../vendor/autoload.php';
use Nesk\Puphpeteer\Puppeteer;
use Nesk\Rialto\Data\JsFunction;
$debug = true;
$puppeteer = new Puppeteer([
'read_timeout' => 100,
'debug' => $debug,
]);
$browser = $puppeteer->launch([
'headless' => !$debug,
'ignoreHTTPSErrors' => true,
]);
$page = $browser->newPage();
$page->goto('http://example.python-scraping.com/');
//get text and link
$links = $page->querySelectorXPath('//*[#id="results"]/table/tbody/tr/td/div/a', JsFunction::createWithParameters(['node'])
->body('return node.textContent;'));
// iterate over links and print each link and its text
// get single text
$singleText = $page->querySelectorXPath('//*[#id="pagination"]/a', JsFunction::createWithParameters(['node'])
->body('return node.textContent;'));
$browser->close();
When I run the above script I get the nodes from the page, BUT I cannot access the attributes or the text?
Any suggestions how to do this?
I appreciate your replies!
querySelectorXPath return array of ElementHandle. one more thing querySelectorXPath does not support callback function.
first get all node ElementHandle
$links = $page->querySelectorXPath('//*[#id="results"]/table/tbody/tr/td/div/a');
then loop over links to access attributes or text of node
foreach($links as $link){
// for text
$text = $link->evaluate(JsFunction::createWithParameters(['node'])
->body('return node.innerText;'));
// for link
$link = $link->evaluate(JsFunction::createWithParameters(['node'])
->body('return node.href;'));
}
Disclaimer: This is just an intermediate answer - I would update once I've got more specific requests on HTML attrs or other expectations to be retrieved.
tl;dr: Mentioned composer package nesk/puphpeteer really is just a wrapper to underlying NodeJS based implementation of puppeteer. Thus, accessing data and structures has to be "similar" to their JavaScript counterparts...
Maybe Codeception (headless) or symfony/dom-crawler (raw markup) might be better and more mature alternatives.
Anyway, let's pick the example from above and go through it step by step:
$links = $page->querySelectorXPath(
'//*[#id="results"]/table/tbody/tr/td/div/a',
JsFunction::createWithParameters(['node'])->body('return node.textContent;')
);
XPath query $x() would result in an array of ElementHandle items
to access exported node.textContent (from JsFunction), corresponding data gets fetched via ElementHandle.getProperty(prop)
exporting a scalar value (to PHP) is then done via ElementHandle.jsonValue()
Thus, after that we would have something like this:
$links = $page->querySelectorXPath(
'//*[#id="results"]/table/tbody/tr/td/div/a',
JsFunction::createWithParameters(['node'])->body('return node.textContent;')
);
/** #var \Nesk\Puphpeteer\Resources\ElementHandle $link */
foreach ($links as $link) {
var_dump($link->getProperty('textContent')->jsonValue());
}
Which outputs the following raw data (as retrieved from http://example.python-scraping.com/):
string(12) " Afghanistan"
string(14) " Aland Islands"
string(8) " Albania"
string(8) " Algeria"
string(15) " American Samoa"
string(8) " Andorra"
string(7) " Angola"
string(9) " Anguilla"
string(11) " Antarctica"
string(20) " Antigua and Barbuda"

How to end a transaction after rendering an HTML return

I'm tring implement this API : https://developer.vivawallet.com/web-api-integration/native-checkout-v2-api/. I got the response from the server after sending the card number, something like:
{
"chargeToken": "ctok_bcGN8H87tGi1qtxtEoYkliYgMrc",
"redirectToACSForm": "<html><head></head><body>Hey there! Don't
forget to render me!</body></html>"
}
So I recived a error (Browser closed before authentication finished).
My question is how to render the string: redirectToACSForm, wait for your return and then get the chargeToken variable?
the erro Api response:
array(3) {
["status"]=>int(400)
["message"]=>string(45) "PaymentsCardHolderAuthenticationInvalidStatus"
["eventId"]=> string(4) "2061"
}

How Do I read CloudKit Errors?

I have a php script that's trying to create a record in a CloudKit database.
It returns this error:
object(stdClass)#1 (3) { ["uuid"]=> string(36)
"c70072a1-fab6-491b-a68f-03b9056223e1" ["serverErrorCode"]=>
string(11) "BAD_REQUEST" ["reason"]=> string(62)
"BadRequestException: Unexpected input at [line: 2, column: 10]" }
I presume this tells me exactly what the problem is, but I don't know how to interpret it. Where is line 2 and column 10?
I think its related to the JSON I'm sending in the create record request.
$url = 'https://api.apple-cloudkit.com/database/1/' . $CONTAINER . '/development/public/records/modify';
$opDict = '{"operationType": "create",
"record":"Artists",
"fields": {"firstName":{"value":"Mei"},
"lastName": {"value":"Chen"},
"principalDiscipline": {"value":""},
"secondaryDiscipline":{"value":""}},
"recordName":"Mei Chen"}';
$body = '{"operations":['.$opDict.']}';
echo $body;
When I check the output from $body
{"operations":[{"operationType": "create", "record":"Artists",
"fields": {"firstName":{"value":"Mei"}, "lastName": {"value":"Chen"},
"principalDiscipline": {"value":""},
"secondaryDiscipline":{"value":""}}, "recordName":"Mei Chen"}]}
it passes JSON lint, so I am not sure it is a JSON problem.
Can someone explain to me how to interpret the error I'm getting from CloudKit. The docs are a little vague on errors.
I got absolutely no clue about CloudKit, but I found this documentation page with the followin example:
{
"operationType" : "create",
"record" : {
"recordType" : "Artist",
"fields" : {
"firstName" : {"value" : "Mei"},
"lastName" : {"value" : "Chen"}
}
"recordName" : "Mei Chen"
},
}
which definitely differs from what you try to send, both in terms of data structure
(your record is not a dictionary) and content (you have no recordType).
So while your JSON is syntactically correct, you are simply sending invalid content data wrapped in valid JSON which is most likely the reason you are seeing the error message.

SOAP web service not recognizing ArrayOfAnyType from PHP client for Agemni Database API

I am trying to insert a lead into the SOAP web service with this WSDL: http://www.agemni.com/AgemniWebservices/service1.asmx?WSDL
The API is documented here: http://wiki.agemni.com/4Integration_And_API%27s/APIs/Database_API
This web service's back end code seems to be in .NET.
Here is my code:
// Create soap client.
try {
$this->client = new SoapClient("https://www.agemni.com/AgemniWebservices/service1.asmx?WSDL", array('soap_version' => SOAP_1_2, 'cache_wsdl' => 0, "trace" => true));
} catch (Exception $e) {
$this->logMessage('Couldn\'t connect to web service.');
throw $e;
}
// Create parameters.
$dataParams = new \stdClass;
$dataParams->strUsername = 'userman';
$dataParams->strPassword = 'hissecretpassword';
$dataParams->strCompanyName = 'validcompanyname';
$leadCode = 2;
$dataParams->objecttype = $leadCode;
// Create keys.
$dataParams->keys = new \stdClass;
$dataParams->keys->Phone = 'Phone';
// Create values.
$dataParams->values = new \stdClass;
$dataParams->values->Phone = '8011234567';
// Call web service.
$validateResult = $this->client->CreateEntity($dataParams);
Here is the response I receive:
object(stdClass)#27 (1) {
["ValidateEntityResult"]=>
object(SoapVar)#29 (4) {
["enc_type"]=>
int(0)
["enc_value"]=>
object(stdClass)#28 (10) {
["statusCode"]=>
string(9) "Succeeded"
["status"]=>
string(5) "Error"
["description"]=>
string(56) "Phone number is required and needs to be 10 digits long."
["errorNumber"]=>
int(1)
["xmlResult"]=>
string(39) "<?xml version="1.0" standalone="yes" ?>"
["EntityValidated"]=>
bool(false)
["EntityCreated"]=>
bool(false)
["EntityUpdated"]=>
bool(false)
["EntityIDCreated"]=>
int(0)
["isloggedIn"]=>
bool(false)
}
["enc_stype"]=>
string(15) "ExceptionReport"
["enc_ns"]=>
string(44) "http://tempuri.org/AgemniWebService/Service1"
}
}
I found a similar issue on PHPFreaks that was years old and was never successfully answered. I see other similar issues with nesting parameters in the PHP SoapClient, but all of the suggestions I've seen end in the same error message for me.
The authentication is being received just fine, along with the company name. However, I've stabbed at formatting, parsing, and encoding the keys and values parameters in nearly every way I could conceive. I've played with declaring my parameters as SoapVar and SoapParam with every potential constructor parameter I could think of and still have received the same error message.
I'd greatly appreciate any suggestions as to any reason that someone could suppose that the Agemni web service is not accepting my lead's phone number.
Thanks.
Update
I can just generate the XML request I need in a string and send it using cURL, but I'd like to use SoapClient. However, I have a hard time generating the elements within the keys and values nodes to look like this:
<anyType xsi:type="xsd:string">phone</anyType>'
I followed some guides on creating custom complex types in SoapClient, but I couldn't get it to create XML that looks like that.

php if statement

I am using a twitter class to post updates to my account for this I have removed my twitter credentials so I am aware that XXXXX is wrong. I am able to parse the text from the remote xml file. This xml files text always reads "There are no active codes." So in my if statement i said that if the xml file reads "There are no active codes." i dont want to post anything to my twitter, but if it changes to anything else then i would like to parse that information and post it to my twitter. So today when there was an update to the xml file nothing happened. I know that the twitter portion is correct because I have a similar script that does not use an if statement and it posts fine. Once i introduced the if statement i have run into problem of not being able to post. So what can i do to post to twitter only when the xml file changes from "There are no active codes." to anything else?
// Parse Message
$source = file_get_contents('WEBSITE_URL_GOES_HERE');
$dom = new DOMDocument();
#$dom->loadHTML($source);
$xml = simplexml_import_dom($dom);
$match = $xml->xpath("//code_message");
//Twitter class (Updating status)
require_once 'twitteroauth.php';
//Twitter credentials
define("CONSUMER_KEY", "XXXXXX");
define("CONSUMER_SECRET", "XXXXXX");
define("OAUTH_TOKEN", "XXXXXX-XXXXXX");
define("OAUTH_SECRET", "XXXXXX");
// Verify credentials
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_SECRET);
$content = $connection->get('account/verify_credentials');
//If Statement
if ( $match[0] == "There are no active codes." ) {
/* Do Nothing */;
} else {
$connection->post('statuses/update', array('status' => 'New Code Available - ' . $match[0] ));
return $connection;
}
var_dump of the $match array:
array(1) { [0]=> object(SimpleXMLElement)#3 (1) { [0]=> string(32) "There are no active codes." } }
You should probably use a string comparison function.
like strcmp : http://php.net/manual/en/function.strcmp.php
if (strcmp($match,"There are no active codes.") != 0 )
{
$connection->post('statuses/update', array('status' => 'New Code Available - ' . $match[0] ));
return $connection;
}
Why don't you just add some debugging code and check what's going on? Echo you $match[0] and check what's in there. It's hard to imagine "if" being broken, isn't it? Maybe var_dump($match) just to check what's going on. Then you should probably either fix your condition or fix the retrieval of $match.
Check your array: the [0] element is an object, not a string. You need to get the first element of that object, if you know what I mean.
You are comparing:
Object(SimpleXMLElement)#3 (1) { [0]=> string(32) "There are no active codes." }
to
"There are no active codes."
Which is obviously not the same.
I can't test it from here, but check out the manual of simpelXMLElement: http://php.net/manual/en/class.simplexmlelement.php
You should probably get away with a simple call. Just check out what kind of object you have. A simple example would be something like "$match[0]->childname", but I can't quickly see what the childname is. Check out the manual for some sort of getchild or something, shouldn't be too tricky

Categories