2012-05-05 20 views
7

Mi experiencia me dice que one should not use RegExp to parse HTML/XML, y estoy totalmente de acuerdo! Es¿Cómo se implementan los analizadores DOM?

  • sucia
  • No es robusto y fácil de romper
  • el mal puro

Todos dicen "utilizar un analizador DOM" de algún tipo, lo cual está bien por mí. Pero ahora tengo curiosidad. ¿Cómo funcionan?

Estaba buscando el origen de la clase DOMDocument y no pude encontrarlo.

Esta pregunta proviene del hecho de que filter_var(), por ejemplo, se considera una buena alternativa para validar correos electrónicos con RegExp, pero cuando mira la fuente, ¡verá que realmente usa RegExp!

Entonces, si construyes un analizador DOM en PHP? ¿Cómo harías para analizar el HTML? ¿Cómo lo hicieron?

+2

Los analizadores DOM normalmente se implementan como tokenizadores. Si puede leer C#, el código fuente de [HTML Agility Pack] (http://htmlagilitypack.codeplex.com) puede aclarar el enfoque. – Oded

+4

Acerca de 'filter_var()': nunca nadie dijo que no debiera validar una dirección de correo electrónico con expresiones regulares. El hecho es que escribir una expresión regular para esta tarea * correcta * es muy difícil y requiere mucho esfuerzo de investigación. Entonces hay miles de implementaciones terribles por ahí. Es por eso que simplemente debes usar 'filter_var()'. – kapa

+0

Si se trata de XHTML, un analizador XML normal funcionará bien. – Niko

Respuesta

5

Creo que deberías echar un vistazo al artículo How Browsers Work: Behind the Scenes of Modern Web Browsers. Es una lectura larga, pero vale la pena su tiempo. Específicamente, la sección Analizador HTML.

Si bien no puedo hacer justicia al artículo, tal vez un resumen superficial será bueno para mantener uno hasta que tengan el tiempo para leer y digerir esa obra maestra. Debo admitir, sin embargo, que en esta área soy un novato con muy poca experiencia. Después de haber desarrollado para la web profesionalmente durante unos 10 años, la forma en que el navegador maneja e interpreta mi código ha sido durante mucho tiempo una caja negra.

HTML, XHTML, CSS o JavaScript: haga su elección. Todos tienen una gramática, así como un vocabulario. El inglés es otro gran ejemplo. Tenemos reglas gramaticales que esperamos que sigan personas, libros y más. También tenemos un vocabulario compuesto de sustantivos, verbos, adjetivos y más.

Los navegadores interpretan un documento al examinar su gramática, así como su vocabulario. Cuando se trata de artículos que en última instancia no comprende, se lo hará saber (planteando excepciones, etc.). Tú y yo hacemos lo mismo en lenguaje común.

Me encanta Stackoverflow, pero si pudiera cambiar una cosa que se puede romper ... Absolutamente

Nota en el ejemplo anterior como se comienza inmediatamente a desmenuzar las palabras y las relaciones entre las palabras . El comienzo tiene mucho sentido, "Me encanta StackOverflow". Luego llegamos a "... si pudiera cambiar", e inmediatamente nos detenemos. "Cambiado" no pertenece aquí. Es probable que el autor significara "cambio" en su lugar.Ahora el vocabulario es correcto, pero la gramática es incorrecta. Un poco más tarde nos topamos con "be be", que también puede violar una regla gramatical, y un poco más adelante encontramos la palabra "absolutamente", que no forma parte del vocabulario inglés, otro error.

Piense en todo esto en términos de un DOCTYPE. Ahora mismo abrí en mi segundo monitor la fuente detrás de XHTML 1.0 Strict Doctype. Entre sus partes internas se encuentran líneas como las siguientes:

<!ENTITY % heading "h1|h2|h3|h4|h5|h6"> 

Esto define las entidades del encabezado. Y mientras siga la gramática de XHTML, puedo usar cualquiera de estos en mi documento (<h1>Hello World</h1>). Pero si trato de hacer uno, y di H7, el navegador tropezar con el vocabulario como "extrañas", y me informen:

"Línea 7, Columna 8: Elemento 'H7' indefinido"

Tal vez al analizar el documento nos encontremos con <table. Sabemos que ahora estamos lidiando con un elemento table, que tiene su propio conjunto de vocabulario como tbody, tr, etc. Mientras sepamos el idioma, las reglas de gramática, etc., sabemos cuándo algo está mal. Volviendo al XHTML 1.0 Estricto Doctype, nos encontramos con lo siguiente:

<!ELEMENT table 
    (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))> 
<!ELEMENT caption %Inline;> 
<!ELEMENT thead (tr)+> 
<!ELEMENT tfoot (tr)+> 
<!ELEMENT tbody (tr)+> 
<!ELEMENT colgroup (col)*> 
<!ELEMENT col  EMPTY> 
<!ELEMENT tr  (th|td)+> 
<!ELEMENT th  %Flow;> 
<!ELEMENT td  %Flow;> 

Teniendo en cuenta esta referencia, se puede mantener un control de funcionamiento contra cualquier fuente que estamos análisis. Si el autor escribe tread, en lugar de thead, tenemos un estándar por el cual podemos determinar que es un error. Cuando los problemas no se resuelven y no podemos encontrar reglas que coincidan con ciertos usos de la gramática y el vocabulario, informamos al autor que su documento no es válido.

No estoy de ninguna manera haciendo justicia a esta ciencia, sin embargo, espero que esto sirva, si nada más, para que sea suficiente que usted pueda sentarse y leer el artículo al que se hace referencia como el principio de esta respuesta, y tal vez sentarse y estudiar las diversas DTD que encontramos día a día.

1

Las buenas noticias están aquí, no es necesario reinventar la rueda. El libxml library se usa dentro de la extensión DOMDocument de PHP y su código fuente está disponible. Have a look there Sugiero.

Y, por cierto, las expresiones regulares no siempre son incorrectas, pero debes usarlas correctamente, otras ir directamente a la cocina de los infiernos, convertirte en un asesino en serie o visitar a Chutullu o cómo se llama ese tipo. Sugiero la siguiente lectura por lo tanto: REX: XML Shallow Parsing with Regular Expressions.

Pero si haces todo bien, las expresiones regulares pueden ayudarte mucho con el análisis. Es solo que debes saber lo que haces.

+0

Como he dicho, no estoy tratando de reinventar la rueda, solo tengo curiosidad sobre cómo funciona la rueda. También traté de encontrar la fuente de DOMDocument y no pude encontrarlo. –

+0

Vinculado el origen de libxml. Ver también la descripción de la arquitectura en su sitio web, el proyecto es bastante grande. Y también está el proyecto htmlpurifier, que es un analizador HTML escrito en PHP IIRC. – hakre

Cuestiones relacionadas