javascript - son - lista de atributos html
¿Cómo cerrar las etiquetas HTML no cerradas? (8)
Además de las herramientas del lado del servidor como Tidy, también puede usar el navegador del usuario para hacer parte de la limpieza por usted. Una de las mejores cosas de innerHTML
es que aplicará la misma reparación sobre la marcha al contenido dinámico que a las páginas HTML. Este código funciona bastante bien (con dos advertencias) y en realidad no se escribe nada en la página:
var divTemp = document.createElement(''div'');
divTemp.innerHTML = ''<p id="myPara">these <i>tags aren/'t <strong> closed'';
console.log(divTemp.innerHTML);
Las advertencias:
Los diferentes navegadores devolverán diferentes cadenas. Esto no es tan malo, excepto en el caso de IE, que devolverá las etiquetas en mayúscula y quitará las comillas de los atributos de la etiqueta, lo que no pasará la validación. La solución aquí es hacer una limpieza simple en el lado del servidor. Pero al menos el documento será XML estructurado adecuadamente.
Sospecho que deberías demorar un poco antes de leer el HTML interno - dale al navegador la oportunidad de digerir el hilo - o te arriesgas a recuperar exactamente lo que pusieron. Acabo de probar IE8 y parece que la cadena se analiza inmediatamente, pero no estoy tan seguro de IE6. Probablemente sea mejor leer el HTML interno después de un retraso (o tirarlo a un setTimeout () para forzarlo hasta el final de la cola).
Te recomendaría que tomes el consejo de @ Gordon y uses Tidy si tienes acceso (lleva menos trabajo implementarlo) y en su defecto, usa innerHTML y escribe tu propia función ordenada en PHP.
Y aunque esto no forma parte de su pregunta, ya que se trata de un CMS, considere también el uso del editor de texto enriquecido YUI 2 para cosas como esta. Es bastante fácil de implementar, algo fácil de personalizar, la interfaz es muy familiar para la mayoría de los usuarios y arroja un código perfectamente válido. Hay muchos otros editores de textos enriquecidos listos para usar, pero YUI tiene la mejor licencia y es el más poderoso que he visto.
Siempre que vayamos a buscar contenido insertado por un usuario con alguna edición de la base de datos o fuentes similares, podríamos recuperar la porción que solo contiene la etiqueta de apertura pero no el cierre.
Esto puede obstaculizar el diseño actual del sitio web.
¿Hay alguna forma de solucionar esto en el lado del cliente o en el servidor?
Encontré una gran respuesta para este:
Use PHP 5 y use el método loadHTML () del objeto DOMDocument. Esto auto analiza HTML mal formado y una llamada subsiguiente a saveXML () generará el HTML válido. Las funciones DOM se pueden encontrar aquí:
El uso de esto:
$doc = new DOMDocument();
$doc->loadHTML($yourText);
$yourText = $doc->saveHTML();
Erik Arvidsson escribió un buen analizador de HTML SAX en 2004. http://erik.eae.net/archives/2004/11/20/12.18.31/
Realiza un seguimiento de las etiquetas abiertas, por lo que con un controlador SAX minimalista es posible insertar etiquetas de cierre en la posición correcta:
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;
}
Para los fragmentos de HTML, y trabajando a partir de la respuesta de KJS, he tenido éxito con lo siguiente cuando el fragmento tiene un elemento raíz:
$dom = new DOMDocument();
$dom->loadHTML($string);
$body = $dom->documentElement->firstChild->firstChild;
$string = $dom->saveHTML($body);
Sin un elemento raíz, esto es posible (pero parece envolver solo el primer nodo hijo de texto en etiquetas p en el text <p>para</p> text
):
$dom = new DOMDocument();
$dom->loadHTML($string);
$bodyChildNodes = $dom->documentElement->firstChild->childNodes;
$string = '''';
foreach ($bodyChildNodes as $node){
$string .= $dom->saveHTML($node);
}
O mejor aún, de PHP> = 5.4 y libxml> = 2.7.8 (2.7.7 para LIBXML_HTML_NOIMPLIED
):
$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();
Puedes usar Tidy :
Tidy es un enlace para la utilidad de limpieza y reparación Tidy HTML que le permite no solo limpiar y manipular documentos HTML, sino también recorrer el árbol de documentos.
HTML Purifier es una biblioteca de filtro HTML compatible con los estándares escrita en PHP. HTML Purifier no solo eliminará todos los códigos maliciosos (más conocidos como XSS) con una lista blanca completamente auditada, segura y permisiva, sino que también se asegurará de que sus documentos cumplan con los estándares, algo que solo se puede lograr con un conocimiento exhaustivo de las especificaciones del W3C.
Solía usar el método DOMDocument nativo, pero con algunas mejoras para la seguridad.
Tenga en cuenta que otras respuestas que usan DOMDocument no consideran hebras html como
This is a <em>HTML</em> strand
Lo anterior realmente resultará en
<p>This is a <em>HTML</em> strand
Mi solución está debajo
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;
}
}
Tengo una solución para 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
?>
Puedes usar esta función como
<?php echo closetags("your content <p>test test"); ?>
Una mejor función de PHP para eliminar etiquetas no abiertas / no cerradas de webmaster-glossar.de (me)
function closetag($html){
$html_new = $html;
preg_match_all ( "#<([a-z]+)( .*)?(?!/)>#iU", $html, $result1);
preg_match_all ( "#</([a-z]+)>#iU", $html, $result2);
$results_start = $result1[1];
$results_end = $result2[1];
foreach($results_start AS $startag){
if(!in_array($startag, $results_end)){
$html_new = str_replace(''<''.$startag.''>'', '''', $html_new);
}
}
foreach($results_end AS $endtag){
if(!in_array($endtag, $results_start)){
$html_new = str_replace(''</''.$endtag.''>'', '''', $html_new);
}
}
return $html_new;
}
usa esta función como:
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