笔者在做RSS订阅时,发现了部分订阅链接在浏览器上打开后显示乱码。并且经过测试后,发现这个问题并非编码错误那么简单。遂做记录

最让人熟知的application/*+xml应该是两种流行的RSS订阅格式:application/rss+xml和application/atom+xml

事先说明,因为xml作为rss的中间载体,不会直接面向最终用户,所以不管浏览器怎么显示这个xml都无所谓,只要RSS订阅器能正确解析xml即可,从这个角度讲,讨论没有意义。所以本文的重点在于分析为什么2025年了,浏览器显示xml还会出现乱码

所有数据都在chrome和edge(都基于 Chromium)上测试,Firefox因为会直接把此类MIME直接下载为文件而排除在外

我们拿几个rss链接来测试,并取出其响应头的Content-Type

RSS源链接Content-Type测试结果
阮一峰的网络日志http://www.ruanyifeng.com/blog/atom.xmlapplication/xml
IT之家https://www.ithome.com/rss/text/xml; charset=utf-8
小众软件https://feeds.appinn.com/appinns/application/rss+xml; charset=utf-8
腾讯安全响应中心https://security.tencent.com/index.php/feed/blog/0application/rss+xml乱码

其中只有腾讯安全响应中心的显示内容是乱码,如下图所示,xml中已经指定了编码为utf-8

2025-07-08 13 26 41.png

从上面表格一对比,貌似问题不是出在xml上,而是响应头Content-Type内容少了charset编码

通过本地Python+Bottle进行模拟测试得到如下结果

的确通过添加charset编码可以解决

2025-07-08 14 34 31.png

那这里问题就来了,在Content-Type缺少编码的情况下,为什么浏览器不会从xml去获取编码?
如果细心留意,可以发现,其实application/rss+xml类型的响应内容,并不会被浏览器认为是xml,而是当成了纯文本进行展示
我们可以通过一个真正的xml去对比

2025-07-08 14 45 43.png

看到了吗?所以MIME=application/rss+xml的响应内容,就算是规范的XML,里面写的编码,都被浏览器当做纯文本展示

那是不是rss+xml这个标准的实现有问题?经过查询,尽管RSS规范(https://www.rssboard.org/rss-mime-type-application.txt)约定rss的MIME为pplication/rss+xml,但是在MIME的标准(https://www.iana.org/assignments/media-types/media-types.xhtml)里,并没有找到,也就是MIME目前还不认可rss+xml。问题会在这里么?
并不是,因为在MIME的标准里,有atom+xml这一类型,我使用Python+bottletom+xml类型进行了测试,发现结论和rss+xml完全一致

所以真正的问题在于浏览器对*+xml的实现,浏览器并不把基于xml进行数据格式规约的*+xml当做xml,可能是基于XMl扩展类型太多(光MIME已规范的就有452种),其中部分还包含可执行代码(比如xml-patch+xml),这会导致安全隐患。所以对于XHTML+XML、XML两者外的其他XML扩展,一律当纯文本展示

经过多组组合测试,结论如下

对于响应头是application/xml的,浏览器可以完美进行解码。
但是对于application/*+xml,浏览器按纯文本展示。而上文说的那个乱码,即是浏览器猜测编码不对导致的。所以如果要用*+xml,一定要传递编码,如application/atom+xml;charset=utf-8,才能避免浏览器猜错编码导致乱码

2025-07-08 15 10 35.png

这里顺带提一下Opera,现在的Opera同样基于Chromium开发,同时它自身支持RSS订阅(会把RSS订阅链接解析成新闻加入到个人化新闻页面中)
Opera不支持解析rss+xml和atom+xml,只支持xml(即content-typeapplication/xml

最让人绷不住的是,Opera解析XML乱成一锅粥。下面分别是用不同编码数据流,响应头指定编码,XML指定编码,只有数据流编码=GBK和XML编码encoding='GBK'同时满足时才不会出现乱码,其他编码,要不就是标题乱码,要不就是内容乱码,再不就是全部乱码。

2025-07-08 16 05 48.png