Javascript 如何关闭未关闭的HTML标记?
每当我们从数据库或类似的源获取一些用户输入的内容并进行一些编辑时,我们可能会检索只包含开始标记但不包含结束标记的部分 这会妨碍网站当前的布局 有没有客户端或服务器端的方法来解决此问题?您可以使用: Tidy是Tidy HTML clean and repair实用程序的绑定,它不仅允许您清理和处理HTML文档,还允许您遍历文档树 或 HTML净化器是符合标准的 用HTML编写的HTML过滤器库 PHP。HTML净化器不仅会删除所有恶意 代码(更好地称为XSS)具有经过彻底审核的, 安全但允许的白名单, 它还将确保您的文档 符合标准,只有通过 全面了解W3C规范Javascript 如何关闭未关闭的HTML标记?,javascript,php,Javascript,Php,每当我们从数据库或类似的源获取一些用户输入的内容并进行一些编辑时,我们可能会检索只包含开始标记但不包含结束标记的部分 这会妨碍网站当前的布局 有没有客户端或服务器端的方法来解决此问题?您可以使用: Tidy是Tidy HTML clean and repair实用程序的绑定,它不仅允许您清理和处理HTML文档,还允许您遍历文档树 或 HTML净化器是符合标准的 用HTML编写的HTML过滤器库 PHP。HTML净化器不仅会删除所有恶意 代码(更好地称为XSS)具有经过彻底审核的, 安全但允许的白
我有php的解决方案
<?php
// close opened html tags
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;
}
// close opened html tags
?>
你可以像这样使用这个函数
<?php echo closetags("your content <p>test test"); ?>
除了像Tidy这样的服务器端工具外,您还可以使用用户的浏览器为您进行一些清理。
innerHTML
的一个真正伟大之处在于,它将对动态内容应用与对HTML页面相同的即时修复。这段代码运行得很好(有两个警告),实际上没有任何内容写入页面:
var divTemp = document.createElement('div');
divTemp.innerHTML = '<p id="myPara">these <i>tags aren\'t <strong> closed';
console.log(divTemp.innerHTML);
var divTemp=document.createElement('div');
divTemp.innerHTML='这些标记不是关闭的';
log(divTemp.innerHTML);
注意事项:
虽然这不是你的问题的一部分,因为这是一个CMS,也考虑使用这样的东西。它相当容易实现,有点容易定制,界面对大多数用户来说都非常熟悉,而且它能写出完全有效的代码。还有其他几种现成的富文本编辑器,但YUI拥有最好的许可证,是我见过的最强大的编辑器。Erik Arvidsson在2004年编写了一个漂亮的HTML SAX解析器 它跟踪打开的标记,所以使用最简单的SAX处理程序,可以在正确的位置插入关闭标记:
function tidyHTML(html) {
var output = '';
HTMLParser(html, {
comment: function(text) {
// filter html comments
},
chars: function(text) {
output += text;
},
start: function(tagName, attrs, unary) {
output += '<' + tagName;
for (var i = 0; i < attrs.length; i++) {
output += ' ' + attrs[i].name + '=';
if (attrs[i].value.indexOf('"') === -1) {
output += '"' + attrs[i].value + '"';
} else if (attrs[i].value.indexOf('\'') === -1) {
output += '\'' + attrs[i].value + '\'';
} else { // value contains " and ' so it cannot contain spaces
output += attrs[i].value;
}
}
output += '>';
},
end: function(tagName) {
output += '</' + tagName + '>';
}
});
return output;
}
函数tidyHTML(html){
var输出=“”;
HTMLPasser(html{
注释:函数(文本){
//过滤html注释
},
字符:函数(文本){
输出+=文本;
},
开始:函数(标记名、属性、一元){
输出+='';
},
结束:函数(标记名){
输出+='';
}
});
返回输出;
}
找到了一个很好的答案:
使用PHP5并使用DOMDocument对象的loadHTML()方法。这将自动解析格式错误的HTML,随后调用saveXML()将输出有效的HTML。可以在以下位置找到DOM函数:
此选项的用法:
$doc = new DOMDocument();
$doc->loadHTML($yourText);
$yourText = $doc->saveHTML();
从webmaster-glossar.de(me)中删除未打开/未关闭标记的更好PHP函数
函数closetag($html){
$html_new=$html;
preg#u match_all(“##iU“,$html,$result1);
preg#u match_all(“##iU“,$html,$result2);
$results_start=$result1[1];
$results_end=$result2[1];
foreach($results\u以$startag开头){
如果(!in_数组($startag,$results_end)){
$html_new=str_replace('',$html_new);
}
}
foreach($results\u end AS$endtag){
如果(!在数组中($endtag,$results\u start)){
$html_new=str_replace('',$html_new);
}
}
返回$html_new;
}
使用此功能,如:
closetag('i <b>love</b> my <strike>cat');
#output: i <b>love</b> my cat
closetag('i <b>love</b> my cat</strike>');
#output: i <b>love</b> my cat
closetag(“我爱我的猫”);
#输出:我爱我的猫
closetag(“我爱我的猫”);
#输出:我爱我的猫
我习惯于原生的DOMDocument方法,但在安全性方面有一些改进
<> Pote,使用DOMBOOST的其他答案不考虑HTML字符串,如
This is a <em>HTML</em> strand
这是一条HTML链
上述情况实际上会导致
<p>This is a <em>HTML</em> strand
这是一条HTML链
我的解决方案如下
function closeDanglingTags($html) {
if (strpos($html, '<') || strpos($html, '>')) {
// There are definitiley HTML tags
$wrapped = false;
if (strpos(trim($html), '<') !== 0) {
// The HTML starts with a text node. Wrap it in an element with an id to prevent the software wrapping it with a <p>
// that we know nothing about and cannot safely retrieve
$html = cHE::getDivHtml($html, null, 'closedanglingtagswrapper');
$wrapped = true;
}
$doc = new DOMDocument();
$doc->encoding = 'utf-8';
@$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
if ($doc->firstChild) {
// Test whether the firstchild is definitely a DOMDocumentType
if ($doc->firstChild instanceof DOMDocumentType) {
// Remove the added doctype
$doc->removeChild($doc->firstChild);
}
}
if ($wrapped) {
// The contents originally started with a text node and was wrapped in a div#plasmappclibtextwrap. Take the contents
// out of that div
$node = $doc->getElementById('closedanglingtagswrapper');
$children = $node->childNodes; // The contents of the div. Equivalent to $('selector').children()
$doc = new DOMDocument(); // Create a new document to add the contents to, equiv. to "var doc = $('<html></html>');"
foreach ($children as $childnode) {
$doc->appendChild($doc->importNode($childnode, true)); // E.g. doc.append()
}
}
// Remove the added html,body tags
return trim(str_replace(array('<html><body>', '</body></html>'), '', html_entity_decode($doc->saveHTML())));
} else {
return $html;
}
}
函数closeDanglingTags($html){
if(strpos($html,,)){
//有明确的HTML标记
$wrapped=false;
如果(strpos(trim($html),“用于html片段,并且当片段有一个根元素时,从我开始的工作已经成功地实现了以下几点:
$dom = new DOMDocument();
$dom->loadHTML($string);
$body = $dom->documentElement->firstChild->firstChild;
$string = $dom->saveHTML($body);
如果没有根元素,这是可能的(但似乎只在textparatext
中的p标记中包装第一个文本子节点):
或者更好的是,从PHP>=5.4和libxml>=2.7.8(对于libxml\u HTML\u noimpled
,为2.7.7):
我喜欢这个函数。我看到的一个问题是,它无法修复一些用户非常擅长的损坏的嵌套(例如,“粗体和斜体文本”
)。-1检查count($closedtags)==count($openedtags)
是不够的…例如,“
改进XHTML:$doc=new DOMDocument();libxml使用内部错误(true);$doc->loadHTML('.$html_text.');libxml_clear_errors();$html_text=
$dom = new DOMDocument();
$dom->loadHTML($string);
$body = $dom->documentElement->firstChild->firstChild;
$string = $dom->saveHTML($body);
$dom = new DOMDocument();
$dom->loadHTML($string);
$bodyChildNodes = $dom->documentElement->firstChild->childNodes;
$string = '';
foreach ($bodyChildNodes as $node){
$string .= $dom->saveHTML($node);
}
$dom = new DOMDocument();
// Load with no html/body tags and do not add a default dtd
$dom->loadHTML($string, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$string = $dom->saveHTML();