PHP Dom problem, how to insert html code in a particular div - php

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.

Related

How to add child element to head tag using DOMDocument

I am trying to arrange document by collecting distributed <style> tag into one and delete all of them then add the new one into head, and i have written this snippet, but missing to how to add the new style tag into header
ob_start('ob_postprocess');
// ob_postprocess is our custom post processing function
function ob_postprocess($buffer){
$d = new DOMDocument('1.0','UTF-8');
$d->loadHTML($buffer);
$x = new DOMXPath($d);
$t = $x->evaluate("//text()");
$cc = array();
foreach($d->getElementsByTagName('style') as $style){
$cc[]= $style->nodeValue;
$style->parentNode->removeChild($style);
}
foreach($d->getElementsByTagName('head') as $head){
//add new style tag
}
$buffer = $d->saveHTML($d);
return $buffer;
}

PHP DOM functuon to creat Div ID from HTML5 Elements

I am using the following function to replace HTML5 elements with Div ID.
<?php function nonHTML5 ($content){
$dom = new DOMDocument;
// Hide HTML5 element errors
libxml_use_internal_errors(true);
$dom->loadHTML($content);
libxml_clear_errors();
$xp = new DOMXPath($dom);
// Bring elements into array
$elements = $xp->query('//*[self::header| self::footer ]
[not(ancestor::pre) and not(ancestor::code)]');
// Loop through
foreach($elements as $element){
// Replace with 'div' tag
$newElement = $dom->createElement('div');
while($element->childNodes->length){
// Keepup with the child nodes
$childElement = $element->childNodes->item(0);
$newElement->appendChild($dom->importNode($childElement, true));
}
while($element->attributes->length){
// Mailtain the length
$attributeNode = $element->attributes->item(0);
$newElement->setAttributeNode($dom->importNode($attributeNode));
}
$element->parentNode->replaceChild($newElement, $element);
}
$content = $dom->saveXML($dom->documentElement);
return $content;
} ?>
I know we can use HTMLShiv but I want to do this primarily for Old browsers with JavaScript disabled.
My Challenge:
I am not able to add an id =" " to it. For example.....
<header>
<h1>I am the header</h1>
</header>
Should become
<div id ="header">
<h1>I am the header</h1>
</div>
I tried doing......
$newElement = $dom->createElement('div id ="' . $element . '"');
but did not work.
My question
What should be the correct code?
Please Note: I am not a PHP expert hence please be a little descriptive in your answers / comments.
Here is how you can do it:
NOTE : I have added comments for more clarification that what is happening in exactly each statement of the code.
CREATING AN HTML ELEMENT WITH ATTRIBUTE USING DOM :
<?php
// Initiate a new DOMDocument
$dom = new DOMDocument();
// Create an element
$div = $dom->createElement("div","HERE DIV CONTENTS");
// Create an attribute i.e id
$divAttr = $dom->createAttribute('id');
// Assign value to your attribute i.e id="value"
$divAttr->value = 'This is an id';
// Add your attribute (id) to your element (div)
$div->appendChild($divAttr);
// Add your element (div) to DOM
$dom->appendChild($div);
// Print your DOM HERE
echo $dom->saveHTML();
?>
CODE OUTPUT :
<div id="This is an id">HERE DIV CONTENTS</div>

DOMDocument->saveHTML isn't working

An api returns me couple of html code (only part of the body, not full html) and i want to change all images src's with others.
I get and set attributes then if i echo it in foreach loop i see old and new value but when i try to save it with saveHTML then dump the full html block which is returned from api, i don't see replaced paths.
$page = json_decode($page);
$page = (array) $page->rows;
$page = ($page[0]->_->content);
$dom = new \DOMDocument();
$dom->loadHTML($page);
$tag = $dom->getElementsByTagName('img');
foreach($tag as $t)
{
echo $t->getAttribute('src').'<br'>; //showing old src
$t->setAttribute('src', 'bla');
echo $t->getAttribute('src').'<br'>; //showing new src
}
$dom->saveHTML();
var_dump($page); //nothing is changed
My_ friend this is not how it works.
You should have your edited HTML in the result of saveHTML() so:
$editedHtml = $dom->saveHTML()
var_dump($editedHtml);
Now you should see your changed HTML.
Explanation is that $page is completely different object that has nothing to do with $dom object.
Cheers!

Dom Document - extract a document id & save

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

Fetching image using xpath or some other way

I need to fetch the image from a remote page, i tried xpath but i was told it wont work because img does not have nodevalue
Then i was advised to use getAttribute, but i dont know how to get it working.
Any suggestions?
This is my code
<?php
libxml_use_internal_errors(true);
//Setting content type to xml!
header('Content-type: application/xml');
//POST Field name is bWV0aG9k
$url_prefix = $_GET['bWV0aG9k'];
$url_http_request_encode = strpos($url_prefix, "http://");
//Checking to see if url has a http prefix
if($url_http_request_encode === false){
//does not have, add it!
$fetchable_url_link_consistancy_remote_data = "http://".$url_prefix;
}
else
//has it, do nothing
{
$fetchable_url_link_consistancy_remote_data = $url_prefix;
}
//Creating a new DOM Document on top of pre-existing one
$page = new DOMDocument();
//Loading the requested file
$page->loadHTMLFile($fetchable_url_link_consistancy_remote_data);
//Initliazing xpath
$xpath = new DOMXPath($page);
//Search parameters
//Searching for title attribute
$query = "//title";
//Searching for paragraph attribute
$query1 = "//p";
//Searching for thumbnails
$query2 = "//img";
//Binding the attributes to xpath for later use
$title = $xpath->query($query);
$paragraph = $xpath->query($query1);
$images = $xpath->query($query2);
echo "<remotedata>";
//Echoing the attributes
echo "<title-render>".$title->item(0)->nodeValue."</title-render>";
echo "<paragraph>".$paragraph->item(0)->nodeValue."</paragraph>";
echo "<image_link>".$images->item(0)->nodeValue."</image_link>";
echo "</remotedata>";
?>
you should get source attribute of an image tag.
$images->item(0)->getAttribute('src');
if this is normal xhtml, img has no value, you need the value of img/#src

Categories