415 Stimmen

Können Sie anhand von Beispielen erläutern, warum es schwierig ist, XML und HTML mit einer Regex zu parsen?

Ein Fehler, den ich bei den Leuten sehe über et noch einmal versucht, XML oder HTML mit einer Regex zu parsen. Hier sind einige der Gründe, warum das Parsen von XML und HTML schwierig ist:

Die Leute wollen eine Datei als eine Folge von Zeilen behandeln, aber das ist richtig:

<tag
attr="5"
/>

Die Leute wollen < oder <tag als den Anfang eines Tags behandeln, aber so etwas gibt es auch in der freien Wildbahn:

<img src="imgtag.gif" alt="<img>" />

Oft möchte man beginnende Tags mit endenden Tags abgleichen, aber XML und HTML erlauben es, dass Tags sich selbst enthalten (was traditionelle Regexe überhaupt nicht können):

<span id="outer"><span id="inner">foo</span></span> 

Oft möchte man einen Abgleich mit dem Inhalt eines Dokuments durchführen (z. B. das berühmte Problem "alle Telefonnummern auf einer bestimmten Seite finden"), aber die Daten sind möglicherweise markiert (auch wenn sie bei der Betrachtung normal erscheinen):

<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>

Kommentare können schlecht formatierte oder unvollständige Tags enthalten:

<a href="foo">foo</a>
<!-- FIXME:
    <a href="
-->
<a href="bar">bar</a>

Welche anderen Probleme sind Ihnen bekannt?

270voto

bobince Punkte 512550

Hier ist etwas lustiges gültiges XML für Sie:

<!DOCTYPE x [ <!ENTITY y "a]>b"> ]>
<x>
    <a b="&y;>" />
    <![CDATA[[a>b <a>b <a]]>
    <?x <a> <!-- <b> ?> c --> d
</x>

Und dieser kleine Wonneproppen ist gültiges HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" [
    <!ENTITY % e "href='hello'">
    <!ENTITY e "<a %e;>">
]>
    <title>x</TITLE>
</head>
    <p id  =  a:b center>
    <span / hello </span>
    &amp<br left>
    <!---- >t<!---> < -->
    &e link </a>
</body>

Ganz zu schweigen von der browser-spezifischen Analyse auf ungültige Konstrukte.

Viel Glück beim Kampf gegen Regex!

EDIT (Jörg W. Mittag): Hier ist ein weiteres schönes Beispiel für wohlgeformtes, gültiges HTML 4.01:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd"> 
<HTML/
  <HEAD/
    <TITLE/>/
    <P/>

72voto

LordOfThePigs Punkte 10640

Eigentlich

<img src="imgtag.gif" alt="<img>" />

ist kein gültiges HTML und auch kein gültiges XML.

Es handelt sich nicht um gültiges XML, da die Zeichen '<' und '>' innerhalb von Attributstrings nicht gültig sind. Sie müssen mit den entsprechenden XML-Entitäten < und > maskiert werden

Es handelt sich auch nicht um gültiges HTML, da die kurze Schlussform in HTML nicht zulässig ist (in XML und XHTML ist sie jedoch korrekt). Der "img"-Tag ist außerdem ein implizit geschlossener Tag gemäß der HTML 4.01-Spezifikation. Das bedeutet, dass das manuelle Schließen des Tags eigentlich falsch ist und dem doppelten Schließen eines anderen Tags entspricht.

Die korrekte Version in HTML lautet

<img src="imgtag.gif" alt="&lt;img&gt;">

und die korrekte Version in XHTML und XML lautet

<img src="imgtag.gif" alt="&lt;img&gt;"/>

Das folgende Beispiel, das Sie angeführt haben, ist ebenfalls ungültig

<
tag
attr="5"
/>

Dies ist auch kein gültiges HTML oder XML. Der Name des Tags muss direkt hinter dem "<" stehen, obwohl die Attribute und das abschließende ">" an beliebiger Stelle stehen können. Das gültige XML ist also eigentlich

