Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent html entities with PHP a DOMDocument::saveHTML()?

Due to custom storage needs (the "why" is not important here, thanks!) I have to save html <a> links in a specific format such as this:

myDOMNode->setAttribute("href", "{{{123456}}}");

Everything works fine until i call saveHTML() on the containing DOMDocument. This kills it, since it encodes { in %7B.

This is a legacy application where href="{{{123456}}}" works as a placeholder. The command-line parser look for this pattern exactly (unencoded) and cannot be changed.

I've no choice but to do it this way.

I cannot htmldecode() the result.

This HTML will never be displayed as this, it is just a storage need.

Thanks for your help!

Note: I've looked around for 2 hours but none of the proposed solution worked for me. For those who will blindly mark the question as duplicate: please comment and let me know.

like image 202
Dr. Gianluigi Zane Zanettini Avatar asked Oct 30 '25 13:10

Dr. Gianluigi Zane Zanettini


1 Answers

As the legacy code is using {{{...}}} as a placeholder, it may be safe to use a somewhat hackish approach with preg_replace_callback. The following will restore the URL encoded placeholders once the HTML is generated:

$src = <<<EOS
<html>
    <body>
        <a href="foo">Bar</a>
   </body>
</html>
EOS;

// Create DOM document
$dom = new DOMDocument();
$dom->loadHTML($src);

// Alter `href` attribute of anchor
$a = $dom->getElementsByTagName('a')
    ->item(0)
    ->setAttribute('href', '{{{123456}}}');

// Callback function to URL decode match
$urldecode = function ($matches) {
    return urldecode($matches[0]);
};

// Turn DOMDocument into HTML string, then restore/urldecode placeholders 
$html = preg_replace_callback(
    '/' . urlencode('{{{') . '\d+' . urlencode('}}}') . '/',
    $urldecode,
    $dom->saveHTML()
);

echo $html, PHP_EOL;

Output (indented for clarity):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
    <body>
        <a href="{{{123456}}}">Bar</a>
    </body>
</html>
like image 100
mhall Avatar answered Nov 02 '25 04:11

mhall



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!