2010-06-29 13 views
9

He estado usando el DOM de PHP para cargar una plantilla html, modificarla y enviarla. Recientemente descubrí que las etiquetas de cierre automático (vacías) no incluyen una barra inclinada de cierre, a pesar de que el archivo de la plantilla sí lo hizo.¿Por qué PHP DOM no incluye barras en las etiquetas de cierre automático?

p. Ej.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"`"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
</head> 
<body> 
</body> 
</html> 

se convierte en:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
</head> 
<body> 
</body> 
</html> 

Es esto un error o una configuración, o un problema de tipo de documento?

+0

¿Has intentado agregar un doctype para ver qué pasa? – ceejayoz

+0

Siempre he estado usando un doctype XHTML, pensé que no era relevante porque estoy cansado -_- – peterjwest

Respuesta

19

DOMDocument->saveHTML() toma su infoset XML DOM y lo escribe como HTML de la vieja escuela, no XML. No debe usar saveHTML() junto con un doctype XHTML, ya que su resultado no será un XML bien formado.

En cambio, si usa saveXML(), obtendrá el XHTML adecuado. Está bien servir esta salida XML a los navegadores compatibles con estándares si le da un encabezado Content-Type: application/xhtml+xml. Pero desafortunadamente IE6-8 no podrá leer eso, ya que solo pueden manejar HTML de la vieja escuela, bajo el tipo de medio text/html.

La solución de compromiso habitual es servir text/html y utilizar 'XHTML compatible con HTML' como se indica en el Apéndice C de la especificación XHTML 1.0. Pero lamentablemente no existe el método PHP DOMDocument->saveXHTML() para generar el resultado correcto para esto.

Hay algunas cosas que puede hacer para persuadir saveXML() para producir resultados compatibles con HTML para algunos casos comunes. La principal es que debe asegurarse de que solo los elementos definidos por HTML4 tengan un modelo de contenido EMPTY (<img>, <br>, etc.) realmente tienen contenido vacío, lo que hace que se use la sintaxis de cierre automático (<img/>). Otros elementos no deben usar la sintaxis de cierre automático, por lo que si están vacíos se debería poner un espacio en su contenido de texto para que dejen de ser tan:

<script src="x.js"/>   <-- no good, confuses HTML parser and breaks page 
<script src="x.js"> </script> <-- fine 

El otro a tener en cuenta es el manejo de la en línea <script> y <style> elementos, que son elementos normales en XHTML pero especiales CDATA -contenidos en HTML. Es necesario algún tipo de envoltura /*<![CDATA[*/.../*]]>*/ para que los caracteres < o & en su interior se comporten de manera consistente, aunque tenga en cuenta que debe evitar las secuencias ]]> y </.

Si realmente quiere hacerlo bien, tendría que escribir su propio serializador XHTML compatible con HTML. A largo plazo, esa sería probablemente una mejor opción. Pero para pequeños casos simples, piratear su entrada para que no contenga nada que pueda salir del otro lado de un serializador XML como incompatible con HTML es probablemente la solución más rápida.

Eso o simplemente aguántalo y convive con el HTML no XML de la vieja escuela, obviamente.

+0

Gracias por la respuesta detallada. Siempre he odiado el DOM de PHP, sin embargo, esta es la guinda del ataúd. Puedo probar algunos procesos de pre/post de expresiones regulares para alterar la entrada/salida con saveXML(). Esta no es una solución ideal. ¿El DOM de PHP admite HTML 5? – peterjwest

+0

Evite el HTML de salida de hackeo regex a toda costa. (Pero yo diría eso, ¿no?) Escribir un serializador XHTML no es tan malo (XML es mucho más fácil de serializar de lo que es analizar); sería lento, pero luego preparar plantillas con 'DOMDocument' es bastante lento en general. En cuanto a HTML5, funcionará efectivamente igual que HTML4. PHP no sabe acerca de los nuevos elementos HTML5, por lo que si usa alguno que debe ser 'VACÍO' (por ejemplo,' '), obtendrá una etiqueta final no válida para ellos. – bobince

+0

Oh wow, [lo harías] (http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454) dicen eso. ¿Conoces una forma rápida de preparar plantillas (HTML o XHTML) en PHP? – peterjwest

2

tema tipo de documento, ya que es text/html no se necesita la barra de cierre, sólo es necesario el cierre de barra si es un documento XHTML

señaló que ha actualizado para añadir en el tipo de documento, pero también se ve dom PHP en esa etiqueta meta que tienes ahí, y content = "text/html; charset = utf-8" claramente no está basado en XML, es solo texto/html :)

aside: DOM api también retoma el juego de caracteres desde allí

+1

Todavía no entiendo por qué las personas usan xhtml doctype, especialmente cuando luego usan el tipo de contenido de texto/html para hacer que su sitio funcione correctamente en IE ... para el 99% de la web, xhtml no ofrece ninguna ventaja a HTML4.01 a costa de tener que implementarlo incorrectamente (a saber, content-type = text/html) – HorusKol

+0

xhtml es compatible con la cadena de herramientas XML, y ha habido una gran inversión en herramientas XML, puede no marcar una diferencia para los navegadores, pero sin duda hace una diferencia para muchos otros clientes y generadores (especialmente si agrega xslt, etc. a la combinación) – nathan

-1

Ésta es una vieja pregunta, pero ...
Como otros han dicho de, DOM de PHP deja mucho que desear ...
Aquí es una expresión regular para cerrar las etiquetas "VOID" si así lo desea

$voidTags = array('area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr'); 
$regEx = '#<('.implode('|', $voidTags).')(\b[^>]*)>#'; 
$html = preg_replace($regEx, '<\\1\\2 />', $html); 
+0

Parece haber algunos problemas. Lo modifiqué y esto funcionó para mí: '$ regEx = '# <\ b ('. Implode ('|', $ voidTags). ') ([^>] +)><\/\b\1> #g';' – user594044

Cuestiones relacionadas