MW

Close HTML Tags

If you cut a html-formatted string at some random position (e.g. with my truncate() function) you might mess up the html. To circumvent that, this function will close all open tags at the end of the string:

The original function was written by connum at DONOTSPAMME dot googlemail dot com

    /**
     * close all open xhtml tags at the end of the string
     *
     * @param string $html
     * @return string
     * @author Milian Wolff <mail@milianw.de>
     */
    function closetags($html) {
      #put all opened tags into an array
      preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
      $openedtags = $result[1];
     
      #put all closed tags into an array
      preg_match_all('#</([a-z]+)>#iU', $html, $result);
      $closedtags = $result[1];
      $len_opened = count($openedtags);
      # all tags are closed
      if (count($closedtags) == $len_opened) {
        return $html;
      }
      $openedtags = array_reverse($openedtags);
      # close tags
      for ($i=0; $i < $len_opened; $i++) {
        if (!in_array($openedtags[$i], $closedtags)){
          $html .= '</'.$openedtags[$i].'>';
        } else {
          unset($closedtags[array_search($openedtags[$i], $closedtags)]);
        }
      }
      return $html;
    }

Comments

Want to comment? Send me an email!

Comment by Volo Kulpa (not verified) (2011-03-18 14:11:00)
    Hi, thanks all for comments
    Here are some my fixes:
    * in_array is case sensitive so convert opened tag to lower case
    * checking if next_tag exists to prevent offset error

geshi:code| # close tags for ($i=0; $i < $len_opened; $i++) { $openedtags[$i] = strtolower($openedtags[$i]); if (!in_array($openedtags[$i],$arr_single_tags)) { if (!in_array($openedtags[$i], $closedtags)) { $next_tag = (($i + 1) < count($openedtags) ? strtolower($openedtags[$i+1]) : null); if ($next_tag && !in_array($next_tag, $arr_single_tags)) { $html = preg_replace('#</'.$next_tag.'#iU','</'.$openedtags[$i].'></'.$next_tag,$html); } else { $html .= '</'.$openedtags[$i].'>'; } } } } |code

Comment by San Andreas Multiplayer (not verified) (2012-11-19 01:03:00)

Ich denke, falls alle Schreiber und Blogger so einen super Inhalt wie du in das Blog stellen würden, gaebe es so viel mehr Sinnvolles zu finden.

Comment by Plasmodino (not verified) (2011-01-05 23:25:00)

A small fix: I tried to ignore closing tags which do not have an opening tag, but it does not work the way I did it. The following code only works if the html syntax in the truncated string is correct:

          static function closeTags($html) {
           preg_match_all("/<\/?(\w+)((\s+(\w|\w[\w-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/i",$html,$result);
         $tags = &$result[0]; $closeCnt = 0;
            for ($i=count($tags)-1;$i>=0;$i--) {
                if ($tags[$i]{strlen($tags[$i])-2}!='/') {
                   if ($tags[$i]{1}!='/') {
                     if (!$closeCnt) $html .= '</'.$result[1][$i].'>'; else $closeCnt--;
                  } else $closeCnt++;
                }
          }
          return $html;
      }
Comment by Plasmodino (not verified) (2011-01-05 22:47:00)

I suggest the following code for closing open tags:

        static function closeTags($html) {
         preg_match_all("/<\/?(\w+)((\s+(\w|\w[\w-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/i",$html,$result);
         $tags = &$result[0]; $closeCnt = 0;
            for ($i=count($tags)-1;$i>=0;$i--) {
                if ($tags[$i]{strlen($tags[$i])-2}!='/') {
                   if ($tags[$i]{1}!='/') {
                     if (!$closeCnt) $html .= '</'.$result[1][$i].'>'; else $closeCnt--;
                  } elseif ($i>0&&$result[1][$i]==$result[1][$i-1]) $closeCnt++;
              }
          }
          return $html;
      }

I did not test it much, though.

Comment by Plasmodino (not verified) (2011-01-05 22:29:00)

