2012-05-05 28 views
7

La mia esperienza mi dice che one should not use RegExp to parse HTML/XML, e sono completamente d'accordo! E 'Come vengono implementati i parser DOM?

  • sudicio
  • Non robusta e facilmente rotto
  • male puro

Tutti dicono "utilizzare un parser DOM" di qualche tipo, che è bene per me. Ma ora mi sono incuriosito. Come funzionano?

Stavo cercando l'origine della classe DOMDocument e non è riuscito a trovarlo.

Questa domanda deriva dal fatto che, ad esempio, filter_var() è considerato una valida alternativa per la convalida delle e-mail con RegExp, ma quando si guarda all'origine, vedrete che in realtà utilizza RegExp stesso!

Quindi, se si dovesse costruire un DOM Parser in PHP? Come andresti sull'analisi dell'HTML? Come hanno fatto?

+2

I parser DOM vengono normalmente implementati come tokenizer. Se puoi leggere C#, il codice sorgente per [HTML Agility Pack] (http://htmlagilitypack.codeplex.com) può chiarire l'approccio. – Oded

+4

Informazioni su 'filter_var()': nessuno ha mai detto che non dovresti convalidare un indirizzo email con espressioni regolari. Il fatto è che scrivere una regex per questo compito che è * giusto * è molto difficile e richiede un grande sforzo di ricerca. Quindi ci sono migliaia di implementazioni terribili là fuori. Questo è il motivo per cui dovresti semplicemente usare 'filter_var()'. – kapa

+0

Se hai a che fare con XHTML, un normale parser XML funzionerà perfettamente. – Niko

risposta

5

Penso che dovresti controllare l'articolo How Browsers Work: Behind the Scenes of Modern Web Browsers. È una lettura lunga, ma vale il tuo tempo. In particolare, la sezione HTML Parser.

Mentre non riesco a rendere giustizia l'articolo, forse un sommario superficiale sarà buono per tenerne uno finché non avranno il tempo di leggere e digerire quel capolavoro. Devo ammettere però, in questo settore sono un novizio che ha poca esperienza. Avendo sviluppato per il web professionalmente da circa 10 anni, il modo in cui il browser gestisce e interpreta il mio codice è da tempo una scatola nera.

HTML, XHTML, CSS o JavaScript: fai la tua scelta. Hanno tutti un grammatico e un vocabolario. L'inglese è un altro grande esempio. Abbiamo regole grammaticali che ci aspettiamo che persone, libri e altro seguano. Abbiamo anche un vocabolario composto da nomi, verbi, aggettivi e altro.

I browser interpretano un documento esaminando la sua grammatica e il suo vocabolario. Quando capita tra gli oggetti che alla fine non capisce, ti farà sapere (sollevando eccezioni, ecc.). Tu ed io facciamo lo stesso in common-speak.

amo StackOverflow, ma se potessi cambiare una cosa sarebbe essere absolutamente rotto ...

Nota nell'esempio di cui sopra come si inizia subito a raccogliere a parte le parole e le relazioni tra le parole . L'inizio ha perfettamente senso, "Adoro StackOverflow." Poi arriviamo a "... se potessi cambiare" e ci fermiamo immediatamente. "Modificato" non appartiene a questo. È probabile che l'autore volesse dire "cambiamento".Ora il vocabolario è giusto, ma la grammatica è sbagliata. Un po 'più tardi ci imbattiamo in "essere essere", che può anche violare una regola grammaticale, e poco più avanti incontriamo la parola "absolutamente", che non fa parte del vocabolario inglese - un altro errore.

Pensa a tutto questo in termini di DOCTYPE. Al momento ho aperto sul mio secondo monitor la fonte dietro XHTML 1.0 Strict Doctype. Tra i suoi interni ci sono linee come la seguente:

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

Definisce le entità di intestazione. E fintanto che aderisco alla grammatica di XHTML, posso usare uno qualsiasi di questi nel mio documento (<h1>Hello World</h1>). Ma se provo a fare uno, dicono H7, il browser inciampare il vocabolario come "straniero", e informare me:

"Linea 7, Colonna 8: elemento 'H7' indefinito"

Forse durante l'analisi del documento ci imbattiamo in <table. Sappiamo che ora abbiamo a che fare con un elemento table, che ha il proprio set di vocabolario come tbody, tr, ecc. Finché conosciamo la lingua, le regole grammaticali, ecc., Sappiamo quando qualcosa non va. Tornando alla XHTML 1.0 Strict Doctype, troviamo il seguente:

<!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;> 

Dato questo riferimento, siamo in grado di mantenere un controllo in esecuzione contro qualsiasi fonte stiamo analizzando. Se l'autore scrive tread, anziché thead, abbiamo uno standard in base al quale possiamo determinare che si è in errore. Quando i problemi non sono risolti e non riusciamo a trovare regole che soddisfino determinati usi della grammatica e del vocabolario, informiamo l'autore che il loro documento non è valido.

Non sto affatto facendo giustizia a questa scienza, tuttavia spero che questo serva, se non altro, abbastanza da poterlo trovare dentro di te per sederti e leggere l'articolo di riferimento come l'inizio di questa risposta, e magari sedersi e studiare i vari DTD che incontriamo giorno per giorno.

1

La buona notizia è qui, non è necessario reinventare la ruota. Lo libxml library viene utilizzato all'interno dell'estensione DOMDocument di PHP e il suo codice sorgente è disponibile. Have a look there Suggerisco.

E btw., Le espressioni regolari non sono sempre sbagliate, ma è necessario usarle correttamente, altre si entra direttamente nella cucina di Hells, diventare un serial killer o visitare Chutullu o come si chiama quel tizio. Suggerisco quindi quanto segue: REX: XML Shallow Parsing with Regular Expressions.

Ma se fai tutto bene, le espressioni regolari possono aiutarti molto con l'analisi. Devi solo sapere cosa fai.

+0

Come ho già detto, non sto cercando di reinventare la ruota, sono solo curioso di sapere come funziona la ruota. Inoltre ho provato a trovare il codice sorgente per DOMDocument e non sono riuscito a trovarlo. –

+0

Ho collegato il sorgente di libxml. Vedi anche la descrizione dell'architettura sul loro sito web, il progetto è abbastanza grande. E c'è anche il progetto htmlpurifier che è un parser HTML scritto in PHP IIRC. – hakre