I'm trying to write a droid app that sends and receives XML between the app and a web service. When I try to run the following code
$dom = new domDocument;
$dom = simplexml_load_file('php://input');
$xml = simplexml_import_dom($dom);
$messages = Messages::find_by_sql("SELECT * FROM messages WHERE reciever = '$xml->userName'");
$xmlString = "";
if($messages)
{
foreach($messages as $message)
{
$ts = strtotime($message->ts);
$xmlString=$xmlString."<Message><sender>".$message->sender."</sender><reciever>".$message->reciever."</reciever><timestamp>"."123"."</timestamp><text>".$message->text."</text></Message>";
}
}
else
{
//do something
}
$xmlReturn = new DOMDocument('1.0', 'UTF-8');
$xmlReturn->loadXML($xmlString);
echo($xmlReturn->saveXML());
?>
I get a Warning Extra content at the end of the document.
The error comes from this line: $xmlReturn->loadXML($xmlString);
I'm not 100% sure that you can create an xml document by loading a string, but I've seen similar things done and if you look here you can see what it ouputs, which looks like valid XML to me.
An XML document can have only one root element. You are stringing together multiple <message>…</message> combinations here, so a root element encapsulating those is missing.
Related
I am using PHP DOM Xpath to read XML files. In some cases tags are not properly closed like below
<data>
<name> value </name>
<address
I have following code to check if XML is valid
$doc = new DOMDocument();
if(!$doc->load(test.xml))
{
foreach (libxml_get_errors() as $error)
{
print_r($error);
}
libxml_clear_errors();
}
else
{
$valid_xml = 'y';
}
if($valid_xml=='y')
// then process XML
else
// skip and take next file
but I am getting below errors at line if(!$doc->load(test.xml))
Message: DOMDocument::load(): Couldn't find end of Start Tag AdjustmentsToReconcile
Message: DOMDocument::load(): Premature end of data in tag
You were almost there. Try adding the command libxml_use_internal_errors(true); before everything to tell PHP not to throw errors but to cache them for you to iterate through as your code is doing.
That should helps you:
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$valid_xml = true;
if(!$doc->load(test.xml))
{
$valid_xml = (count(libxml_get_errors()) === 0);
libxml_clear_errors();
}
if($valid_xml)
// then process XML
else
// skip and take next file
libxml_use_internal_errors is the key.
I am getting data from a website using DOM. I've tested my code in my local server and it works perfectly however, when I uploaded it on a server and ran the code, the script I created returned html tags without any content. My code looks something like this:
$divs = $dom->getElementsByTagName('div');
foreach($divs as $div){
if($div->getAttribute('class') == "content1"){
$dom = new DOMDocument();
$dom->appendChild($dom->importNode($div, true));
$content1 = $dom->saveHTML();
echo "content:".$content1;
}
}
In my localhost, it returns something like so:
<div class="content1">This is my content</div>
However, in the server, I strangely get the empty html tags like so:
<div class="content1"></div>
What are possible causes of this problem? Is there any way I can fix it? Please advise.
PHP version under 5.3.6 :
create a variable that will contains a clone of the current node with all sub nodes,
append it as a child
echo the returned value.
foreach($divs as $div) {
if($div->getAttribute('class') == "content1"){
$dom = new DOMDocument();
$cloned = $div->cloneNode(TRUE);
$dom->appendChild($dom->importNode($cloned,TRUE));
$content1 = $dom->saveHTML();
echo "content:".$content1;
}
}
EDIT: I've made a mistake it was not
$cloned = $element->cloneNode(TRUE);
but
$cloned = $div->cloneNode(TRUE);
sorry ^^ (hope it will work)
I am trying to extract a specific clump of HTML using dom document.
My code is as follows:
$domd = new DOMDocument('1.0', 'utf-8');
$domd->loadHTML($string);
$this->hook = 'content';
if($this->hook !== '') {
$main = $domd->getElementById($this->hook);
$newstr = "";
foreach($main->childNodes as $node) {
$newstr .= $domd->saveXML($node, LIBXML_NOEMPTYTAG);
}
$domd->loadHTML($newstr);
}
//MORE PARSING USING THE DOMD OBJECT
It works great BUT the foreach is quite slow, and I was wondering if there's a more intelligent way of doing this. I am re-loading the HTML into the $domd so I can keep editing. In the back of my mind I feel I should be saving a fragment, not re-loading the saved $newstr into the object.
Can this be made more elegant or faster?
Thanks!
I'm assuming you want to mutate your existing $domd document, replacing it completely with those child nodes you're grabbing from that content node:
UPDATE: Just realized that since you were reloading using loadHTML, you probably wanted to preserve the html/body nodes that it creates. Code below has been adjusted to empty body and append the fragment there:
$domd = new DOMDocument('1.0', 'utf-8');
$domd->loadHTML($string);
$this->hook = 'content';
if($this->hook !== '') {
$main = $domd->getElementById($this->hook);
$fragment = $domd->createDocumentFragment();
while($main->hasChildNodes()) {
$fragment->appendChild($main->firstChild);
}
$body = $domd->getElementsByTagName("body")->item(0);
while($body->hasChildNodes()) {
$body->removeChild($body->firstChild);
}
$body->appendChild($fragment);
}
//MORE PARSING USING THE DOMD OBJECT
I'm having trouble trying to write an if statement for the DOM that will check if $html is blank. However, whenever the HTML page does end up blank, it just removes everything that would be below DOM (including what I had to check if it was blank).
$html = file_get_contents("http://example.com/");
$dom = new DOMDocument;
#$dom->loadHTML($html);
$links = $dom->getElementById('dividhere')->getElementsByTagName('img');
foreach ($links as $link)
{
echo $link->getAttribute('src');
}
All this does is grab an image URL in the specified div, which works perfectly until the page is a blank HTML page.
I've tried using SimpleHTMLDOM, which didn't work either (it didn't even fetch the image on working pages). Did I happen to miss something with this one or am I just missing something in both?
include_once('simple_html_dom.php')
$html = file_get_html("http://example.com/");
foreach($html->find('div[id="dividhere"]') as $div)
{
if(empty($div->src))
{
continue;
}
echo $div->src;
}
Get rid on the $html variable and just load the file into $dom by doing #$dom->loadHTMLFile("http://example.com/");, then have an if statement below that to check if $dom is empty.
I am trying to replace the html code inside the div 'resultsContainer' with the html of $response.
The result of my unsuccessful code is that the contents of 'resultsContainer' remain and the html of $response shows up on screen as text rather than being parsed as html.
Finally, I would like to inject the content of $response inside 'resultContainer' without having to create any new div, I need this: <div id='resultsContainer'>Html inside $response here...</div> and NOT THIS: <div id='resultsContainer'><div>Html inside $response here...</div></div>
// Set Config
libxml_use_internal_errors(true);
$doc = new DomDocument();
$doc->strictErrorChecking = false;
$doc->validateOnParse = true;
// load the html page
$app = file_get_contents('index.php');
$doc->loadHTML($app);
// get the dynamic content
$response = file_get_contents('search.php'.$query);
$response = utf8_decode($response);
// add dynamic content to corresponding div
$node = $doc->createElement('div', $response);
$doc->getElementById('resultsContainer')->appendChild($node);
// echo html snapshot
echo $doc->saveHTML();
if $reponse is plain text:
// add dynamic content to corresponding div
$node = $doc->createTextNode($response);
$doc->getElementById('resultsContainer')->appendChild($node);
if it (can) contain html (one could use createDocumentFragment but that creates its own set of trouble with entities, dtd, etc.):
// add dynamic content to corresponding div
$frag = new DomDocument();
$frag->strictErrorChecking = false;
$frag->validateOnParse = true;
$frag->loadHTML($response);
$target = $doc->getElementById('resultsContainer');
if(isset($target->childNodes) && $target->childNodes->length)){
for($i = $target->childNodes->length -1; $i >= 0;$i--){
$target->removeChild($target->childNodes->item($i));
}
}
//if there's lots of content in $target, you might try this:
//$target->parentNode->replaceChild($target->cloneNode(false),$target);
foreach($frag->getElementsByTagName('body')->item(0)->childNodes as $node){
$target->appendChild($doc->importNode($node,true));
}
Which goes to show it really isn't that suited (or at least cumbersome) to use DOMDocuments as a templating engine.