XML 常被形容成过时,这很奇怪,因为你今天几乎肯定打开过好几个 XML 文件而没有察觉。它确实输掉了“在程序之间传数据”那场争论——JSON 赢得很彻底。其余的它都守住了。
XML 是 Extensible Markup Language(可扩展标记语言)的缩写。它长得像 HTML,但有一个关键差别:HTML 的标签是固定的、已经帮你定义好的,而在 XML 里标签是你自己发明的。
<book>
<title>西游记</title>
<year>1592</year>
</book>
没有任何东西事先定义了 <book>。这个格式给你语法——标签、嵌套、属性——而词汇由你依数据所需提供。
.docx 是一个装满 XML 的 zip 归档;文字、格式和结构全部都是里面的 XML 文件。那不是一份遗产清单。那是 XML 被证明选对了的地方。
这是分界的核心,而且一个例子就能解释整个局面。
想想一个中间带强调的句子:那只敏捷的棕狐,其中只有“敏捷”是斜体。在 XML 里这很自然:
<p>那只<em>敏捷的</em>棕狐</p>
文字和标记交错在一起——XML 把这叫做混合内容。那个元素里装了一些文字,然后一个元素,然后又是文字。
JSON 没有任何办法表达这个。它的值只能是字符串、数字、列表或对象;它没有“文字,而且在特定位置嵌着东西”这个概念。要在 JSON 里表示那个句子,得发明一套约定——一个片段的数组,每个片段标上它的样式——然后所有人都得同意你的发明。
文档就是由混合内容组成的。真实文档里几乎每一个句子里面都有被标记起来的东西。这就是为什么文字处理软件、电子书和页面排版是 XML,也是为什么它们会继续是 XML。
数据不是那样。价格是一个数字、名称是一个字符串、订单有一串商品。JSON 完美贴合那个,而 XML 只是多加了标点。
<book id="42">——附在元素上而不是放在它里面的元数据。<!-- 像这样 -->。JSON 完全没有,这在配置文件里是真实的不便。XML 比 HTML 严格得多,也远没那么宽容:
<br> 无效;<br/> 才对。<Book> 和 <book> 是不同的元素。然后是那个造成的坏 XML 比其他全部加起来还多的:& 符号。
有五个保留字符,而 & 是危险的那个,因为它在网址里不断出现。一个带参数的网址在参数之间含有 &,而原封不动贴进 XML 会立刻让文件失效。它必须写成 &。
这就是一份 sitemap 或 RSS 订阅源被验证器拒绝的常见原因:某个链接里一个没转义的 & 符号。另外四个是 <、>、" 和 ',分别写成 <、>、" 和 '。
对一整块充满这类字符的文字,<![CDATA[ ... ]]> 标出一个解析器应该照字面处理的区域——那是把 HTML 放进 RSS 订阅源的标准做法。
不像 CSV,XML 把编码问题好好解决了。第一行就声明它:
<?xml version="1.0" encoding="UTF-8"?>
文件自己说明它是什么,所以没有东西需要猜,而中文或日文内容在系统之间搬移也活得下来。这是一件小事,但它消掉了一整类的失败。
XML 很啰嗦——每个值都被一个开标签和一个闭标签包起来,往往还挂着命名空间。对一个每秒被调用一千次的 API 来说那是纯粹的浪费,而 JSON 是正确答案。
但对一份必须在三十年后还读得懂、必须能对照一份公布的标准被验证、而且必须被两个从没讲过话的组织完全一致地解读的文档来说,那个啰嗦是在做事。文件自我描述、模式定义什么是合法的,而没有任何东西依赖一个从来没被写下来的共同假设。
这就是值得记住的分界:JSON 给流动中的数据,XML 给必须存续的文档。
& 就会毁掉文件——写成 &,网址里尤其要注意