まず、私のデータベースはネイティブ文字セットとしてWindows-1250を使用しています。データをUTF-8として出力しています。Webサイト全体でiconv()関数を使用して、Windows-1250文字列をUTF-8文字列に変換していますが、これは完璧に機能します。
問題は、PHP DOMを使用してデータベースに格納されているHTMLを解析している場合です(HTMLはWYSIWYGエディターからの出力であり、無効であり、html、head、bodyタグなどがありません)。
HTMLは次のようになります。次に例を示します。
<p>Hello</p>
データベースから特定のHTMLを解析するために使用する方法は次のとおりです。
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];
}
上記のメソッドからの出力は、すべての特殊文字がÚÄ�のような奇妙なものに置き換えられたゴミです。
もう一つ。それは私の開発サーバーで動作します。
ただし、本番サーバーでは機能しません。
助言がありますか?
本番サーバーのPHPバージョン:PHPバージョン5.2.0RC4-dev
開発サーバーのPHPバージョン:PHPバージョン5.2.13
アップデート:
私は自分で解決策に取り組んでいます。このPHPバグレポートからインスピレーションを得ています(実際にはバグではありません): http://bugs.php.net/bug.php? id = 32547
これが私の提案する解決策です。明日試してみて、うまくいくかどうかお知らせします。
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];
}