49 Stimmen

DOM-Parser, der den HTML5-Stil </ im <script>-Tag erlaubt

更新情報 : html5lib (unten in der Frage) scheint nahe dran zu sein, ich muss nur noch besser verstehen, wie es verwendet wird.

Ich versuche, einen HTML5-kompatiblen DOM-Parser für PHP 5.3 zu finden. Insbesondere muss ich auf das folgende HTML-ähnliche CDATA innerhalb eines Skript-Tags zugreifen:

<script type="text/x-jquery-tmpl" id="foo">
    <table><tr><td>${name}</td></tr></table>
</script>

Die meisten Parser beenden das Parsen vorzeitig, da HTML 4.01 beendet das Parsen von Skript-Tags wenn es ETAGO findet ( </ ) innerhalb einer <script> Tag. Allerdings ist HTML5 ermöglicht </ antes de </script> . Alle Parser, die ich bisher ausprobiert habe, sind entweder gescheitert, oder sie sind so schlecht dokumentiert, dass ich nicht herausgefunden habe, ob sie funktionieren oder nicht.

Meine Anforderungen:

  1. Echter Parser, keine Regex-Hacks.
  2. Möglichkeit, ganze Seiten oder HTML-Fragmente zu laden.
  3. Fähigkeit, Skript zu ziehen Inhalt zurück, wobei die Auswahl über das Attribut id des Tags erfolgt.

Eingabe:

<script id="foo"><td>bar</td></script>

Beispiel einer fehlgeschlagenen Ausgabe (kein Schließen) </td> ):

<script id="foo"><td>bar</script>

Einige Parser und ihre Ergebnisse:

DOMDocument (scheitert)

Quelle:

<?php

header('Content-type: text/plain');
$d = new DOMDocument;
$d->loadHTML('<script id="foo"><td>bar</td></script>');
echo $d->saveHTML();

Ausgabe:

Warning: DOMDocument::loadHTML(): Unexpected end tag : td in Entity, line: 1 in /home/adam/public_html/2010/10/26/dom.php on line 5
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><script id="foo"><td>bar</script></head></html>

FluentDOM (scheitert)

Quelle:

<?php

header('Content-type: text/plain');
require_once 'FluentDOM/src/FluentDOM.php';
$html = "<html><head></head><body><script id='foo'><td></td></script></body></html>";
echo FluentDOM($html, 'text/html');

Ausgabe:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head></head><body><script id="foo"><td></script></body></html>

phpQuery (scheitert)

Quelle:

<?php

header('Content-type: text/plain');

require_once 'phpQuery.php';

phpQuery::newDocumentHTML(<<<EOF
<script type="text/x-jquery-tmpl" id="foo">
<td>test</td>
</script>
EOF
);

echo (string)pq('#foo');

Ausgabe:

<script type="text/x-jquery-tmpl" id="foo">
<td>test
</script>

html5lib (Pässe)

Möglicherweise vielversprechend. Kann ich an den Inhalt des script#foo Tag?

Quelle:

<?php

header('Content-type: text/plain');

include 'HTML5/Parser.php';

$html = "<!DOCTYPE html><html><head></head><body><script id='foo'><td></td></script></body></html>";
$d = HTML5_Parser::parse($html);

echo $d->saveHTML();

Ausgabe:

<html><head></head><body><script id="foo"><td></td></script></body></html>

1 Stimmen

Hinweis: Wenn Sie versuchen, HTML über loadHTML zu parsen, verwenden DOM-basierte Bibliotheken das HTML-Parser-Modul von libxml. Wenn Sie Ihr obiges Snippet stattdessen mit loadXML laden, treten keine Fehler auf, aber natürlich wird erwartet, dass die Seite dann gültiges XHTML ist. Siehe auch Beste Methoden zum Parsen von HTML aber im Grunde werden alle DOM-basierten Parser hier wahrscheinlich die gleichen Ergebnisse liefern.

0 Stimmen

+1 für eine gute Frage. Ich frage mich, ob es möglich wäre, HTML-Kommentare oder einen CDATA-Block zu verwenden, um den Code im Skript-Tag abzugrenzen, wie man es bei Javascript tun würde? Oder würde das auch in die Ausgabe der Vorlage aufgenommen werden?

0 Stimmen

