Ajax - responseText working but responseXML null - php

I am trying my first AJAX and having a problem with my xml receiving function.
I alert responseText and I can see the xml returned from my server, but when I try and get responseXML I get null and the error.
Here is the php function that builds my xml
header('Content-type: application/xml');
echo("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
echo("<results>");
echo("<table><![CDATA[tablereererere]]></table>");
//echo("<ratedTable>".$_POST['ratedTable']."</ratedTable>\n");
//echo("<table>".$_POST['table']."</table>\n");
//echo("<post_id>".$_POST['post_id']."</post_id>\n");
//echo("<user_id>".$_POST['user_id']."</user_id>\n");
//echo("<rating>".$_POST['rating']."</rating>\n");
echo("</results>");
And here is my javascript function which is processing the returned xml
function ajaxReceiver(http_request) {
//this function continues to run until a result is returned and then it creates the new div
if(http_request.readyState == 4) {
response_xml = http_request.responseXML;
response_text = http_request.responseText;
alert(response_text);
alert(response_xml.getElementsByTagName("table")[0].textContent);
//document.getElementById('floatingNotification').innerHTML = response_text;
// alert(http_request.responseXML.getElementsByTagName("table")[0].textContent);
//ratedTable = responseXML.getElementsByTagName("table").value;
//alert(ratedTable);
//message = response.getElementsByTagName('table')[0].textContent;
//alert(message);
//alert(message);
//this response contains the xml document that was returned by the php function.You can get any values out of the xml document and
//use javascript dom to manipulate the contents on the page
}
}

It may be because, even though you're setting the content-type correctly, you need to have an <xml tag in the top of your response. Also, you aren't closing your last tag properly. This should work:
echo("<?xml version='1.0'?>");
echo("<results>");
echo("<ratedTable>".$_POST['ratedTable']."</ratedTable>");
echo("<table>".$_POST['table']."</table>");
echo("<post_id>".$_POST['post_id']."</post_id>");
echo("<user_id>".$_POST['user_id']."</user_id>");
echo("<rating>".$_POST['rating']."</rating>");
echo("<message>$message</message>");
echo("</results>");
For more info on how to define your XML: http://www.w3.org/TR/REC-xml/#sec-prolog-dtd

You are closing the parent node improperly (</results> not <results/>) and you should (after sanitizing it) wrap all the POSTDATA in <![CDATA[...]]> tags to be safe. Make sure it's UTF8 encoded, too (see utf8_encode())
EDIT: and what wajiw said about the <?xml version="1.0" encoding="UTF-8" ?> tag at the beginning.
Edit: Example CDATA Block Usage
<?xml version="1.0" encoding="UTF-8" ?>
<myNode>
<myData><![CDATA[
Now I just throw in my data, for fun and profit!
This way I can use special, reserved characters like <, > and &!
]]></myData>
</myNode>
Edit Yet Again:
Why not give Content-Type: text/xml, NOT application/xml, a go?

The answer is to put the asynchronous property in the function "open()" to false.
Like this:
ajaxObject.open("POST", "my_XML_Generator.php", false);
ajaxObject.setRequestHeader("Content-type", "text/xml");
ajaxObject.send();

I had the same problem and couldn't solve it until I put my results into subnodes, e.g.
header("Content-Type: text/xml; charset=utf-8");
echo("<?xml version='1.0' encoding='utf-8'?>\n");
echo("<summary>$summary</summary>\n");
echo("<content>$content</content>\n");
didn't work for me for some weird reason, but this does:
header("Content-Type: text/xml; charset=utf-8");
echo("<?xml version='1.0' encoding='utf-8'?>\n");
echo("<page>\n");
echo(" <summary>$summary</summary>\n");
echo(" <content>$content</content>\n");
echo("</page>\n");
My code retrieving the answer is
function retrieveRequest(title)
{
if (_xmlRequest.readyState == 4 && _xmlRequest.status == 200)
{
var xmlResponse = _xmlRequest.responseXML;
_divSummary.innerHTML = xmlResponse.getElementsByTagName("summary")[0].textContent;
_divContent.innerHTML = xmlResponse.getElementsByTagName("content")[0].textContent;
}
}

I had this error happen to our team once and it took me a long time before we realized that the problem was in our XML data returned from the server. In particular, PHP script that generated return XML string was the culprit.
My solution was to remove any white space from the beginning of the PHP script. I mean any spaces, new lines, and/or tabs need to be removed from the beginning of the script, so that the first thing in the script is the <?php tag itself. It turned out that the <?PHP tag was not the first thing on the first line of my PHP script; somehow I started my code on the second line and the first script line was simply an empty one.
It drove me mad and it took some time for me to figure this out, so I hope someone else can benefit from this solution. It is very simple and easy to try if all else fails.

Related

How can I load POST data into SimpleXML?

I need to post XML data from a textarea input to PHP so I can parse it and output a table.
I've tried a few methods and none seem to be working.
Currently I have this:
jQuery('#btnRegistrarXML').live('click', function(){
var xml;
if (jQuery('#txtRegXML').val() == ""){
AddMsg('You must paste XML from the excel export into the textarea.', 'error');
} else {
jQuery.post('registrar-xml-to-table.php', {xml:escape(jQuery('#txtRegXML').val())}, function(data){
jQuery('#regXMLasTable').empty();
jQuery('#regXMLasTable').append(data);
});
}
displayMsgs();
});
The PHP is:
$xmlraw = urldecode($_POST['xml']);
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xmlraw);
$dom->formatOutput = TRUE;
$xmlstr = $dom->saveXml();
$xml = simplexml_load_string($xmlstr);
echo "<p>xmlraw:</p>";
echo $xmlraw;
echo "<p>xml:</p>";
echo $xml;
foreach ($xml->document as $doc) {
echo '<p class="alert alert-error">'.$doc->title.'</p>';
}
The first echo $xmlraw is working - it outputs the XML string all on one line - the post is sending the data through properly.
The second echo $xml doesn't output anything and the foreach doesn't output anything either - something is not working in the PHP
I've also tried loading $xmlraw directly into simplexml_load_string($xmlraw) but it doesn't work - I'm assuming because it's not well formed?
The XML I'm using to test is:
<?xml version="1.0"?>
<document>
<title>
Foobar
</title>
</document>
You can paste the XML into the textarea on this ( http://tsdexter.com/webservice-testing/programs-list.php ) page and then if you inspect element underneath xmlraw: you can see that the raw xml string was echoed - however, underneath xml: there is nothing and also the foreach doesn't output anything either.
Here's a jsFiddle so you can see the HTML/JS - it doesn't actually do anything though because it can't ajax to the PHP page - so I included the PHP version above to test. http://jsfiddle.net/tsdexter/EDqQB/
Any ideas?
A few questions, which may or may not constitute an answer, but needed more space than a comment.
Why are you running urldecode on the $_POST variable? PHP should be doing that for you, unless you are double-escaping it somewhere.
Why are you loading into DOM and then SimpleXML? I know you said you tried without, but they use the same XML parser underneath, so there is no way this will help you rather than introducing more confusion.
What does var_dump(simplexml_load_string($rawxml)) give you? My guess would be FALSE, meaning an error. In which case, check you have warnings turned on (error_reporting(E_ALL); ini_set('display_errors', '1');) and detailed XML error handling turned off (libxml_use_internal_errors(false);).
In case it does give you a SimpleXMLElement object, don't spend too long looking at the var_dump output. Try one of these debugging functions instead.

PHP / CakePHP returning malformed XML

Basically I am trying to add Google Checkout order processing (level 2 integration) into a CakePHP app using the Google Checkout PHP sample code.
I can successfully create carts and receive notifications sent from Google to my app, however it cannot acknowledge these properly.
The function in google's code to do this echo's this:
<?xml version="1.0" encoding="UTF-8" ?><notification-acknowledgment xmlns="http://checkout.google.com/schema/2" serial-number="119963104284921-00001-7" />
However Google Checkout receives that code like this:
<?xml version=1.0 encoding=UTF-8 ?><notification-acknowledgment xmlns="http://checkout.google.com/schema/2" serial-number=119963104284921-00001-7 />
I can't work out what is causing this, I don't think it has anything to do with Cake and I've disabled PHP short tags so I can use inline XML but this makes no difference.
If I remove the first < from the string, the function echo's the rest of the code correctly, leave it in and it brakes (obviously this also applies for the ? and closing > symbol too, I just cant't have all of them at once!).
I have been able to replicate this myself in attempt to remove any unseen stuff being done in the Google Code using the function below. It does exactly the same thing but is contained within a (Cake) controller and hard codes the variables.
public function blank($tags = null) {
$schema = 'http://checkout.google.com/schema/2';
$serial = '119963104284921-00001-7';
if ($tags != null) {
$acknowledgment = '<?xml version="1.0" encoding="UTF-8" ?'.'>'.'<notification-acknowledgment xmlns="'.$schema.' '.'serial-number="'.$serial.'" />';
} else {
$acknowledgment = '?xml version="1.0" encoding="UTF-8" ?>'.'<notification-acknowledgment xmlns="'.$schema.' '.'serial-number="'.$serial.'" />';
}
$this->set('_ack', $acknowledgment);
}
The IF statement is used to show the difference the < symbol makes.
Calling it with nothing ($tags == null) gives this output:
<?xml version="1.0" encoding="UTF-8" ?><notification-acknowledgment xmlns="http://checkout.google.com/schema/2" serial-number="119963104284921-00001-7" />
Source.
Calling it with any other value ($tags != null) gives this output:
<?xml version=1.0 encoding=UTF-8 ?><notification-acknowledgment xmlns="http://checkout.google.com/schema/2" serial-number=119963104284921-00001-7 />
Source.
My question (finally!) is, why does this happen? and how can I get it output the XML correctly?
Sorry if I've missed something really obvious, but I'd rather have it pointed out here than faff around getting nowhere for another day!
this "problem" has to do with the PHP interpreter.
There are solutions but everything in View not in the Controlled.
//var
$questionmark = "?";
echo "<".$questionmark."xml version=\"1.0\" encoding=\"utf-8\"".$questionmark.">";
// separate
echo '<' . '?xml version="1.0" encoding="utf-8"?' . '>';
You forgot to close the quotes on the xmlns attribute, that's the probable cause. Try this:
$acknowledgment = '<?xml version="1.0" encoding="UTF-8" ?'.'>'.'<notification-acknowledgment xmlns="'.$schema.'" '.'serial-number="'.$serial.'" />';
Some XML parsers do not allow specifying the encoding in capital letters (e.g. UTF-8 is incorrect).
Try changing the encoding to "utf-8" to see if that fixes it.

