12

我从其他地方搜索和处理 XML 文件,并且需要使用一些 XSLT 对其进行转换。没问题。使用 PHP5 和 DOM 库,一切都变得轻而易举。工作正常,到现在为止。今天,时髦的字符出现在 XML 文件中——看起来像是来自 Word 的“智能”引用。无论如何, DOMDocument->load 抱怨它们,说它们不是 UTF-8,并指定编码。

瞧,这些 XML 文件中没有指定编码。如果我将 'encoding="iso-8859-1"' 添加到标题中,它可以正常工作。问题是我无法控制这些 XML 文件。

将文件读入字符串、修改其标题并将其写回另一个位置似乎是我唯一的选择,但我更愿意这样做,而根本不必使用 XML 文件的临时副本。有什么方法可以简单地告诉解析器解析它们,就好像它们是 iso-8859-1 一样?

4

3 回答 3

10

这对你有用吗?

$doc = new DOMDocument('1.0', 'iso-8859-1');
$doc->load($xmlPath);

编辑:由于这似乎不起作用,您可以做的与您现有的方法类似,但没有临时文件。仅使用标准 IO 操作(或其他东西)从您的源中读取 XML 文件file_get_contents(),然后对您需要的编码进行任何更改(iconv()utf8_decode()),然后使用loadXML()

$myXMLString = file_get_contents($xmlPath);
$myXMLString = utf8_decode($myXMLString);
$doc = new DOMDocument('1.0', 'iso-8859-1');
$doc->loadXML($myXMLString);
于 2009-08-13T00:48:30.270 回答
5

我还没有找到设置默认编码的方法(还),但在这种情况下恢复模式可能是可行的。
当 libxml 遇到编码错误并且没有明确设置编码时,它会从 unicode/utf8 切换到 latin1 并继续解析文档。但在解析器上下文中,该属性wellFormed设置为 0/false。wellFormed如果为真DOMDocument 对象的属性为真,PHP 的 DOM 扩展认为文档有效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 时出现一次)。此特定错误的错误代码将为 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";
    }
}
于 2009-08-13T13:48:44.917 回答
2

指定编码的唯一方法是在文件开头的 XML 声明中:

<?xml version="1.0" encoding="ISO-8859-1"?>
于 2013-11-26T13:43:23.223 回答