1

I am attempting to create a new, stripped-down DOM however I cannot find a way to take a the HTML string returned from DOMDocument::saveHTML() and insert that into a new DOMDocument.

I want to take $courseHTML and append it to the <body> node.

Is that possible, or is my approach sub-optimal?

// grab the original DOM
$doc = new DOMDocument();
$doc->loadHTML($content, LIBXML_HTML_NOIMPLIED);
$body = $doc->getElementsByTagName('body');

// create a new DOM just for the <body> content
$mock = new DOMDocument();
foreach ($body->item(0)->childNodes as $child) {
   $mock->appendChild($mock->importNode($child, true));
}

$courseHTML = $mock->saveHTML();

// create a new, stripped-down DOM
$doc = new DOMDocument();
$html = $doc->appendChild($doc->createElement('html'));
$head = $html->appendChild($doc->createElement('head'));

$node = $head->appendChild($doc->createElement('meta'));
$node->setAttribute('charset', 'utf-8');

$node = $head->appendChild($doc->createElement('meta'));
$node->setAttribute('name', 'viewport');
$node->setAttribute('content', 'width=device-width, initial-scale=1');

$style = $head->appendChild($doc->createElement('style'));
$style->setAttribute('type', 'text/css');

$rangersCSS = $doc->createTextNode('@import url("https://crmpicco.co.uk/grfc1872.css");');
$style->appendChild($rangersCSS);

$body = $html->appendChild($doc->createElement('body'));
$body->setAttribute('id', 'crmpicco_course');

$doc->formatOutput = true;

$content = '<!DOCTYPE html>';
$content .= $doc->saveHTML();

Also, is there a cleaner way to add the DOCTYPE to the DOM other than string concatenation?

1 Answer 1

2

Inserting an arbitrary piece of HTML string can be done by creating a DOMDocumentFragment from the HTML. Note this only works if the HTML is well-formed XML as well.

Creating a document with a doctype declaration can be done by constructing the DOMDocument object with a DOMImplementation.

For example:

<?php
$myhtml = '<p>Here is some <abbr title="hypertext markup language">HTML</abbr></p>';

$doc = (new DOMImplementation)->createDocument(
    null,
    "html",
    (new DOMImplementation)->createDocumentType("html")
);

// html element is already created
$html = $doc->getElementsByTagName('html')[0];
$head = $html->appendChild($doc->createElement('head'));

$node = $head->appendChild($doc->createElement('meta'));
$node->setAttribute('charset', 'utf-8');

$node = $head->appendChild($doc->createElement('meta'));
$node->setAttribute('name', 'viewport');
$node->setAttribute('content', 'width=device-width, initial-scale=1');

$style = $head->appendChild($doc->createElement('style'));
$style->setAttribute('type', 'text/css');

$rangersCSS = $doc->createTextNode('@import url("https://crmpicco.co.uk/grfc1872.css");');
$style->appendChild($rangersCSS);

$body = $html->appendChild($doc->createElement('body'));
$body->setAttribute('id', 'crmpicco_course');

// can't just use new DOMDocumentFragment for some reason
$fragment = $doc->createDocumentFragment();
$fragment->appendXML($myhtml);
$body->appendChild($fragment);

$doc->formatOutput = true;

echo $doc->saveHTML();

Output:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">@import url("https://crmpicco.co.uk/grfc1872.css");</style>
</head>
<body id="crmpicco_course"><p>Here is some <abbr title="hypertext markup language">HTML</abbr></p></body>
</html>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.