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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: daverandom@php.net
New email:
PHP Version: OS:

 

 [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: Thu Nov 21 19:01:29 2024 UTC