$file = simplexml_load_file($url); {
foreach($file->entry as $post) {
$row = simplexml_load_string($post->asXML()); // after adding this line, i get error message
$links = $row->xpath('//link[#rel="alternate" and #type="text/html"]');
echo (string) $post->title;
echo (string) $links[0]['href'];
I use this script to parse atom feed. At first didn't work because it couldn't pass the link's href attribute properly. I added $row and even though it worked, it gives an error : "namespace prefix gd for etag on entry is not defined". I'm searching this for hours, can't find a solution. I was so close.
The line $row = simplexml_load_string($post->asXML());, if it worked, would be a long-winded way of writing $row = $post. ->asXML() and simplexml_load_string perform the opposite action to each other so you'd get back the same object you started with.
I think the reason it's behaving strangely in your case is that your XML document is using "namespaces", and the fragment of XML produced by $post->asXML() doesn't quite work as an XML document on its own.
I suspect that the original problem you had, which this line seemed to magically fix, was also with namespaces, as XPath is rather sensitive to them. Look up examples of using registerXPathNamespace and see if they solve your problem. If not, feel free to post a follow-up question showing your original problem, and including a sample of the XML you're processing.
Related
I need help to extract value from a soap response.
https://i.stack.imgur.com/djv5y.jpg
What i exactly need is:
$username=user
$message=success
Maybe include the SOAP response here, that would be helpful for those who come in the future. As for your question are you using a particular language? That would make it easier to answer.
If you are looking for a way to view use can use this URL: https://codebeautify.org/xmlviewer
Ok now that I see it, it's fairly easy
Assuming you have loaded the SOAP XML into a variable, lets call it $xml_string
$xml = simplexml_load_string($xml_string); // Load it as an object
$xmlarray = json_decode(json_encode($xml),TRUE); // Change it into an array
Then the variables you are looking for is in
$username = $xmlarray['UserName'];
$message = $xmlarray['response']['MESSAGE'];
BTW This solution is found here
PHP convert XML to JSON
I did it as an array as sometimes objects are a little hard to process. You can easily just do the first line and address it as an object. (If those are the only variables you need then an array works fine. Ex: the 'Plan' data will be messed up in an array as it appears twice)
There can be some issues such as the MESSAGE not appearing or the XML returning a failure but I think you should know how to code around missing datum.
I'm having a horrible trouble getting this XML to be properly parsed through PHP's SimpleXMLElement. The error that I'm getting (below) is looking like it's a parsing error, but I can't seem to find any issue. And, since this is the National Weather Service's alerts feed, I would have to assume others are pulling this feed and getting it to correctly work.
I've tried all the the following and several variations of them:
$simpleFeed = new SimpleXMLElement(simplexml_load_string(file_get_contents('http://alerts.weather.gov/cap/us.php?x=0')));
and
$simpleFeed = new SimpleXMLElement(simplexml_load_string('http://alerts.weather.gov/cap/us.php?x=0'));
and
$simpleFeed = new SimpleXMLElement('http://alerts.weather.gov/cap/us.php?x=0', NULL, TRUE);
I've included the error that I'm currently getting, but the line numbers do occasionally change around (I'm not sure if that's my doing or the National Weather Service's Feed's doing):
SimpleXMLElement::__construct(): Entity: line 107: parser error : Start tag expected, '<' not found
SimpleXMLElement::__construct():
SimpleXMLElement::__construct(): ^
Every XML parser / validator that I run this through says that it's valid, with a few warnings. I'm not seeing anything here that would indicate the XML is the problem, except that the error message makes it look like that is the case.
Does anyone have experience with something like this and can help?
To spare you some misdirections and extra-routes:
$simpleFeed = new SimpleXMLElement(simplexml_load_string(file_get_contents('http://alerts.weather.gov/cap/us.php?x=0')));
is really over-doing it. In two ways:
simplexml_load_string(file_get_contents(...)) is actually just simplexml_load_file(...). PHP uses the same layer internally to get the date, regardless from within simplexml_load_file or file_get_contents. It's not hurting, but I think you should know.
more hurting (in the meaning of incompatible) is that you can't instantiate a SimpleXMLElement passing the SimpleXMLElement as the first parameter of it's contructor. That just does not work. I wonder you haven't seen other errors, you might think you can "skip" those safely, but it's actually crucial you listen to error messages when developing and running software (see How to get useful error messages in PHP?).
So what does this ranting list say? Simple in code:
$feedURL = http://alerts.weather.gov/cap/us.php?x=0';
$xml = simplexml_load_file($feedURL);
if (!$xml) {
throw new UnexpectedValueException(
sprintf('failed to open %s', var_export($feedURL, true))
);
}
This little code-example will give you either a the SimpleXMLElement or will tell you otherwise. You don't have to argue whether or not the XML is valid or the parser can deal with it. For the rest of your application it would be the same. A failure to open the URL or a success. There is nothing else you need to worry about. If the URL is wrong, get the right one. If the XML might be broken, file a bug-report. Everything else is nothing you really need to worry about. Just don't put code together you have no know understanding about how it works. In that case, just read the manual how it's intended to work, double-check, trouble-shoot, listen to PHP error messages and more especially, introduce checks into your own software your own that deals with cases of failure. They are there. Design for those.
I'm using the following PHP code to read XML data from NOAA's tide reporting station API:
$rawxml = file_get_contents(
"http://opendap.co-ops.nos.noaa.gov/axis/webservices/activestations/"
."response.jsp?v=2&format=xml&Submit=Submit"
);
$rawxml = utf8_encode($rawxml);
$ob = simplexml_load_string($rawxml);
var_dump($ob);
Unfortunately, I end up with it displaying this:
object(SimpleXMLElement)#246 (0) { }
It looks to me like the XML is perfectly well-formed - why won't this parse? From looking at another question (Simplexml_load_string() fail to parse error) I got the idea that the header might be the problem - the http call does indeed return a charset value of "ISO-8859-1". But adding in the utf8_encode() call doesn't seem to do the trick.
What's especially confusing is that simplexml_load_string() doesn't actually fail - it returns a cheerful XML array, just with nothing in it!
You've been fooled (and had me fooled) by the oldest trick in the SimpleXML book: SimpleXML doesn't parse the whole document into a PHP object, it presents a PHP API to an internal structure. Functions like var_dump can't see this structure, so don't always give a useful idea of what's in the object.
The reason it looks "empty" is that it is listing the children of the root element which are in the default namespace - but there aren't any, they're all in the "soapenv:" namespace.
To access namespaced elements, you need to use the children() method, passing in the full namespace name (recommended) or its local prefix (simpler, but could be broken by changes in the way the file is generated the other end). To switch back to the "default namespace", use ->children(null).
So you could get the ID attribute of the first stationV2 element like this (live demo):
// Define constant for the namespace names, rather than relying on the prefix the remote service uses remaining stable
define('NS_SOAP', 'http://schemas.xmlsoap.org/soap/envelope/');
// Download the XML
$rawxml = file_get_contents("http://opendap.co-ops.nos.noaa.gov/axis/webservices/activestations/response.jsp?v=2&format=xml&Submit=Submit");
// Parse it
$ob = simplexml_load_string($rawxml);
// Use it!
echo $ob->children(NS_SOAP)->Body->children(null)->ActiveStationsV2->stationsV2->stationV2[0]['ID'];
I've written some debugging functions to use with SimpleXML which should be much less misleading than var_dump etc. Here's a live demo with your code and simplexml_dump.
I'm working on some system for a few hours now and this little thing is too much for me to think logically about at the moment.
Normally I would wait a few hours but this is a last minute job and I need to finish this.
Here's my problem:
I have an XML file that gets posted to my PHP file, the PHP file inserts certain data into a DB, but some XML nodes have the same name:
<accessoires>
<accessoire>value1</accessoire>
<accessoire>value2</accessoire>
<accessoire>value3</accessoire>
</accessoires>
Now I want to get a var $acclist which contains all values seperated by a comma:
value1,value2,value3,
I bet the solution to this is very easy but I'm at the known point where even the easiest piece of code becomes a hassle. And googling only comes up with nodes that in some way have their own identifiers.
Could someone help me out please?
You can try simplexml_load_string to parse the html then call implode on the node after casting to an array.
NOTE This code was tested in php 5.4.6 and behaves as expected.
<?php
$xml = '<accessoires>
<accessoire>value1</accessoire>
<accessoire>value2</accessoire>
<accessoire>value3</accessoire>
</accessoires>';
$dat = simplexml_load_string($xml);
echo implode(",",(array)$dat->accessoire);
For 5.3.x I had to change to
$xml = '<accessoires>
<accessoire>value1</accessoire>
<accessoire>value2</accessoire>
<accessoire>value3</accessoire>
</accessoires>';
$dat = simplexml_load_string($xml);
$dat = (array)$dat;
echo implode(",",$dat["accessoire"]);
You do this by taking a library that is able to parse and process XML, for example with SimpleXML:
implode(',', iterator_to_array($accessoires->accessoire, FALSE));
The key part here is to use iterator_to_array() as SimpleXML offers the same-named child-elements here as an iterator. Otherwise $accessoires->accessoire gives you auto-magically only the first element (if any).
Apologies if there is an obvious answer (and I know there are about 1000 of these similar questions) - but I have spent two days trying to attack this without success. I cannot seem to crack why I get a null response...
Short background: the following works just fine
$xurl= new SimpleXMLElement('https://gptxsw.appspot.com/view/submissionList?formId=GP_v7&numEntries=1', NULL, TRUE);
$keyname = $xurl->idList->id[0];
echo $keyname;
this provides a response: a unique key like uuid:d0721391-6953-4d0b-b981-26e38f05d2e5
however I try a similar request (which ultimately would be based on first request) and get a failure. I've simplified code as follows...
$xdurl= new SimpleXMLElement('https://gptxsw.appspot.com/view/downloadSubmission?formId=GP_v7[#version=null%20and%20#uiVersion=null]/GP_v7[#key=uuid:d0721391-6953-4d0b-b981-26e38f05d2e5]', NULL, TRUE);
$keyname2 = $xdurl->data->GP_v7->SDD_ID_N[0];
echo $keyname2;
this provides null. And if I try something like
echo $xdurl->asXML();
I get an error response from the site (not from PHP).
Do I need to eject from SimpleXMLElement for the second request? I've read about using XPath and about defining the namespace, but I'm not sure that either would be required: the second file does have two namespaces but one of them isn't used and the other has no prefix for elements. Plus I have tried variations of those - enough to think that my problem/error is either more global in nature (or oversight due to inexperience).
For purposes of this request I have no control over the formatting of either XML file.
Here we go: SimpleXMLElement seems to re-escape (or incorrectly handle in some way) already url-escaped characters like white spaces. Try:
$xdurl= new SimpleXMLElement('https://gptxsw.appspot.com/view/downloadSubmission?formId=GP_v7[#version=null and #uiVersion=null]/GP_v7[#key=uuid:d0721391-6953-4d0b-b981-26e38f05d2e5]', NULL, TRUE);
$keyname2 = $xdurl->data->GP_v7->SDD_ID_N[0];
echo $keyname2;
and you should be fine.
(FYI: I debugged this by manually creating a local copy of the XML request result named "foo.xml" which worked perfectly.)
Thanks to #Matze for getting me on right track.
Issue is that URL has special characters that SimpleXMLElement cannot parse without help.
Solution: add urlencode() command like the following
$fixurl = urlencode('https://gptxsw.appspot.com/view/downloadSubmission?formId=GP_v7[#version=null and #uiVersion=null]/GP_v7[#key=uuid:d0721391-6953-4d0b-b981-26e38f05d2e5]');
$xdurl= new SimpleXMLElement($fixurl, NULL, TRUE);
$keyname2 = $xdurl->data->GP_v7->SDD_ID_N[0];
echo $keyname2;
this provided the answer (in this case 958)