SPQRInc
SPQRInc

Reputation: 188

Use DOMDocument to replace text with href link

I tried to use this to solve a problem: I would like to replace a text with a text link this way.

But if I use this source code:

$dom = new DOMDocument;
$dom->loadHTML($html_content);

function preg_replace_dom($regex, $replacement, DOMNode $dom, array $excludeParents = array()) {
  if (!empty($dom->childNodes)) {
    foreach ($dom->childNodes as $node) {
      if ($node instanceof DOMText && 
          !in_array($node->parentNode->nodeName, $excludeParents)) 
      {
        $node->nodeValue = preg_replace($regex, $replacement, $node->nodeValue);
      } 
      else
      {
        preg_replace_dom($regex, $replacement, $node, $excludeParents);
      }
    }
  }
}

preg_replace_dom('/match this text/i', "<a href='http://test.de'>test</a>", $dom->documentElement, array('a'));

The text gets replaced, but <a href='http://test.de>test</a> is printed as plain text, not as link.

How can I solve this?

Upvotes: 1

Views: 961

Answers (2)

Dan Hastings
Dan Hastings

Reputation: 3280

This isnt as clean as I would have liked it to be but I got it working. I know this is an old question now but the answer is still relevant. You will need to pass the dom document into the method as you have to create a new HTML node to replace the old one. You cant just replace the text with HTML you have to replace the HTML node with a new HTML node. Would love to hear any suggestions on how this could be improved upon

private function _preg_replace_dom($regex, $domDocument, $replacement, DOMNode $dom, array $excludeParents = array()) {
        
        if (!empty($dom->childNodes)) {
            $replacementNodes = array();
            foreach ($dom->childNodes as $node) {
                if ($node instanceof DOMText && !in_array($node->parentNode->nodeName, $excludeParents)) 
                {
                    //$node->nodeValue = preg_replace($regex, $replacement, $node->nodeValue);
                    $replacementHtml = preg_replace($regex, $replacement, $node->nodeValue);                        
                    
                    $linkReplacement = $domDocument->createDocumentFragment();
                    $linkReplacement->appendXML($replacementHtml);
                    
                    $tmpreplacement = new stdClass();
                    $tmpreplacement->oldNode = $node;
                    $tmpreplacement->newNode = $linkReplacement;
                    $replacementNodes[] = $tmpreplacement;
                } 
                else
                {
                    $this->_preg_replace_dom($regex, $domDocument, $replacement, $node, $excludeParents);
                }
            }
            
            foreach($replacementNodes as $replacement)
            {
                $dom->replaceChild($replacement->newNode, $replacement->oldNode);
            }
        }
    }   

Upvotes: 0

Nirav Madariya
Nirav Madariya

Reputation: 1508

As I can see a ' is misplaced,

<a href='http://test.de>test</a>'

This is not something you should want, replace it with this,

<a href='http://test.de'>test</a>

As I've seen this Link, you may use preg_replace() instead of preg_replace_dom() at your last line of code.

Hope this helps.

Upvotes: 1

Related Questions