phpdompreg-replacedomdocumentdom-node

DOMElement replace HTML value


I have this HTML string in a DOMElement:

<h1>Home</h1>
test{{test}}

I want to replace this content in a way that only

<h1>Home</h1>
test

remains (so I want to remove the {{test}}).

At this moment, my code looks like this:

$node->nodeValue = preg_replace(
    '/(?<replaceable>{{([a-z0-9_]+)}})/mi', '' , $node->nodeValue);

This doesn't work because nodeValue doesn't contain the HTML value of the node. I can't figure out how to get the HTML string of the node other than using $node->C14N(), but by using C14N I can't replace the content. Any ideas how I can remove the {{test}} in an HTML string like this?


Solution

  • Have you tried the DOMDocument::saveXML function? (http://php.net/manual/en/domdocument.savexml.php)

    It has a second argument $node with which you can specify which node to print the HTML/XML of.

    So, for example:

    <?php
    
    $doc = new DOMDocument('1.0');
    // we want a nice output
    $doc->formatOutput = true;
    
    $root = $doc->createElement('body');
    $root = $doc->appendChild($root);
    
    $title = $doc->createElement('h1', 'Home');
    $root->appendChild($title);
    
    $text = $doc->createTextNode('test{{test}}');
    $text = $root->appendChild($text);
    
    echo $doc->saveXML($root);
    
    ?>
    

    This will give you:

    <body>
      <h1>Home</h1>
      test{{test}}
    </body>
    

    If you do not want the <body> tag, you could cycle through all of its childnodes:

    <?php
    
    foreach($root->childNodes as $child){    
        echo $doc->saveXML($child);
    }
    
    ?>
    

    This will give you:

    <h1>Home</h1>test{{test}}
    

    Edit: you can then of course replace {{test}} by the regex that you are already using:

    <?php
    
    $xml = '';
    foreach($root->childNodes as $child){    
        $xml .= preg_replace(
                    '/(?<replaceable>{{([a-z0-9_]+)}})/mi', '', 
                    $doc->saveXML($child)
        );
    }
    
    ?>
    

    This will give you:

    <h1>Home</h1>test
    

    Note: I haven't tested the code, but this should give you the general idea.