Wenn html5lib angenommen wird, ist das dann nicht die Antwort auf diese Frage?

10voto

Alex Punkte 65208

Ich hatte das gleiche Problem und anscheinend kann man sich einen Weg durch dieses Problem bahnen, indem man das Dokument als XML lädt und es als HTML speichert :)

$d = new DOMDocument;
$d->loadXML('<script id="foo"><td>bar</td></script>');
echo $d->saveHTML();

Aber natürlich muss das Markup fehlerfrei sein, damit loadXML funktioniert.

1 Stimmen

Beachten Sie auch, dass dies auf HTML5-Elemente, die nicht selbst schließen (Link, img, br, etc.), da diese in XML illegal sind brechen.

7voto

Ich finde es einfach heraus (in meinem Fall).

versuchen, die Parameter zu ändern Option von loadHTML mit LIBXML_SCHEMA_CREATE en DOMDocument

$dom = new DOMDocument;

libxml_use_internal_errors(true);
//$dom->loadHTML($buffer, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$dom->loadHTML($buffer, LIBXML_SCHEMA_CREATE);

1 Stimmen

Damit war es eigentlich erledigt. Gibt es Nebenwirkungen/Einschränkungen?

5voto

Alan Storm Punkte 160579

Re: html5lib

Sie klicken auf die Registerkarte "Download" und die PHP-Version des Parsers herunterladen .

Sie entpacken das Archiv in einen lokalen Ordner

 tar -zxvf html5lib-php-0.1.tar.gz
 x html5lib-php-0.1/
 x html5lib-php-0.1/VERSION
 x html5lib-php-0.1/docs/
 ... etc

Sie wechseln das Verzeichnis und erstellen eine Datei namens hello.php

cd html5lib-php-0.1
touch hello.php 

Sie platzieren den folgenden PHP-Code in hello.php

$html = '<html><head></head><body>
<script type="text/x-jquery-tmpl" id="foo">
<table><tr><td>${name}</td></tr></table>
</script> 
</body></html>';
$dom = HTML5_Parser::parse($html); 
var_dump($dom->saveXml()); 
echo "\nDone\n";

Sie laufen hello.php über die Befehlszeile

php hello.php

Der Parser parst den Dokumentenbaum und gibt ein DOMDocument-Objekt zurück, das wie jedes andere DOMDocument-Objekt bearbeitet werden kann.

0 Stimmen

Danke für die Hinweise. Wie kann ich den Inhalt des Skript-Tags auffinden, indem ich nach der ID suche?

1 Stimmen

Es handelt sich um ein Standard-DOMDocument-Objekt. Wenn Sie mit dem DOMDocument nicht zurechtkommen, rufen Sie die saveXML-Methode (wie oben) auf und erstellen Sie daraus ein SimpleXml-Objekt. Wenn Sie mit Simple XML nicht vertraut sind, sollten Sie <a href=" us.php.net/manual/de/simplexml.examples-basic.php">lesen das Handbuch</a>

0 Stimmen

Html5lib hinzugefügt zu Beste Methoden zum Parsen von HTML

5voto

ThW Punkte 17997

FluentDOM verwendet das DOMDocument, blockiert aber Ladehinweise und Warnungen. Es hat keinen eigenen Parser. Sie können Ihre eigenen Lader hinzufügen (zum Beispiel einen, der die html5lib verwendet).

3voto

alex Punkte 457905

Ich habe Kommentar-Tags hinzugefügt ( <!-- ... --> ) in meinen jQuery-Vorlagenblöcken (CDATA-Blöcke schlugen ebenfalls fehl) und DOMDocument berührte das interne HTML nicht.

Bevor ich dann die jQuery-Vorlagen verwendete, schrieb ich ein Skript, um die Kommentare zu entfernen.

$(function() {
    $('script[type="text/x-jquery-tmpl"]').text(function() {
        // The comment node in this context is actually a text node.
        return $.trim($(this).text()).replace(/^<!--([\s\S]*)-->$/, '$1');
    });
});

Nicht ideal, aber ich wusste keine bessere Lösung.

1 Stimmen

Ich meine... ich verwende <% %> Tags (für Unterstrich Templating) und kommentieren es funktioniert nicht. Ich würde gerne verhindern, dass XMLDocument Skript innere Texte/htmls parsen

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