デフォルトのエンコーディングを設定する方法は(まだ)見つかりませんが、この場合はリカバリモードが実行可能かもしれません。
libxmlでエンコードエラーが発生し、エンコードが明示的に設定されていない場合、libxmlはunicode / utf8からlatin1に切り替わり、ドキュメントの解析を続行します。ただし、パーサーコンテキストでは、プロパティwellFormed
は0/falseに設定されます。wellFormed
PHPのDOM拡張機能は、 trueまたはDOMDocumentオブジェクトの属性がtrueの場合、ドキュメントを有効と見なしrecover
ます。
<?php
// german Umlaut ä in latin1 = 0xE4
$xml = '<foo>'.chr(0xE4).'</foo>';
$doc = new DOMDocument;
$b = $doc->loadxml($xml);
echo 'with doc->recover=false(default) : ', ($b) ? 'success':'failed', "\n";
$doc = new DOMDocument;
$doc->recover = true;
$b = $doc->loadxml($xml);
echo 'with doc->recover=true : ', ($b) ? 'success':'failed', "\n";
プリント
Warning: DOMDocument::loadXML(): Input is not proper UTF-8, indicate encoding !
Bytes: 0xE4 0x3C 0x2F 0x66 in Entity, line: 1 in test.php on line 6
with doc->recover=false(default) : failed
Warning: DOMDocument::loadXML(): Input is not proper UTF-8, indicate encoding !
Bytes: 0xE4 0x3C 0x2F 0x66 in Entity, line: 1 in test.php on line 11
with doc->recover=true : success
警告メッセージ(@ $ doc-> load()で抑制できます)が表示され、内部libxmlエラーにも表示されます(パーサーがutf8からlatin1に切り替わるときに1回だけ)。この特定のエラーのエラーコードは9(XML_ERR_INVALID_CHAR)になります。
<?php
$xml = sprintf('<foo>
<ae>%s</ae>
<oe>%s</oe>
&
</foo>', chr(0xE4),chr(0xF6));
libxml_use_internal_errors(true);
$doc = new DOMDocument;
$doc->recover = true;
libxml_clear_errors();
$b = $doc->loadxml($xml);
$invalidCharFound = false;
foreach(libxml_get_errors() as $error) {
if ( 9==$error->code && !$invalidCharFound ) {
$invalidCharFound = true;
echo "found invalid char, possibly harmless\n";
}
else {
echo "hm, that's probably more severe: ", $error->message, "\n";
}
}