<tag
attr="5"
/>

Und hier ist noch ein weiterer lustiger Aspekt: Sie können entweder " oder ' als Anführungszeichen für Ihr Attribut verwenden

<img src="image.gif" alt='This is single quoted AND valid!'>

Alle anderen Gründe, die genannt wurden, sind richtig, aber das größte Problem beim Parsen von HTML ist, dass die Leute in der Regel nicht alle Syntaxregeln richtig verstehen. Die Tatsache, dass Ihr Browser Ihre Tagsuppe als HTML interpretiert, bedeutet nicht, dass Sie tatsächlich gültiges HTML geschrieben haben.

Edit: Und sogar stackoverflow.com stimmt mir zu, was die Definition von gültig und ungültig angeht. Ihr ungültiges XML/HTML wird nicht hervorgehoben, meine korrigierte Version hingegen schon.

Im Grunde ist XML nicht dafür gemacht, mit Regexps geparst zu werden. Es gibt aber auch keinen Grund, dies zu tun. Es gibt viele, viele XML-Parser für jede einzelne Sprache. Sie haben die Wahl zwischen SAX-Parsern, DOM-Parsern und Pull-Parsern. Alle diese sind garantiert viel schneller als das Parsen mit einem Regexp und Sie können dann coole Technologien wie XPath oder XSLT auf den resultierenden DOM-Baum anwenden.

Meine Antwort lautet daher: Das Parsen von XML mit Regexps ist nicht nur schwierig, sondern auch eine schlechte Idee. Verwenden Sie einfach einen der Millionen vorhandenen XML-Parser und nutzen Sie alle fortgeschrittenen Funktionen von XML.

HTML ist einfach zu schwierig, um es selbst zu analysieren. Erstens hat die legale Syntax viele kleine Feinheiten, die Sie vielleicht nicht kennen, und zweitens ist HTML in der freien Wildbahn einfach ein riesiger stinkender Haufen (Sie verstehen, worauf ich hinaus will). Es gibt eine Reihe von laxen Parser-Bibliotheken, die HTML wie eine Tag-Suppe behandeln können, verwenden Sie einfach diese.

62voto

JaredPar Punkte 699699

Ich habe einen ganzen Blogeintrag zu diesem Thema geschrieben: Einschränkungen bei regulären Ausdrücken

Der springende Punkt ist, dass es sich bei HTML und XML um rekursive Strukturen handelt, die Zählmechanismen erfordern, um korrekt geparst werden zu können. Ein echter Regex ist nicht in der Lage, zu zählen. Man braucht eine kontextfreie Grammatik, um zu zählen.

Der vorherige Absatz ist mit einem kleinen Vorbehalt versehen. Bestimmte Regex-Implementierungen unterstützen jetzt die Idee der Rekursion. Sobald Sie jedoch anfangen, Rekursion in Ihre Regex-Ausdrücke einzubauen, stoßen Sie wirklich an die Grenzen und sollten einen Parser in Betracht ziehen.

22voto

AmbroseChapel Punkte 11580

Ein Problem, das nicht auf Ihrer Liste steht, ist, dass Attribute in beliebiger Reihenfolge auftreten können. Wenn Ihr Regex also nach einem Link mit der href "foo" und der Klasse "bar" sucht, können sie in beliebiger Reihenfolge auftreten und eine beliebige Anzahl anderer Dinge zwischen ihnen haben.

17voto

Anton Gogolev Punkte 109749

Das hängt davon ab, was Sie mit "Parsen" meinen. Im Allgemeinen kann XML nicht mit Regex geparst werden, da die XML-Grammatik keineswegs regulär ist. Vereinfacht gesagt, können Regexe nicht zählen (na ja, Perl-Regexe können vielleicht tatsächlich Dinge zählen), also kann man keine Open-Close-Tags ausgleichen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X