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)
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:
Comment by Plasmodino (not verified) (2011-01-05 22:47:00)
I suggest the following code for closing open tags:
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:
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>
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>
</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!
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:
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:
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
by this
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:
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
andinput
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:
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
).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 necessarypreg_replace
myself, but maybe the for-loop can be used viastrpos
and friend?Schöne Grüße aus dem Süden der Republik!