php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67948 DOMDocument::saveHTML() should accept a DOMNodeList for the $node argument
Submitted: 2014-09-02 12:48 UTC Modified: 2021-10-11 15:50 UTC
From: daverandom@php.net Assigned:
Status: Open Package: DOM XML related
PHP Version: Irrelevant OS: Any
Private report: No CVE-ID: None
 [2014-09-02 12:48 UTC] daverandom@php.net
Description:
------------
A common usage of DOM is a pattern roughly like this:

// A HTML fragment as a string, probably loaded from external source
$html = <<<HTML
  <div>
    <span>Some random data</span>
  </div>
HTML;

$doc = new DOMDocument;
$doc->loadHTML($html);
// manipulate the data
$data = $doc->saveHTML();

By default, libxml will wrap this fragment in <html><body> tags, meaning that saveHTML() exports a whole document and not just a fragment, which is not likely to be the desired result.

While it is possible to avoid this when loading the document using the LIBXML_HTML_NOIMPLIED flag, it's often desirable to accept a DOMDocument as an argument to a routine that does not know whether this flag was used or not.

It is possible to pass a node to the saveHTML() routine (e.g. the <body> element) but this exports the container node as well as it's children. as a result, people often write code which strips this outer element from the fragment using string manipulation, which is error-prone and less than ideal.

A good way to make this situation easier to handle would be if saveHTML() could also accept a DOMNodeList, which would mean that *only* the children of an arbitrary element would be easy to export, using `$node->childNodes`.

This would also potentially have uses with XPath results.

Test script:
---------------
<?php

$html = <<<HTML
  <div>
    <span>Some random data</span>
  </div>
HTML;

$doc = new DOMDocument;
$doc->loadHTML($html);
$body = $doc->getElementsByTagName('body')[0];
$body->appendChild($doc->createElement('span', 'more data'));

$data = $doc->saveHTML($body->childNodes);
echo $data;

Expected result:
----------------
  <div>
    <span>Some random data</span>
    <span>more data</span>
  </div>



Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-09-02 14:22 UTC] thomas at weinert dot info
> This would also potentially have uses with XPath results.

Yes, this would be useful for XPath.

But DOMDocument::saveXml() should get the same functionality. 

(DOMDocument::createDocumentFragment() allows to import a fragment. This would allow to export one.)
 [2021-10-11 15:50 UTC] cmb@php.net
A working userland alternative is to append all child nodes to a
new DOMDocumentFragment, and to export that:

<?php

$html = <<<HTML
  <div>
    <span>Some random data</span>
  </div>
HTML;

$doc = new DOMDocument;
$doc->loadHTML($html);
$body = $doc->getElementsByTagName('body')[0];
$body->appendChild($doc->createElement('span', 'more data'));

$frag = $doc->createDocumentFragment();
foreach ($body->childNodes as $node) {
    $frag->appendChild($node);
}

$data = $doc->saveHTML($frag);
echo $data;
?>
 [2023-04-22 07:30 UTC] buzysreports at gmail dot com
Buzyrepoters are sharing latest news about Business, Finance, Education, Entertainment, Gaming, Mobile, tech, Realstate etc. More info to visit: (https://buzyrepoters.com)github.com
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 15 01:01:36 2024 UTC