📘 第十章 构建Web内容的技术
📄 一句话概括

XML 是「标签名自己起」的标记语言:<book>、<price> 都行,不用等标准组织批准。 但语法必须严格——一个标签没闭合,整篇都不认。

📝 本节和前面几节的关系

上一节讲的是「给浏览器看的标记」。 这一节讲「给程序传数据用的标记」,它和 HTML 长得像,脾气正好相反。

一、标签可以自己发明

HTML 的标签是定死的:<h1>、<p>、<li> 就那么些,你不能发明一个 <价格> 让浏览器认。 XML 反过来:标签名随你起,只要成对、只要嵌套合法。 所以你能写出 <书><书名>图解 HTTP</书名><作者>上野宣</作者></书> 这种东西,而它确实是合法的 XML。 这就是「可扩展」三个字的意思:结构由你来定,语法由规范来定。 规范只管「尖括号怎么配对」,不管「book 里该有什么」。

二、严格在哪

Demo 里那段 XML 有 9 个元素、最大深度 3 层、共 310 字节,解析得干干净净。 把其中一个 </title> 删掉再解析,直接报错:mismatched tag: line 1, column 27。 整篇都不认,没有「尽量猜」这回事。 同样的写法放进 HTML(<p>没闭合<p>第二段),HTML 的解析器照收不误,还乖乖认出了 4 个标签。 这就是两者最根本的分歧:XML 一个错就全篇不认,HTML 尽量猜你想写什么。 为什么 XML 要这么硬?因为它的用户是程序。程序没法「猜」,猜错了就是数据错乱。 宁可整篇拒绝,也不要给出一个半对的结果。

三、属性还是子元素

同一份数据在 XML 里至少有两种装法:<book id="b1"> 把编号放属性里, 或者 <id>b1</id> 放子元素里。规范不告诉你该用哪种。 这是 XML 的灵活,也是它后来被嫌啰嗦的原因——每个项目都要自己定一套约定,然后写文档、 写校验规则(DTD 或 XSD),不然对方根本猜不到你的结构。 Soap、WSDL 那一代企业级接口就是这么堆起来的:功能很全,但一个简单请求能写出几十行 XML。 这套东西今天还在银行和电信的系统里跑着。

四、动手 Demo:解析一段 XML,再故意弄坏它

写一段书目 XML,用 Python 自带的 ElementTree 解析,数元素、数深度、取字段; 然后把一个闭合标签删掉再解析,看它怎么报错。最后用 HTML 解析器吃同样的「坏」写法,对比两者的态度。

root = ET.fromstring(XML_DOC)
books = root.findall(u'book')
for b in books:
    print(b.get(u'id'), b.find(u'title').text)

# 少一个闭合标签
ET.fromstring(u'<library><book><title>没闭合</book></library>')
# ParseError: mismatched tag

实跑输出:

--------------------------------------------------------------------
XML:严格的那一套
--------------------------------------------------------------------
  编号     书名                 作者         年份
  b1     图解 HTTP            上野宣        2014
  b2     今夜ワカルHTTP          上野宣        2013

  根元素                     library
  元素总数                   9 个
  最大深度                   3 层
  book 的个数                2 个
  每个 book 的属性           id、lang
  整个文档                   310 字节

  注意 `id` 和 `lang` 放在属性里,`title`、`author` 放在子元素里——
  同一份数据在 XML 里有两种装法,规范不告诉你该用哪种,全看约定。
  这是 XML 的灵活,也是它后来被嫌啰嗦的原因之一。

  一个有标签没闭合的文档     解析直接失败
  报错:mismatched tag: line 1, column 27

  同样的写法放进 HTML        照解析,认出 4 个标签
  它认出的是                 html/body/p/p

  一句话总结两者:**XML 一个错就全篇不认,HTML 尽量猜你想写什么。**

两个 book 都取出来了,id 从属性拿,title 从子元素拿——同一份数据两种装法并存,解析器都认。 元素总数 9 个、最大深度 3 层、整篇 310 字节。就这么点数据,标签占了一大半。 坏文档报的是 mismatched tag,位置精确到第 1 行第 27 列。 XML 的报错一向这么具体,因为它假定你是程序,需要准确定位。 同样的「坏」写法给 HTML 解析器,它认出 html/body/p/p 四个标签,一句怨言都没有。 这就是「严格」与「容错」的实测对比。

30 秒实验

  1. 把 id 从属性改成子元素,看解析代码要改哪几行。
  2. 给 XML 加一行 <?xml-stylesheet?>,想想它和 HTML 的 <link> 有什么相似。
  3. 想一想:为什么配置文件(比如 Maven 的 pom.xml)今天还在用 XML?

常见误区

  1. 「XML 就是 HTML 的升级版」——两者用途不同,一个传数据一个写页面。
  2. 「XML 比 HTML 严格所以更好」——严格适合机器,容错适合人,看用途。
  3. 「XML 已经过时了」——数据交换上确实被 JSON 顶掉了,但配置和企业接口还在用。
自测三问(点开对答案) 1. XML 的「可扩展」指的是什么? —— 标签名由使用者自己定义,规范只管语法不管结构。 2. XML 和 HTML 对错误的处理有什么不同? —— XML 一个错整篇拒绝,HTML 尽量容错继续解析。 3. 为什么 XML 要这么严格? —— 它的使用者是程序,猜错就是数据错乱,宁可整篇拒绝。

XML 最典型的一个用途,就是让程序读「这个站点最近更新了什么」。

相关笔记