PHP DOM UTF-8 problem
Zunächst, meine Datenbank verwendet, Windows-1250 als einheitlichen charset. Ich bin die Ausgabe der Daten als UTF-8. Ich bin mit iconv () - Funktion auf meiner website zum konvertieren von Windows-1250-strings in UTF-8-strings, und es funktioniert perfekt.
Das problem ist wenn ich mit PHP DOM parse HTML in der Datenbank gespeichert (der HTML-Code wird eine Ausgabe von einem WYSIWYG-editor und ist nicht gültig, hat es keine html -, head -, body-tags etc).
Den HTML könnte so Aussehen, beispielsweise:
<p>Hello</p>
Hier ist eine Methode, die ich verwenden, um zu analysieren, eine bestimmte HTML aus der Datenbank:
private function ParseSlideContent($slideContent)
{
var_dump(iconv('Windows-1250', 'UTF-8', $slideContent)); //this outputs the HTML ok with all special characters
$doc = new DOMDocument('1.0', 'UTF-8');
//hack to preserve UTF-8 characters
$html = iconv('Windows-1250', 'UTF-8', $slideContent);
$doc->loadHTML('<?xml encoding="UTF-8">' . $html);
$doc->preserveWhiteSpace = false;
foreach($doc->getElementsByTagName('img') as $t) {
$path = trim($t->getAttribute('src'));
$t->setAttribute('src', '/clientarea/utils/locate-image?path=' . urlencode($path));
}
foreach ($doc->getElementsByTagName('object') as $o) {
foreach ($o->getElementsByTagName('param') as $p) {
$path = trim($p->getAttribute('value'));
$p->setAttribute('value', '/clientarea/utils/locate-flash?path=' . urlencode($path));
}
}
foreach ($doc->getElementsByTagName('embed') as $e) {
if (true === $e->hasAttribute('pluginspage')) {
$path = trim($e->getAttribute('src'));
$e->setAttribute('src', '/clientarea/utils/locate-flash?path=' . urlencode($path));
} else {
$path = end(explode('data/media/video/', trim($e->getAttribute('src'))));
$path = 'data/media/video/' . $path;
$path = '/clientarea/utils/locate-video?path=' . urlencode($path);
$width = $e->getAttribute('width') . 'px';
$height = $e->getAttribute('height') . 'px';
$a = $doc->createElement('a', '');
$a->setAttribute('href', $path);
$a->setAttribute('style', "display:block;width:$width;height:$height;");
$a->setAttribute('class', 'player');
$e->parentNode->replaceChild($a, $e);
$this->slideContainsVideo = true;
}
}
$html = trim($doc->saveHTML());
$html = explode('<body>', $html);
$html = explode('</body>', $html[1]);
return $html[0];
}
Die Ausgabe aus der Methode oben ist ein Müll mit allen Sonderzeichen ersetzt, mit seltsamen Sachen wie ÚÄ�.
Eine weitere Sache. Es funktioniert auf meinem Entwicklungs-server.
Funktioniert es nicht auf dem Produktions-server obwohl.
Irgendwelche Vorschläge?
PHP-version des production-Servers: PHP-Version 5.2.0RC4-dev
PHP-version der Entwicklungs-server: PHP Version 5.2.13
UPDATE:
Ich arbeite an einer Lösung selber. Ich habe eine inspiration aus dieser PHP-bug-report (nicht wirklich ein bug aber): http://bugs.php.net/bug.php?id=32547
Dies ist meine vorgeschlagene Lösung. Ich werde versuchen, es morgen und lassen Sie wissen, ob es funktioniert:
private function ParseSlideContent($slideContent)
{
var_dump(iconv('Windows-1250', 'UTF-8', $slideContent)); //this outputs the HTML ok with all special characters
$doc = new DOMDocument('1.0', 'UTF-8');
//hack to preserve UTF-8 characters
$html = iconv('Windows-1250', 'UTF-8', $slideContent);
$doc->loadHTML('<?xml encoding="UTF-8">' . $html);
$doc->preserveWhiteSpace = false;
//this might work
//it basically just adds head and meta tags to the document
$html = $doc->getElementsByTagName('html')->item(0);
$head = $doc->createElement('head', '');
$meta = $doc->createElement('meta', '');
$meta->setAttribute('http-equiv', 'Content-Type');
$meta->setAttribute('content', 'text/html; charset=utf-8');
$head->appendChild($meta);
$body = $doc->getElementsByTagName('body')->item(0);
$html->removeChild($body);
$html->appendChild($head);
$html->appendChild($body);
foreach($doc->getElementsByTagName('img') as $t) {
$path = trim($t->getAttribute('src'));
$t->setAttribute('src', '/clientarea/utils/locate-image?path=' . urlencode($path));
}
foreach ($doc->getElementsByTagName('object') as $o) {
foreach ($o->getElementsByTagName('param') as $p) {
$path = trim($p->getAttribute('value'));
$p->setAttribute('value', '/clientarea/utils/locate-flash?path=' . urlencode($path));
}
}
foreach ($doc->getElementsByTagName('embed') as $e) {
if (true === $e->hasAttribute('pluginspage')) {
$path = trim($e->getAttribute('src'));
$e->setAttribute('src', '/clientarea/utils/locate-flash?path=' . urlencode($path));
} else {
$path = end(explode('data/media/video/', trim($e->getAttribute('src'))));
$path = 'data/media/video/' . $path;
$path = '/clientarea/utils/locate-video?path=' . urlencode($path);
$width = $e->getAttribute('width') . 'px';
$height = $e->getAttribute('height') . 'px';
$a = $doc->createElement('a', '');
$a->setAttribute('href', $path);
$a->setAttribute('style', "display:block;width:$width;height:$height;");
$a->setAttribute('class', 'player');
$e->parentNode->replaceChild($a, $e);
$this->slideContainsVideo = true;
}
}
$html = trim($doc->saveHTML());
$html = explode('<body>', $html);
$html = explode('</body>', $html[1]);
return $html[0];
}
Sie haben versucht, die Methode save: $doc->speichern();
Ich werde es versuchen. Warten Sie einige Minuten.
InformationsquelleAutor Richard Knop | 2010-08-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dein "hack" ist nicht sinnvoll.
Sie konvertieren einer Windows-1250 HTML-Datei in UTF-8 und dann voranstellen
<?xml encoding="UTF-8">
. Das wird nicht funktionieren. Die DOM-Erweiterung für HTML-Dateien:Ich schlage vor, Sie stattdessen konvertieren von Windows-1250 in ISO-8859-1 und Schreibe nichts.
BEARBEITEN Der Vorschlag ist nicht sehr gut, denn die Windows-1250 hat Zeichen, die nicht in ISO-8859-1. Da Sie den Umgang mit Fragmenten, ohne
meta
- Elemente für den content-Typ, können Sie Ihre eigenen hinzufügen, um Kraft interpretation als UTF-8:gibt:
auch die erwähnt, die in der PHP-Dokumentation." Link bitte. Notizen sind nicht Teil der Dokumentation.
Es ist ein user-Kommentar hier (php.net/manual/en/domdocument.loadhtml.php). Es ist Dritten Kommentar von oben. Ich weiß, es ist nicht offiziell, aber es ist manchmal der einzige Weg. Dies ist nicht die einzige Zeit, die Windows-1250 + PHP-DOM-Kombination gibt mir Kopfschmerzen. Dennoch, ich schlief für eine Weile und ich habe eine Idee, wie man dieses Problem lösen (nicht sicher, es wil aber funktionieren). Ich werde versuchen, es morgen, wenn es nicht funktioniert werde ich wahrscheinlich beginnen, eine Prämie für diese Frage.
Ich habe eine Idee, was das problem sein könnte von hier: bugs.php.net/bug.php?id=32547, Aber ich gehe jetzt schlafen.
Wenn ich dieses Problem lösen werde ich wohl einen Kommentar hinzufügen, der in der PHP-Dokumentation zum ersten mal 😀
InformationsquelleAutor Artefacto
Zwei Lösungen.
Können Sie entweder die Kodierung als header:
Oder Ihr könnt es als META-tag:
EDIT: in dem Fall, dass diese beiden richtig gesetzt sind, tun Sie den folgenden:
Wenn Sie sicher sind, dass der richtige header gesendet wird, dann Ihre beste chance, den Fehler zu beginnen, raw-bytes. Gleichen bytes gesendet, um eine identische browser, erzielen Sie dasselbe Ergebnis, so dass Sie brauchen, um zu suchen, warum Sie nicht identisch sind. Fiddler/Wireshark helfen mit, dass.
Er erwähnt, dass es funktioniert auf seine Entwicklung-server, was bedeutet, dass es ist sehr wahrscheinlich, dass die bytes geschrieben richtig. Das wahrscheinlichste problem ist, dass die bytes nicht als Lesen richtig, und das sollte das beheben.
Der header wird korrekt gesendet. Es ist auch der richtige meta-tag.
Knop - Siehe Bearbeitungen.
Ok ich werde versuchen mit dem fiddler. Übrigens, ich denke, das problem wird verursacht, durch die PHP-DOM. Ich denke, es ist Unordnung auf dem Ost-europäischen UTF-8-Zeichen. Kennen Sie eine alternative zu PHP-DOM, das ich benutzen konnte, um die parse-HTML?
InformationsquelleAutor riwalk
Ich hatte das gleiche problem. Mein fix war mit notepad++ die Einstellung der Kodierung der php-Dokument "UTF-8 ohne BOM". Hoffe das hilft jedem der anderen.
InformationsquelleAutor user2494874