PHP 中的错误? : XMLReader::readOuterXml 当输入为 UTF-8 时生成 "Input is not proper UTF-8"

Bug in PHP? : XMLReader::readOuterXml generate "Input is not proper UTF-8" when input IS UTF-8

我想我在 PHP 5.5.33 和 5.6.19 的 XMLReader::readOuterXML 中发现了一个错误... PHP 5.2.17 没问题,没有用 7 测试。我的 PHP 是 VC11 x86 线程安全,Apache 2.4.18 VC11 Win32。

当读取以 UTF-8(有或没有 BOM)正确编码的 XML 文件时,readOuterXML 有时会生成警告 "Input is not proper UTF-8, indicate encoding !",即使有几个 UTF-8 编码的字符在违规行之前阅读。

删除了一些标签或字符串的同一个文件将毫无问题地通过。

这是我用来读取 XML 文件的函数的简化版本:

function TestXML($file) {
    $XR = new XMLReader;
    $XR->open($file, null, LIBXML_NOBLANKS);

    //Looking for specific node
    while (($lastRead = $XR->read()) && ($XR->name !== 'records')) {
        ;
    }

    if (!$lastRead) {
        echo $file.' : Invalid file or no records';
        $XR->close();
        return;
    }

    //Looking for specific node
    while (($lastRead = $XR->read()) && ($XR->name !== 'record')) {
        ;
    }
    while ($lastRead) {

        $xml = $XR->readOuterXML();
        if ($xml === '') {
            $err = '';
            if ($e = libxml_get_last_error()) {
                $err = $e->message.' (line: '.$e->line.')';
            }
            $XR->close();
            echo $file.' : Problem with file'.($err ? ' — '.$err : '').'.';
            return;
        }

        //Looking for specific node
        while (($lastRead = $XR->next()) && ($XR->name !== 'record')) {
            ;
        }
    }
    $XR->close();
    echo $file.' : Good!';
    return;
}

这是我能生产的最小的 XML(没有 BOM)会产生问题:

<?xml version="1.0" encoding="utf-8"?>
<records>

<record><aaa><bbbb><ccc><![CDATA[XXX Xxxxxxxxxxxx]]></ccc><ddd><![CDATA[XXX Xx]]></ddd></bbbb><eee><![CDATA[Xxxxx xxxxxxx: xxxx://xxx.xxx.xx.xx/xxxx?xxxxXx=0xx000x0-000x-0xx0-x000-x0000xx0xx00
Xxxxxxxxxxxx xx Xxxxxxxxxxxx Xxxxxxxxx xx Xxxxxxxxx Xxxxxxxxxxxx Xxxxxxxxxxx Xxxxxxxxxxxx (XXX Xxxxxxxxxxxx), xxxxxxxxx xxxxxxx xx Xxx Xxxxxxxxxx Xxxxxxxxxx Xxx.]]></eee></aaa><fff><bbbb><ggg><![CDATA[Xxxxxxxxx Xxxxxxxxxxxxxxx Xxxxxxxxxx xx Xxxxxxxxxxxx]]></ggg><ccc><![CDATA[XXX Xxxxxxxxxxxx]]></ccc></bbbb><hhh><![CDATA[Xx xxxxx, xx xxxxxxxxxxx XXX Xxxxxxxxxxxx x xxxxxcé x’xxxxxxxx xxx x’Xxxxxxléx léxxxxxxxxx xx xx xxxxxxxx xx xx Xxxxxxxxxx Xxxxxxxxxx Xxx (xxx xxx xx xxxxxxxxxx xxxxxxxxx). Xxxxx xxx xréxxxx xxx xxxxxx xxx déxxxxxxxx XXX Xxxxxxxxxxxx xx xxxx xx’xxxxxxxxxxxx xxxxxxxxxxxxxxx xxxxréxxxxxxtéx xx xxxxxxx xxx XX, xxx XXX xx xxx XXX xx xx xxxxxxxx xx xxxxx x’xxxxxxxx xx xxxxx xx xxxxxxxxx xxxxxxxxxxxxx xxréé (XXX). (Xxxxxxxxéx XXX - Xxx 0000)]]></hhh></fff></record>

</records>

由于问题可以通过添加几个空格来解决(例如,如果上面是美化的,它不会造成问题),我上传了我用于测试的文件:

Bad file(无 BOM)
Bad file(从 <ggg> 标签的内容中删除了 BOM 和一对 'x')
Good file(与 Bad 相同,减去了 <ccc> 标签)。
您还可以从 Bad 文件中删除几个 'words',它将通过。

那么,这真的是 PHP 中的错误还是我只是遗漏了什么?

这是一个与 libxml2 相关的错误。 将此库从 URL 升级到最新版本: https://git.gnome.org/browse/libxml2/

只是为了结束这个问题:正如我在 中提到的,这是 PHP 中的一个错误,最近已修复。据我所知,受影响的 PHP 版本是 5.5.32、5.5.33、5.5.34、5.5.35、5.6.18、5.6.19、5.6.20 和 5.6.21。

修复了安装 libxml2-devsudo apt-get install libxml2-dev