phphtmldomdocument

PHP DOMDocument replace multiple child with text nodes


I've one sample string as follows :

$feed_status = 'Nice to see you all back again
<img src="http://example.com/file/pic/emoticon/default/smile.png" alt="Smile" title="Smile" title="v_middle" />
<img src="http://example.com/file/pic/emoticon/default/smile.png" alt="Smile" title="Smile" title="v_middle" />
<img src="http://example.com/file/pic/emoticon/default/smile.png" alt="Smile" title="Smile" title="v_middle" />';

For this example I've just added three <img> tags to the string but in real situation this string could contain a zero or more <img> tags.

I want to get names of files present in each of the <img> tag's src attribute and make array of those file names. Then I have to replace these <img> tags by strings from an array titled $emoticon_codes which is created dynamically based on the file name present in <img> tag. This replacement of strings should happen is the same order.

For this I've tried following code. Till the creation of dynamic array titled $emoticon_codes everything works fine but I'm facing with code for replacing the current <img> tags with the strings from the array $emoticon_codes. So can somebody please help me in correcting the mistake I'm making in my code while replacing the <img> tags from the string.

Following is my code :

  $doc = new DOMDocument();
  $doc->loadHTML($feed_status);
  $imageTags = $doc->getElementsByTagName('img');
  
  if(count($imageTags)) {
    $emoticon_codes = array();
    foreach($imageTags as $tag) {
      if (basename($tag->getAttribute('src')) == 'evilgrin.png') {
        array_push($emoticon_codes, '\ue404');
      }
      if (basename($tag->getAttribute('src')) == 'grin.png') {
        array_push($emoticon_codes, '\ue415');
      }
      if (basename($tag->getAttribute('src')) == 'happy.png') {
        array_push($emoticon_codes, '\ue057');
      }
      if (basename($tag->getAttribute('src')) == 'smile.png') {
        array_push($emoticon_codes, '\ue056');
      }
      if (basename($tag->getAttribute('src')) == 'surprised.png') {
        array_push($emoticon_codes, '\ue107');
      }
      if (basename($tag->getAttribute('src')) == 'tongue.png') {
        array_push($emoticon_codes, '\ue105');
      }
      if (basename($tag->getAttribute('src')) == 'unhappy.png') {
        array_push($emoticon_codes, '\ue403');
      }
      if (basename($tag->getAttribute('src')) == 'waii.png') {
        array_push($emoticon_codes, '\ue407');
      }
      if (basename($tag->getAttribute('src')) == 'wink.png') {
        array_push($emoticon_codes, '\ue405');
      }
    }
    /*Till here everything works fine. The array $emoticon_codes is also getting generated finely*/
 
    /*Following is the code giving problem to me,*/
    $t = 0;
    
    foreach($imageTags as $img) {
      $img->parentNode->replaceChild($img, $doc->createTextNode($emoticon_codes[$t]));
      $t++;
      if ($t > count($emoticon_codes)) {
        break;
      }
    }
  }

My desired output string should be like follows after echo $feed_status; :

Nice to see you all back again \ue056 \ue056 \ue056;


Solution

  • If you're trying to change multiple children, you need some regression to make some changes, and I suggest try to map each replacement in an array instead of having multiple if statements. Example:

    $feed_status = "Nice to see you all back again <img src=\"http://52.1.47.143/file/pic/emoticon/default/smile.png\" alt=\"Smile\" title=\"Smile\" title=\"v_middle\" /><img src=\"http://52.1.47.143/file/pic/emoticon/default/smile.png\" alt=\"Smile\" title=\"Smile\" title=\"v_middle\" /><img src=\"http://52.1.47.143/file/pic/emoticon/default/smile.png\" alt=\"Smile\" title=\"Smile\" title=\"v_middle\" />";
    
    $doc = new DOMDocument();
    @$doc->loadHTML($feed_status, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    $imageTags = $doc->getElementsByTagName('img');
    
    $replacements = array(
        'evilgrin.png' => '\ue404',
        'grin.png' => '\ue415',
        'happy.png' => '\ue057',
        'smile.png' => '\ue056',
        'surprised.png' => '\ue107',
        'tongue.png' => '\ue105',
        'unhappy.png' => '\ue403',
        'waii.png' => '\ue407',
        'wink.png' => '\ue405',
    );
    
    // regression 
    $i = $imageTags->length - 1;
    while($i > -1) {
        $tag = $imageTags->item($i);
        $basename = basename($tag->getAttribute('src'));
        if(isset($replacements[$basename])) { // if the file name matches
            // make replacements
            $r = $replacements[$basename];
            $text = $doc->createTextNode($r);
            $tag->parentNode->replaceChild($text, $tag);
        }
        $i--;
    }
    // append to string container again
    $feed_status = '';
    foreach($doc->childNodes->item(0)->childNodes as $e) {
        $feed_status .= $doc->saveHTML($e);
    }
    echo $feed_status;
    

    Sample Output