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)
Related
I have XML files as "pages" for my website. Now i faced with some bad situation: when i tried to put some PHP-code inside XML it saves well:
<Content><p>TESTTEXT somemoretext</p>
<p> </p>
<?php echo ('PHP!');?></Content>
BUT! When i echoing it through simple XML everything is ok EXCEPT php-code, for some reason it's commented out now!
<!--?php echo ('1');?-->
Just in case if the saving process is important:
$content = htmlspecialchars($_POST['editor1']);//safe string
$rec = $xml->createElement("Content", $content);//saving
$root->appendChild($rec);
Need your masterpiece help guys!!!
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.
I'm using an ajax request to send comments to DB. Succesful response is marked by
1. OK
The problem actually is that the response from the php script is
1.
2. OK
So I debugged the script and noted that the newline character si being added when the script executes the following line:
require_once($ABS_APPS."/quotes/classQuote.php");
After some searches i read that it could be a BOM (Byte Order Mark) problem. So I just downloaded and opened the classQuote.php file with an hex editor and noticed that there's no BOM... can someone help me?
P.S. All files in my project are encoted in UTF-8, and I'm currently usint NetBeans which doesn't add BOM to files.
This is the incriminated script:
// Send new comment to DB
case "send":
$notification = new Notification();
if($comment->insert($_POST["username"], $_POST["comment"], $_POST["app"], $_POST["entryId"])){
switch ($_POST["app"]) {
case "quotes":
require_once($ABS_APPS."/quotes/classQuote.php");
$quote = new Quote();
$quoteData = $quote->get($_POST["entryId"]);
// If user comments his own entry we don't have to send the notification
if($quoteData["UserAuthor"] != $_SESSION["User"]){
$notification->newComment($_POST["username"], $quoteData["UserAuthor"], $_POST["entryId"], $_POST["app"]);
}
break;
default:
break;
}
echo "OK";
} else {
echo "ERROR";
}
break;
Make sure there is nothing, preceeding the opening <?php in your classQuote.php
Make sure there are no trailing characters / lines after the closing ?>
Check to see if a ?> tag exists somewhere in the lines of code (follow flow from your __construct and where you invoke stuff)
Infact, it could prove helpful to leave out the closing tag. Another possibility is this:
// capture output
ob_start();
require_once($ABS_APPS."/quotes/classQuote.php");
$quote = new Quote();
$quoteData = $quote->get($_POST["entryId"]);
// If user comments his own entry we don't have to send the notification
if($quoteData["UserAuthor"] != $_SESSION["User"]){
$notification->newComment($_POST["username"], $quoteData["UserAuthor"], $_POST["entryId"], $_POST["app"]);
// trim whitespace
echo trim(ob_get_clean());
}
If you're using jQuery
you can use jQuery.trim(responseData) in your AJAX success callback, to get rid of the white spaces
see also here
http://api.jquery.com/jQuery.trim/
hope it helps
I also faced the same problem.
The final solution I figured out is following
Check all the files which are loaded into the file to which you are sending AJAX request
Remove the extra white spaces from the very first <? line and PHP starting tag If your file starts from line number 1, the first ever character should be this <?.
If they are PHP files, then don't add ?> at the end.
Try to keep the last line marker only up to the last line of code written. means that do not add extra spaces at the end of the file. If code finishes at line 32, do not go to line number 33 via editor. In fact, press the back button and clear everything below up to line number 32.
If you are using any PHP framework, then make sure that the hierarchy of all files loaded should not have the same problem. e.g. if you are using codeigniter framework them make sure that the calling function's controller and all the models loaded into that controller should not have the same problem.
I fixed by these
Make sure there is nothing, preceeding the opening
Make sure there are no trailing characters / lines after the closing
?>
Check to see if a ?> tag exists somewhere in the lines of code
(follow flow from your __construct and where you invoke stuff)
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.
I'm a PHP virgin (first day), so please type slowly.
I have a number of images, bg_001.jpg, bg_002.jpg, etc., which I want to rotate through each time the page is refreshed. I tried this:
if (isset($_COOKIE["bg1"])) {
$img_no = $_COOKIE["bg1"] + 1;
} else {
$img_no = 1;
}
$filename = 'bg_' . sprintf("%03d", $img_no) . '.jpg';
if (!file_exists("/img/" . $filename)) {
$img_no = 1;
$filename = 'bg_' . sprintf("%03d", $img_no) . '.jpg';
}
setcookie("bg1", $img_no, time() + 86400);
print '<img src="img/' . $filename . '" alt="" height="175" width="800"> ';
Instead of a cookie I get a
Warning: Cannot modify header information - headers already sent by (output
started at /home2/.../about.php:7) in /home2/.../about.php on line 31
Line 31 being the line with the setcookie. I already found pointers about PHP having trouble with Unicode's BOM, but I have no idea how to fix it (if it is the problem here in the first place).
So, to make it official (and avoid a "not a real question" label), how do I fix this? :-)
Constructive criticism on my code is welcome too.
epilogue:
Seemed like a common newbie error: several answers toward the same solution within fifteen minutes. Thanks guyz/galz.
So I moved everything except the print to the start of the file, and indeed: fixed.
cookies can only be sent, if there are no information sent prior. This means that the first thing in your PHP file has to be <?php, and nothing can get before that part (not even the dreaded UTF-8 BOM), because if something is before the first <?php (like <html>), then php will send those data for the browser and after data is sent you can't use setcookie. Refactor your code to look something like this:
<?php
(...)
setcookie(...)
(...)
?>
<HTML>
(...)
</HTML>
And double check that editors like notepad didn't put any UTF-8 BOM signatures before the first <?php in the file.
With HTTP your header (request/response info) and Content (actual textor binary content) are set separately and Header must precede the Content.
Setting a cookie actually adds a command to the header response, so any modifications to the cookie need to happen before you start outputting any content.
Move all your code that references your cookie before the opening html element on your page and you should be ok.
You might also find it easier to use sessions instead of manipulating the cookies themselves. the session_start() still needs to come before any other content but it makes it easier to store data structures, etc.
have a look at http://php.net/session_start
To get around this without major code changes, use Output Buffering like so,--
<?php
ob_start();
// ... my code here
?>
<html></html>
<?php
// ... end of the file
ob_end_flush();
?>
The error/warning you got says it all: headers are already sent
This means that output has been already sent to the browser before the setcookie() method was called.
As you can understand cookies "should be set" before any output is send to the browser.
So check line 7 at about.php. You should have html code there or you might have a call to print or echo.