Append HTML elements by PHP - php

I want to append my head tag with script tag(with some contents) in external Html file using PHP code.
But my Html is not updating or showing any errors.
PHP Code:
<?php
$doc = new DOMDocument();
$doc->loadHtmlFile( 'myfolder/myIndex.html');
$headNode = $doc->getElementsByTagName('head')->item(0);
$scriptNode = $doc->createElement("script");
$headNode->appendChild($scriptNode);
echo $doc->saveXML();
?>
Html File :
(A simple html pattern)
<html>
<head></head>
<body></body>
</html>
I have refered to the documentation here
Couldn't figure out the problem still.

Given a very simple HTML file ( simple.html )
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>A simple HTML Page</title>
</head>
<body>
<h1>Simple HTML</h1>
<p>Well this is nice!</p>
</body>
</html>
Then using the following
$file='simple.html';
libxml_use_internal_errors( true );
$dom=new DOMDocument;
$dom->validateOnParse=false;
$dom->recover=true;
$dom->strictErrorChecking=false;
$dom->loadHTMLFile( $file );
$errors = libxml_get_errors();
libxml_clear_errors();
$script=$dom->createElement('script');
$script->textContent='/* Hello World */';
/* use [] notation rather than ->item(0) */
$dom->getElementsByTagName('head')[0]->appendChild( $script );
printf('<pre>%s</pre>',htmlentities( $dom->saveHTML() ));
/* write changes back to the html file - ie: save */
$dom->saveHTMLFile( $file );
will yield ( for display )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>A simple HTML Page</title>
<script></script></head>
<body>
<h1>Simple HTML</h1>
<p>Well this is nice!</p>
</body>
</html>

Related

How to edit head tag in PHP with DOM with only DOMDocument