I suggest the following code for closing open tags:

    static function closeTags($html) {
     preg_match_all("/<\/?(\w+)((\s+(\w|\w[\w-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/i",$html,$result);
         $tags = &$result[0]; $closeCnt = 0;
            for ($i=count($tags)-1;$i>=0;$i--) {
                if ($tags[$i]{strlen($tags[$i])-2}!='/') {
                   if ($tags[$i]{1}!='/') {
                     if (!$closeCnt) $html .= '</'.$result[1][$i].'>'; else $closeCnt--;
                  } elseif ($i>0&&$result[1][$i]==$result[1][$i-1]) $closeCnt++;
              }
          }
          return $html;
      }

I did not test it much yet, though.

Comment by Anonymous (not verified) (2010-10-19 18:49:00)

This code (including all following postings) has still a lot of problems. For example, it can not close that - the 2nd span will not be closed. fjlfsdlkf 123

Comment by Anonymous (not verified) (2010-09-24 12:37:00)

Little modified for closing all the opened tags

Like incase if we have “rrrrr dddd dddddd ssss”

Output would be : rrrrr dddd dddddd ssss</i>

        /**
     * closetags
     * used to close html tags incase not closed properly
     * @param string $html - html string
     * @access public
    */
    function closetags($html){
        $arr_single_tags = array('meta','img','br','link','area');
        preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])\s*>#iU', $html, $result);
        $openedtags = $result[1];
        preg_match_all('#</([a-z]+)>#iU', $html, $result);
        $closedtags = $result[1];
        $len_opened = count($openedtags);
        if (count($closedtags) == $len_opened){
            return $html;
        }
        $openedtags = array_reverse($openedtags);
        //re arrange open tags and closed tags for count 
        $aOpenedtagsCnt=Array();
        $aClosedtagsCnt=Array();
        if(is_array($openedtags)){
            foreach($openedtags as $iK =>$sTag){
                if(!isset($aOpenedtagsCnt[$sTag])){
                    $aOpenedtagsCnt[$sTag]=1;
                }else{
                    $aOpenedtagsCnt[$sTag]++;
                }
            }
        }
        if(is_array($closedtags)){
            foreach($closedtags as $iK =>$sTag){
                if(!isset($aClosedtagsCnt[$sTag])){
                    $aClosedtagsCnt[$sTag]=1;
                }else{
                    $aClosedtagsCnt[$sTag]++;
                }
            }
        }
        for ($i=0; $i < $len_opened; $i++){
            if (!in_array($openedtags[$i],$arr_single_tags)){
                if ($aOpenedtagsCnt[$openedtags[$i]]!=$aClosedtagsCnt[$openedtags[$i]]){
                    $html .= '</'.$openedtags[$i].'>';
                    if(!isset($aClosedtagsCnt[$openedtags[$i]])){
                        $aClosedtagsCnt[$openedtags[$i]]=1;
                    }else{
                        $aClosedtagsCnt[$openedtags[$i]]++;
                    }
                }
            }
        }
        return $html;
    }
Comment by Kim Steinhaug (not verified) (2010-07-08 15:12:00)

I would just like to point out that all of theese snippets for some reasons forgets to account for the most obvious error of them all, closing the H[1-6] tags! Breaking a page in the middle of a H1 tags has enormous impact of the rest of the page!

This simple code:

h1

p

Does not work! Both the original and the updated versions for some reason does not fix this simple code. The second h1 will not get closed since its already closed the first time… regards, Kim Steinhaug <http://www.steinhaug.com/> </div>
Comment by Web Dev (not verified) (2010-06-06 12:41:00)

this is quite good, and work for general tag closing, although I have managed to trip it in complex XHTML - thanks for sharing, I think this is good foundation for future work.

Comment by Berto (not verified) (2010-03-20 00:44:00)

