simplexml_load_file 和 simplexml_load_string 以不同的编码返回相同的数据

simplexml_load_file and simplexml_load_string return the same data with different encoding

提问人:Math 提问时间:8/4/2023 最后编辑:A.LMath 更新时间:8/4/2023 访问量:58

问:

尝试从 URL 解析 UTF-8 RSS 提要,我首先尝试了这个:

$flux = simplexml_load_file("https://mamanslouves.com/feed");
foreach($flux->channel->item as $Item){
        $title      = $Item->title;
        echo $title;
}

此代码有效,但包含重音符号 (éèà) 的标题将转换为另一个字符集。 以下代码似乎解决了该问题:

$raw = file_get_contents("https://mamanslouves.com/feed");
$flux = simplexml_load_string($raw);
foreach($flux->channel->item as $Item){...}

我想知道为什么。

php rss simplexml

评论

1赞 Markus Zeller 8/4/2023
file_get_contents() 是二进制安全的,而 simplexml_load_file() 可以进行内部转换。
1赞 KIKO Software 8/4/2023
您能@MarkusZeller解释一下这对这个问题意味着什么吗?是否进行“内部转换”?哪个,为什么?它不是完全兼容 UTF-8 吗?simplexml_load_file()
2赞 Markus Zeller 8/4/2023
@KIKOSoftware 做一个,你会看到“文件”是作为提要本身包含的谎言。pastebin.com/8MhAGYtvcurl -vvv -i https://mamanslouves.com/feedcontent-type: text/html; charset=iso-8859-1encoding="UTF-8"
2赞 KIKO Software 8/4/2023
@MarkusZeller啊,我确实检查了文件,但使用的是普通浏览器。我首先得到 2 个重定向,首先是 ,记下域,然后是 ,最后我得到了下载本身。后者的 HTTP 标头是 ,所以我很满意,但仔细检查后,我发现第一个重定向使用 .我没有发现这一点。我可以确认这是原因,因为使用显示正常的重音字母。www.mamanslouves.org/feedwww.mamanslouves.org/feed/Content-Type application/rss+xml; charset=UTF-8content-type text/html; charset=iso-8859-1simplexml_load_file("https://mamanslouves.org/feed/");
1赞 KIKO Software 8/4/2023
我不知道谁拥有,但它显然在标题中发出了错误。你可以要求他们纠正这一点吗?这是一个很好的问题,让我咬牙切齿。mamanslouves.comcharset

答:

0赞 KIKO Software 8/4/2023 #1

通过讨论,我在评论中与 MarkusZeller 进行了讨论,我认为答案应该包含 2 个组成部分。

首先,我们需要查看您正在使用的 URL。它不是您最终下载的文件的 URL。在浏览器开发人员工具的“网络”选项卡中查看一下,如下所示:

enter image description here

首先,在下载 RSS 源本身之前,有两个永久重定向 (301)。一切都经过编码,XML 甚至您下载的文件。唯一不是的是第一个重定向,它是编码的。您可以通过检查网络选项卡中的标头来查看这一点。UTF-8UTF-8iso-8859-1

然后我们需要考虑什么。它需要弄清楚它下载的文件的编码。它可以从许多位置获取编码:重定向的 HTTP 标头、源的 HTTP 标头或 XML 内容。现在很清楚,它使用它遇到的第一件事:第一个重定向的 HTTP 标头,上面写着 .所以,真正被解读为什么,从那里开始一切都出错了。然后将误读的字符转换为 ,但正如您所看到的,这毫无意义。simplexml_load_file()iso-8859-1UTF-8iso-8859-1UTF-8

为了证明第一次重定向中的错误搞砸了事情,您可以在没有重定向的情况下获取提要:charset

$flux = simplexml_load_file("https://mamanslouves.org/feed/");
foreach($flux->channel->item as $Item){
        $title = $Item->title;
        echo $title;
}

这确实返回了正常的重音字母。

之所以通过确实有效,是因为这个函数不关心 ,它只是给你二进制数据,然后被解释为一个字符串。正如马库斯所说。file_get_contents()charsetUTF-8