Just trying to edit/modify the head tag in order to add something inside with DOM and PHP.
$dom = new DOMDocument();
$dom->loadHtml(utf8_decode($html), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
for($i=0; $i<count($r);$i++)
{
// Prepare the HTML to insert
Here I want to add $var inside head tag (at the end if possible)
}
return $dom->saveHTML();
Everytime I tried, I have LENGHT=0 as the result of var_dump.
Edit: I don't want to edit an existing tag. I want to add a new one. To be more specific, I need to add OG meta tag for Facebook sharing.
Edit2 as requested :
Before
<head>
<meta blabla>
<title></title>
</head>
<body>
<h1></h1>
</body>
After
<head>
<meta blabla>
<title></title>
<meta new1>
</head>
<body>
<h1></h1>
</body>
But need to be edit via DOMDocument in PHP...
Add this to the top of your file:
<?php
$var = "Hello world.";
?>
Then start the HTML and add it there.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= $var ?></title>
</head>
<body>
</body>
</html>
If you want to do it in PHP, you can try to use:
$titles = $domDocument->getElementsByTagName('title');
foreach($titles as $key => $title){
$title->setAttribute('attribute', 'value')
}
Source for the edit: https://stackoverflow.com/a/3195048/12077975
Try something along these lines:
$before=
'<html>
<head>
<meta name="old"/>
<title></title>
</head>
<body>
<h1></h1>
</body>
</html>
';
$HTMLDoc = new DOMDocument();
$HTMLDoc->loadHTML($before, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
$xpath = new DOMXPath($HTMLDoc);
$destination = $xpath->query('//head/title');
$template = $HTMLDoc->createDocumentFragment();
$template->appendXML('<meta name="new"/>');
$destination[0]->parentNode->insertBefore($template, $destination[0]->nextSibling);
echo $HTMLDoc->saveHTML();
Output:
<html>
<head>
<meta name="old">
<title></title><meta name="new">
</head>
<body>
<h1></h1>
</body>
</html

PHP DOMElement::replaceChild produces fatal error

Source HTML (test.html) is:
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>PHP Test</title>
</head>
<body>
<h1>Test page</h1>
<div>
<div id="to-replace-1">Test content 1</div>
</div>
</body>
</html>
PHP to modify this HTML is:
<?php
$str = file_get_contents('test.html');
$doc = new DOMDocument();
#$doc->loadHTML($str);
$div1 = $doc->getElementById('to-replace-1');
echo $div1->nodeValue; // Success - 'Test content 1'
$div1_1 = $doc->createElement('div');
$div1_1->nodeValue = 'Content replaced 1';
$doc->appendChild($div1_1);
$doc->replaceChild($div1_1, $div1);
Doesn't matter - append newly created $div1_1 to $doc or not. The result is the same - last line produces 'PHP Fatal error: Uncaught DOMException: Not Found Error in ...'.
What's wrong?
Your issue is that $doc does not have a child which is $div1. Instead, you need to replace the child of $div1's parent, which you can access via its parentNode property:
$doc = new DOMDocument();
$doc->loadHTML($str, LIBXML_HTML_NODEFDTD);
$div1_1 = $doc->createElement('div');
$div1_1->nodeValue = 'Content replaced 1';
$div1 = $doc->getElementById('to-replace-1');
$div1->parentNode->replaceChild($div1_1, $div1);
echo $doc->saveHTML();
Output:
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>PHP Test</title>
</head>
<body>
<h1>Test page</h1>
<div>
<div>Content replaced 1</div>
</div>
</body>
</html>
Demo on 3v4l.org
Note that you don't need to append $div1_1 to the HTML, replaceChild will do that for you.

codeigniter, view template string to DomDocument operating

I have a php file in application\views\article.php
article.php content:
<!DOCTYPE html>
<html prefix='og: http://ogp.me/ns#'>
<head>
<title>test</title>
</head>
<body>
<div> test div1 </div>
<div> test div2 </div>
</body>
</html>
When I use $this->load->view() to load article.php template and use DomDocument to get dom.
$html=$this->load->view('article','',TRUE);
$doc = new DomDocument;
$doc->loadHTML($html);
echo $doc->saveXML($doc->getElementsByTagName('div')->item(0));
// or echo $doc->saveXML();
have the error message:
Message: DOMDocument::loadHTML(): Unexpected end tag : meta in Entity, line: 4
but whe I use this:
$html='<!DOCTYPE html>
<html prefix=\'og: http://ogp.me/ns#\'>
<head>
<title>test</title>
</head>
<body>
<div> test div1 </div>
<div> test div2 </div>
<p>Directory </p>
</body>
</html>';
$doc->loadHTML($html);
echo $doc->saveXML($doc->getElementsByTagName('div')->item(0));
// or echo $doc->saveXML();
this is success.
gettype($html) to two methods of $html, both are strings.
Try hide the warning with
libxml_use_internal_errors(true);
Or:
#$doc->loadHTML($html);
The warning is because the HTML returned by $this->load->view('article','',TRUE); is invalid, loadHTML() resolve this but show the warnings.
Manual

PHP DOM: drop XML declaration and add doctype

What I want is to drop XML declaration and add <!DOCTYPE html>. Here is a code example:
$html = new DOMDocument();
$html->formatOutput = true;
$htmlNode = $html->createElement("html");
$html->appendChild($htmlNode);
$htmlNode->appendChild($html->createElement("head"));
$bodyNode = $html->createElement("body");
$bodyNode->setAttribute("data-spy", "scroll");
$bodyNode->setAttribute("data-target", "#myAffix");
$htmlNode->appendChild($bodyNode);
$mainNode = $html->createElement("main");
$bodyNode->appendChild($mainNode);
$gridcellNode = $html->createElement("div");
$gridcellNode->setAttribute("class", "grid-cell");
$mainNode->appendChild($gridcellNode);
$containerFluid = $html->createElement("div");
$containerFluid->setAttribute("class","container-fluid");
$gridcellNode->appendChild($containerFluid);
$html->saveHTMLFile("../article.html");
$html->saveHTML();
$html->save("../article2.html");
The first article.html does not contain XML declaration, but is poor formatted (without indent). The second produced article2.html has indent, but also has <?xml version="1.0"?>.
Output in article.html:
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head>
<body data-spy="scroll" data-target="#myAffix"><main><div class="grid-cell"><div class="container-fluid"></div></div></main></body>
</html>
output in article2.html:
<?xml version="1.0"?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body data-spy="scroll" data-target="#myAffix">
<main>
<div class="grid-cell">
<div class="container-fluid"/>
</div>
</main>
</body>
</html>
You can use LIBXML_NOXMLDECL option to drop the XML declaration but this is only available in Libxml >= 2.6.21, i.e.:
$html->save("../article2.html", LIBXML_NOXMLDECL);
If you don't have Libxml >= 2.6.21, your only option (afaik), is:
$output = $html->saveHTML();
$the_file = "../article2.html";
$html->save($the_file);
file_put_contents($the_file, preg_replace('/<\?xml[^>]+>\s+/', '', file_get_contents($the_file)));

saveHTML() not working properly

I have this line of code in my index.php:
<?php include ("header.php"); ?>
</body>
</html>
My header.php:
<!DOCTYPE html>
<html lang="en">
<head>
<?php include("php/dynamic_header.php"); ?>
<meta charset="utf-8">
<meta name="description" content="Write a description" />
<meta name="keywords" content="Your keywords here" />
<title>Random Title</title>
</head>
<body>
<header>This is my header</header>
And my dynamic_header.php:
$dom = new domDocument;
#$dom->loadHTMLFile("header.php");
$meta = $dom->getElementsByTagName('meta')->item(1);
$meta->setAttribute('content','new description');
$dom->saveHTML();
However, when I use saveHTML(), nothing happens.
I tried using:
echo $dom->saveHTML();
But this produces two headers, so can someone explain me what am I doing wrong?
Basically, I'm trying to change attribute on my meta tag with PHP DOM, but I can't save it without duplicating my header.
It should work just as good with saveHTMLFile() which is why I believed something was wrong with your file permissions or so not allowing you to save back the data. Either way, I think you're doing this wrong you should use a template library instead of modifying the data with DOMDocument.
For example with Smarty, you could do a header template like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="{$description|default:"Write a description"}" />
<meta name="keywords" content="Your keywords here" />
<title>{$title|default:"Default Page Title"}</title>
</head>
<body>
Here was the relevant test code to show it would not create duplicates with DOMDocument:
<?php
$str = <<<DATA
<!DOCTYPE html>
<html lang="en">
<head>
<?php include("php/dynamic_header.php"); ?>
<meta charset="utf-8">
<meta name="description" content="Write a description" />
<meta name="keywords" content="Your keywords here" />
<title>Random Title</title>
</head>
<body>
<header>This is my header</header>
DATA;
$dom = new domDocument;
#$dom->loadHTML($str);
$dom->formatOutput = true;
$dom->preserveWhitespace = false;
$meta = $dom->getElementsByTagName('meta')->item(1);
$meta->setAttribute('content','new description');
echo $dom->saveHTML();

Categories