---
layout: post
title: 在Google杀死XSLT之后的XML美化方案
tags: [XML, Feed, XSLT, 美化]
---

  即使没有了XSLT，也不能让读者看到光秃秃的XML！<!--more-->   

# 起因
  在半年前，我写了一篇[用XSLT美化博客XML文件](/2025/07/01/xslt.html)的文章，自从那以后，每次我在浏览其他人博客的时候，都会看一眼对方博客有没有给自己的订阅文件做美化。不过就在前段时间，我在浏览某个博客的时候，发现他博客的订阅文件，甚至连最基本的XML文档树都没有显示出来。这时候我打开开发者工具看了一眼源代码，发现他也并没有使用`xml-stylesheet`之类的指令……而且控制台貌似报了些错，好像是出现了什么CSP错误……于是我就想，浏览器显示XML文档树的本质，会不会其实也是一种XSLT？之所以报错也有可能是浏览器在自动引用内置的XSLT时违反了CSP。所以我就问了问谷歌AI，结果似乎真的是这样，比如火狐浏览器就内置了一份[XSLT文件](https://github.com/mozilla-firefox/firefox/blob/main/dom/xml/resources/XMLPrettyPrint.xsl)，IE浏览器也有。正当我为XSLT的功能感到强大时，谷歌AI随后提到，[Chrome浏览器决定弃用XSLT](https://developer.chrome.com/docs/web-platform/deprecating-xslt)，所以以后不要再用XSLT了😰……   
  我给我的订阅文件加美化功能才半年，怎么就要不能用了？XSLT出现这么多年都还能用，结果等我加上就要废弃了？当时为了增加这个功能，还是费了不少劲的，怎么能让谷歌说没就没？于是我就开始对这件事进行了调查。   

# Google杀死了XSLT
  从上面Chrome的弃用XSLT文档中，可以发现，这件事的始作俑者是[Mason Freed](https://github.com/mfreed7)，他在WHATWG中发起了一个[Issue](https://github.com/whatwg/html/issues/11523)，因为XSLT用的人很少，以及实现XSLT的库很老而且容易出漏洞，所以建议把XSLT从Web标准中删除。在这个Issue中可以发现，有很多人表示不满，毕竟这个功能对想要给自己订阅做美化的博主来说还是很有用的。为了对抗谷歌，还有人做了个网站： <https://xslt.rip> 。   
  而且XSLT虽然用的人占比也许不高，但从总量上应该还是挺多的，除了用XSLT美化博客订阅的，甚至还有用[XSLT作为博客框架的](https://github.com/vgr-land/vgr-xslt-blog-framework)，另外还有一些人提出[一部分政府网站也有使用XSLT](https://github.com/whatwg/html/issues/11582)。   
  不过Freed看起来对这件事早有准备，他做了一个[Polyfill库](https://github.com/mfreed7/xslt_polyfill)，通过WASM的方式让XSLT可以正常工作，为了方便大家使用这个库，我顺手给CDNJS发了个[PR](https://github.com/cdnjs/packages/pull/2118)，以后可以用CDN引用它了。不过使用这个库的前提是需要在订阅中加一段引用JS的代码，像我博客中的Atom订阅，用的是[jekyll-feed](https://github.com/jekyll/jekyll-feed)插件，里面的格式都是写死的，就用不了了……   
  只不过现在已经没办法阻止谷歌了……而且其他浏览器也表示会跟进，看来我们唯一能做的就是去适应了。   
  
# 没有XSLT之后的美化方案
## 纯CSS
  虽然XSLT不能用，但不代表`xml-stylesheet`指令就不能用了，除了XSLT之外，`xml-stylesheet`同样可以引用CSS。只是似乎完全没见过用CSS美化订阅源的，也许是因为光用CSS能做到的事比较少吧，想用CSS给XML文档加链接之类的估计就做不到了。   
  但目前能选择的也不多了，既然大家都没写过用CSS美化订阅源，那就让我来写一个吧！然而我并不会写😅……那就只好让AI来写了，我把需求说清楚之后，AI就写出来了：[feed.css](/assets/css/feed.css)。试了一下效果还挺不错的，我让AI写的这个版本无论是RSS还是Atom都可以使用，如果有人感兴趣可以拿去用。可惜我的Atom订阅因为用的是插件的原因用不了😭，只能加到用纯Liquid实现的RSS订阅上了。   
  但用纯CSS的缺点也很明显，没办法操作文档的内容，像修改日期格式的就做不了了，而且也不能添加超链接……XML的标签本身对浏览器来说并没有内建的语义，正常情况下也没法让浏览器把某个标签当作超链接。那难道就没办法了吗？   
## 混合XHTML
  如果完全不能修改XML内容，那确实就没有办法了，但如果能修改XML的内容那还是有办法的，简单来说就是混入XHTML，事实上Freed编写的Polyfill库原理上也是利用了XHTML，只要在能作为XHTML的标签中添加XHTML的命名空间，那么浏览器就可以理解它的语义并渲染，像刚刚用纯CSS美化的订阅没有链接，那就可以在根元素中添加命名空间：`xmlns:xhtml="http://www.w3.org/1999/xhtml"`，然后在合适的位置写：   
```xml
<xhtml:a href="https://example.com">Read more -&gt;</xhtml:a>
```
  就可以了。只是这样有个缺点，这样写的订阅文件不够“纯粹”，用验证器验证会显示“[Misplaced XHTML content](https://validator.w3.org/feed/docs/warning/MisplacedXHTMLContent.html)”警告。对有洁癖的人来说可能会有点难受😆。   
  不过如果能接受这种“不纯粹”，那么其实`xml-stylesheet`指令也没必要了，`link`标签一样可以用，包括`script`也是，所以有人写了一个[不使用XSLT美化XML](https://github.com/dfabulich/style-xml-feeds-without-xslt)的库。   
  只不过这种方法和XSLT相比还是有一些缺陷，要知道XSLT的本质是转换，是把XML转换为HTML，也就是说转出来的文档本质是HTML，所有的DOM操作都和操作HTML是完全相同的，但是在XML里混入XHTML标签就不一样了，它的本质依然是XML文档，只是嵌入了XHTML命名空间下的元素，所以相应的DOM操作会有一些不同。如果是自己写的纯JS可能还好，如果是用了jQuery之类假定DOM为HTML的库就会出现问题了，因此这也就是那个Polyfill库的局限性，用正常的XSLT执行`document.constructor`会显示`HTMLDocument`，而用这个Polyfill库执行完则是显示`XMLDocument`。因此，直接套用为浏览器原生XSLT编写的旧样式文件，就有可能会出问题，但如果要考虑改XSLT的话那还不如重新写JS，然后用XHTML引入呢。   

# 感想
  虽然有一些技术会因为各种各样的原因消失，但这不代表我们就要妥协一些东西，总有一些不同的技术可以解决相同的问题，所以我们只需要用其他的技术去实现就好了。不过这也是没办法的事情，毕竟没人能改变浏览器厂商们的决策啊😂。