Try this!

    function closetags($html) {
       preg_match_all('#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
        $openedtags = $result[1];
      preg_match_all('#</([a-z]+)>#iU', $html, $result);
     $closedtags = $result[1];
      $len_opened = count($openedtags);
      if (count($closedtags) == $len_opened) {
           return $html;
      }
      $openedtags = array_reverse($openedtags);
      for ($i=0; $i < $len_opened; $i++) {
            if (!in_array($openedtags[$i], $closedtags)) {
             $html .= '</'.$openedtags[$i].'>';
           } else {
               unset($closedtags[array_search($openedtags[$i], $closedtags)]);
            }
      }
      return $html;
    } 
Comment by ssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfaaa (not verified) (2010-04-15 21:09:00)

ssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgssssssssssssssssssssssssssssssssssssssssssfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfg

Comment by Hack MLx (not verified) (2010-03-13 07:20:00)

hey, nice snipe thax for sharing.. but how do i make it work, where do i put because i need it for a script that a i added to a post body…

stripslashes(substr($info[‘post_body’],0,600));

i added that to make like a lil “continue reading” script i could found a plug in, i found some just for wordpress, so yea where do i need to add the function, thanks…

i wait for ur answer… thank you

Comment by Anonymous (not verified) (2009-02-12 02:22:00)

Hi. Can you help me with such problem - I truncate the html (to make a teaser from it) and your code helps to close all the tags, but I ecoutered a problem when a tag is cut in the middle (for example - instead of “<p>” on the end I have “<p” only. How can I add the “>” when it’s needed?

Comment by Milian Wolff (2009-02-12 15:52:00)

The easiest would be to check that by an additional regexp. Something like:

    ...
    $html = preg_replace('#<[a-z]+[^>]*?$#', '', $html);
    return $html;

Note: I did not test this, but the idea should be clear.

Comment by Alexandre de Oliveira (not verified) (2009-01-07 00:29:00)

Thanks, Milian, for the code. The code posted by Martin, however, doesn’t work well.

In the following string, it will not work:

    <div><p>Some text

It will close div but not p. That’s why the code tries to replace the $next-tag from the string, which doesn’t exist because it’s the end of the string and the div tag hasn’t been closed yet.

I made a work around, but have not checked extensively, I just need this quickly, so I have no time. Replace this

    $html = preg_replace('#</'.$next_tag.'#iU','</'.$openedtags[$i].'></'.$next_tag,$html);

by this

    $tmp_html = $html;
    $html = preg_replace('#</'.$next_tag.'#iU','</'.$openedtags[$i].'></'.$next_tag,$html);
    if($html == $tmp_html){ //if it did not replace, do it now
         $html .= '</'.$openedtags[$i].'>';
    }

I hope someone improves the code.

See you.

Comment by Martin (not verified) (2008-04-02 16:05:00)

Hi Milian,

nice snippet, but it does not work always… e.g. if you got the following construct: <table><tr><td>asdasd</tr> I also added the standalone tag option for e.g. or
I modified your code a little like this:

    function closetags($html)
    {
       $arr_single_tags = array('meta','img','br','link','area');
     
       preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
        $openedtags = $result[1];
     
       preg_match_all('#</([a-z]+)>#iU', $html, $result);
     
       $closedtags = $result[1];
     
       $len_opened = count($openedtags);
     
       if (count($closedtags) == $len_opened)
     {
          return $html;
      }
     
       $openedtags = array_reverse($openedtags);
     
       for ($i=0; $i < $len_opened; $i++)
      {
          if (!in_array($openedtags[$i],$arr_single_tags))
           {
              if (!in_array($openedtags[$i], $closedtags))
               {
                  if ($next_tag = $openedtags[$i+1])
                 {
                      $html = preg_replace('#</'.$next_tag.'#iU','</'.$openedtags[$i].'></'.$next_tag,$html);
                    }
                  else
                   {
                      $html .= '</'.$openedtags[$i].'>';
                   }
              }
          }
      }
     
       return $html;
    }

Now it returns: <table><tr><td>asdasd</td></tr></table>

Comment by Milian Wolff (2008-04-05 12:54:00)

Hi Martin! Great that my script is of at least some help.

I just wanted to add that you are missing hr and input in your $arr_single_tags array.

Comment by Michael (not verified) (2007-06-16 12:12:00)

Hi Milian,

thanks for your code snippet. However, there are two issues:

  1. The function fails on self-closing tags, i. e. <img />. For example, <img src="foo.png" />, will become <img src="foo.png">...more.<em>html</em>...</img>. I solved this by adding a switch in the FOR loop (case "img":...break; default: your original code).

  2. Is it possible to change the actual closing behavior? For example: Not close at the end of $html, but close directly after the “false” opening tag occurs; or: remove the “false” opening tag from $html? I couldn’t build the necessary preg_replace myself, but maybe the for-loop can be used via strpos and friend?

Schöne Grüße aus dem Süden der Republik!

</div>

Published on June 16, 2007.