I am presented with an HTML document similar to this in view source mode (the below is simplified for brevity):
I was about to post an answer on your next question but Casimir closed it before I got the chance. I am coming back here to post a proper html parse-then-replace technique for the benefit of researchers and you.
Code: (Demo)
define('LOOKUP', [
'block' => [
'welcome-intro' => 'custom intro'
],
'variable' => [
'contact-email-address' => 'mmu@mmu.com',
'system_version' => 'sys ver',
'system_name' => 'sys name',
'system_login' => 'sys login',
'activate_url' => 'some url'
],
]);
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($html);
$xpath = new DOMXpath($dom);
foreach ($xpath->query("//*[not(self::textarea or self::select or self::input) and contains(., '{{{')]/text()") as $node) {
$node->nodeValue = preg_replace_callback('~{{{([^:]+):([^}]+)}}}~', function($m) {
return LOOKUP[$m[1]][$m[2]] ?? '**unknown variable**';
},
$node->nodeValue);
}
echo $dom->saveHTML();
Output:
Test
custom intro
You are using system version: sys ver
Your address: mmu@mmu.com
There aren't too many tricks involved.
Parse the HTML with DOMDocument and write a filtering query with XPath which requires nodes to not be textarea|select|input tags and they must contain {{{
in their text. There will be several "magical" ways to filter the dom -- this is just one way that feels efficient/direct to me.
I use preg_replace_callback()
to perform replacements based on a lookup array.
To avoid use()
in the callback syntax, I make the lookup available inside the callback's scope by declaring it as a constant (I can't imagine you need it to be a variable anyhow).
I found during testing that DOMDocument didn't like the tags, so I silenced the complaints with
libxml_use_internal_errors(true);
.