📄 一句话概括
两拨人各自发明了 <名称>,撞名怎么办?命名空间给标签加上【姓】——前缀背后是全局唯一的 URI,同名标签从此各归各家。
📝 本节和前面几节的关系
上一节说交换要靠统一的标签约定,可不同行业、不同公司撞名怎么办?本节解决 XML 世界里的重名问题。
一、重名为什么是问题
卖电脑的公司用 <名称> 表示商品名,另一部门用 <名称> 表示公司名;
两份文档一合并,两个 <名称> 语义完全不同,程序无法区分;
改名字能躲一时——行业标准一多,靠改名避让迟早用尽词汇。
二、命名空间的做法
用 xmlns 声明一个前缀指向的命名空间标识符:xmlns:商品="urn:shop";
此后 <商品:名称> 就是【姓商品的名字】,与 <公司:名称> 分属两个世界;
前缀只是给人看的简称——解析器内部把标签还原成 {urn:shop}名称 这样的完整形式;
标识符通常写成 URI(不要求真能访问),图的就是全局唯一:域名归各家自己管,天然不撞。
三、读法上的两处常见困惑
默认命名空间:写 xmlns="urn:a"(不带前缀)时,文档里所有无前缀标签都归它管辖;
前缀名可以随便起、不同文档里同一个 URI 可以用不同前缀——认 URI 不认前缀;
【⚠️ 2026 现状】所有现代 XML 方言都大量使用命名空间:打开任意 docx 解包可见 w:、r:、a: 等多个前缀并存。
四、动手 Demo:同名标签,各归各家
构造一份含两个 <名称> 的文档(一属商品、一属公司),用解析器读出两者的完整标签名。
import xml.etree.ElementTree as ET
xml = ('<报表>'
'<商品:名称 xmlns:商品="urn:shop">笔记本电脑</商品:名称>'
'<公司:名称 xmlns:公司="urn:corp">曦数科技</公司:名称>'
'</报表>')
for e in ET.fromstring(xml):
print(e.tag, "->", e.text)
实跑输出:
--------------------------------------------------------------------
可以为 XML 标签设定命名空间
--------------------------------------------------------------------
两个部门都用了 <名称> 标签: 一个是商品名, 一个是公司名——撞名了!
命名空间给标签加上【姓】, 前缀一写, 同名的两拨标签各归各家:
<报表>
<商品:名称 xmlns:商品="urn:shop">笔记本电脑</商品:名称>
<公司:名称 xmlns:公司="urn:corp">曦数科技</公司:名称>
</报表>
解析后(前缀被还原成完整命名空间):
{urn:shop}名称 -> 笔记本电脑
{urn:corp}名称 -> 曦数科技
写法 含义
---------------------------------------------------------------------
xmlns:商品="urn:shop" 声明前缀 商品 属于 urn:shop 命名空间
<商品:名称> 这个名字姓【商品】, 与姓【公司】的互不干扰
解析器看到的标签其实是 {urn:shop}名称 —— 前缀只是给人看的简称。
解析器输出 {urn:shop}名称 与 {urn:corp}名称——前缀被展开成命名空间,撞名不再成立。 注意两个 xmlns 是分别声明在两个子元素上的:谁声明谁生效(作用域跟着元素走)。
30 秒实验
- 给一段含两个重名元素的 XML 分别加上命名空间声明,跑解析看输出变化。
- 用一句话解释【前缀只是简称,认的是 URI】这句话的含义。
常见误区
- 以为前缀不同就等于命名空间不同——真正决定归属的是 xmlns 指向的 URI。
- 以为 xmlns 里的 URI 必须能访问——它只是唯一的标识串,浏览器打不开也完全正常。
自测三问(点开对答案)
1. 命名空间解决什么问题? —— 不同来源的同名标签撞车——给标签加上归属。 2. xmlns:商品="urn:shop" 的含义? —— 声明前缀 商品 归属 urn:shop 这个命名空间。 3. 解析器眼里的标签是什么形式? —— {urn:shop}名称——前缀已被展开成完整命名空间。- ☐ 下一节(11.7 可以严格地定义 XML 的文档结构)
相关笔记
- XML 是可扩展的语言 — 可扩展的副作用正是撞名
- XML 是通用的数据交换格式 — 交换双方靠命名空间避让
- 💻 计算机是怎样跑起来的 · 索引