PHP -> XML output is different on IE

I have been trying to output XML with PHP but encountered a strange(!) error in Internet Explorer.
The expected xml output is this:(simplified)
<root>
<match_id>12</match_id>
<stadium_id>43</stadium_id>
<tribune_id>2</tribune_id>
<fan_id>453</fan_id>
</root>
I am producing this output with the following PHP code:
echo "<?xml version='1.0' encoding='utf-8' ?>
<root>
<match_id>"; echo $match->getId(); echo "</match_id>
<stadium_id>43</stadium_id>
<tribune_id>2</tribune_id>
<fan_id>".$_SESSION['user_id']."</fan_id>
</root>";
In Firefox, the output is same as expected. However, in IE, the output is this:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<match_id>0</match_id>
<stadium_id>43</stadium_id>
<tribune_id>2</tribune_id>
<fan_id />
</root>
This is a really annoying error. I have set the PHP header for XML output, and changed lots of other things but could not make it work.
The $match->getId() part is just returning an integer but IE always shows this value as 0. If I set <fan_id> and <match_id> manually, IE shows the values correctly.
By the way, I am using this XML output in Flash (AS3) and this also shows the same result with IE.
What am I doing wrong?
This looks like it's due to a session difference - the IE session isn't storing the user id. Similarly, $match->getId() is actually 0 - I imagine you'd get a similar result using Chrome or Safari or a web browser on any other computer.
One other thing: Flash may not be sending the PHP session cookie to the server on the request - which would match the IE behavior / no valid session.
Try:
header( "content-type: application/xml; charset=ISO-8859-15" );
OR
$doc = new DOMDocument;
$root = $doc->createElement('root');
$doc->appendChild($root);
$match_id = $doc->createElement('match_id', $match->getId());
$root->appendChild($match_id);
$stadium_id = $doc->createElement('stadium_id', '43');
$root->appendChild($stadium_id);
$tribune_id = $doc->createElement('tribune_id', '2');
$root->appendChild($tribune_id, '2');
$fan_id = $doc->createElement('fan_id', $_SESSION['user_id']);
$root->appendChild($fan_id);
echo $doc->saveXML();
//$doc->save('file.xml'); // if you want to write to file
What browser is used has no effect on how your PHP executes (because it's executed on server, not in browser). Notice that in the second example your fan_id is also empty, which indicates something's wrong with your session setup. Investigate this.
Having said all that: did you consider using simplexml() to output XML from PHP? It's much more fun to use than echoing tags.

prob!em with sending xml (declaration xml) with php

my question is actually
What kind off structure would I use to send xml as part off a REST service if I have most off the logic in a class. I call/include the class at the top off my php index page if it becomes clear a service is being requested.
Someone mentioned to me that a class method should not output anything.
Then where should I output the xml. Outside the class?
Also I have a problem that the receiving end is saying that the declaration should start at the start off the document.
The receiving end only has these two lines in the document.
I do not have code to process it yet, but this already gives an error.
<?php
$url='http://www.woonbel.nl/gps/setgpsloc';
$xml =simplexml_load_string(file_get_contents($url));
?>
I send the xml from this class as you can see, so maybe here something go's wrong,
something with white lines or something else.
Anyway, I need some advice how to avoid the declaration error and how to send xml if I am not supposed to do it in a method?store it in a class variable first then maybe?
<?php
class gps {
public $url;
public $test;
function __construct($url) {
$this->url = $url;
}
function invoke($methode_naam) {
switch($methode_naam){
case "test":
$this->setgpsloc();
break;
case "setgpsloc":
header('Content-type: text/xml');
$status_code = 2;
$output= "<?xml version=\"1.0\"encoding=\"utf-8\"?>\n";
$output.= "<response>\n";
$output.= "\t<status>$status_code</status>\n";
$output.= "\t<fout>Geen</fout>\n";
$output.= "</response>";
echo trim($output);
}
}//EINDE invoke
}
?>
This is how I detect if a service is requested and call the class
<?php
//WEBSERVICE SECTIE
$url = $_GET['url'];
$parts = split('/', $url); // Opslaan van delen van de aangevraagde url in $parts
$cparts=count($parts);
//if($cparts>=2){
$controller = $parts[0];
$wslijst=array("gps","gebruikers");
if(in_array($controller,$wslijst)){
include $controller .".php";
$clr = new $controller("test");
$clr->invoke($parts[1]);
exit();
}
//other code underneath for displaying normal page
?>
This is the actual error the receiving end get's
PHP Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 4: parser error : XML declaration allowed only at the start of the document in D:\Domains\tsa.nl\wwwroot\index.php on line 4 PHP Warning: simplexml_load_string() [function.simplexml-load-string]: in D:\Domains\tsa.nl\wwwroot\index.php on line 4 PHP Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in D:\Domains\tsa.nl\wwwroot\index.php on line 4
As in "http://www.woonbel.nl/gps/setgpsloc", you have blank spaces before the XML declaration.
I recommend you trim (http://php.net/trim) your output.
//Edit, you forgot a space between \" and encoding bellow
$output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
//-----------------^
$output .= "<response>\n";
$output .= "\t<status>$status_code</status>\n";
$output .= "\t<fout>Geen</fout>\n";
$output .= "</response>";
echo trim($output);
If there is something else in your code that maybe are sending these outputs, you can get it on a buffer:
//In the beginning of your script
ob_start();
//In the end of your script
$output = ob_get_clean();
echo trim($output);
There is a good chance that our problem is the same I was having. The solution was really simple, as expected. Every page on my site require__once a file with some classes I made to parse and manage the site. This file had a space ' ' right after the closing php tag ?>
As that space is outside of the script, it was included on the document by default when require was called. So, check the end of all the files you are including/requiring. My pages are declaring the <?xml without problems now. IT HAS TO BE THE FIRST THING!
Here is my validation: W3C VALIDATOR TO MY PAGE
You can find the site link there as well (it is my father's band site.. lol)
So, check any space or newline OUTSIDE THE <?PHP ?> that is probably where it is coming from (using include or require will parse that outside the script, on the html document (and before you parse or execute anything else, that came in when you included the file, so it is 'before' everything you are doing, trimming is out of your power and scope on this case).
PS: If you check the Validator, and then go to the page and check the source code, you will see the <?xml declaration, My pages are 100% parsed (No PHP inside HTML).
Hope this helps...
Cheers! :)
Well, the quick answer is that you have 4 blank lines before your "<?xml" in the document, which is causing the error. You'll need to go through your code and find out what's doing that (although I can't honestly figure out how that's happening, because the header would theoretically throw an error if you sent any output before it). The code you've posted definitely doesn't output the extra 4 lines before the xml declaration, so the issue's elsewhere in your code :)
[UPDATE] Wish I could comment, but in regards to the other answer supplied, output buffering and trimming will certainly solve the problem, but the better solution would be to figure out where those extra 4 lines of whitespace are coming from (no insult intended, but trimming the output buffer is a bit of a band-aid solution)

PHP XML IE problem

<?xml version="1.0" ?>
<NBR>
<resultGroups>
<result>Hello</result>
</resultGroups>
</NBR>
i have a n xml created in PHP ike this. i am retruning this XML into javascript and is trying to acces the value of node "result" using
alert($(xmlObj).children('result').text());
In firefox its working fine. but in IE it gives out nothing...
how can i solve this???
It could be you are not sending the correct XML Content-Type header. You should send Content-Type: text/xml with XML content. You should also check that you set the correct charset in both the headers and the file. IE should be able to parse a correct XML response just fine if the JS code is correct and your XML response is valid.
My guess would that is has something to do with the text() function. I am a Prototype guy myself but I ran into a similar problem with IE a little while ago. It came from me trying to pull the textContent value from an element in the DOM. I could grab the value in all other browser but IE was giving me the shaft. After running some tests, this is what I came up with:
IE does not support element.textContent. In most browsers, like FireFox, you would be able to pull the textContent value from element.
Example
<p id="my_element">this is my element</p>
alert($('my_element').textContent); // will alert "this is my element"
In IE, you need to use element.innerHTML. This will return the value you want. Right now, I assume that text() is returning the textContent value and that is why you're getting no dice.
Example
<p id="my_element">this is my element</p>
alert($('my_element').innerHTML); // will alert "this is my element"
Hope this helps!
Are you loading this across SSL?
There is a known issue in IE where sometimes it fails to load XML over SSL:
http://support.microsoft.com/default.aspx?scid=kb;en-us;272359
This page contains more info on how to resolve it:
http://www.blog.lessrain.com/flash-nasty-xml-load-bug-in-internet-explorer/
Ensure that your in your headers that you're specifying the Content-Type and charset, and that your charset (if using utf-8) is utf-8 and not utf8. IE doesn't recognise the latter and doesn't bother to tell you.
So, you want your header to specify the following:
Content-Type: application/xml; charset=utf-8
Have you tried parsing the data out before alert'ing it, and possibly using find instead?
var node_text = $(xmlObj).find('result').text();
alert(node_text);
Otherwise i would suggest trying to change the result tag to something different (like theresult) - everyone knows IE likes to do strange things! :)
If <result> is inside <resultGroups>, then try:
alert($(xmlObj).children('resultGroups').children('result').text());
or, you could try:
alert($($($(xmlObj).children('resultGroups')).children('result')).text());
or even:
alert($($(xmlObj).children('result')).text());
Let me know if any of these work.

Categories