XML 实战速查:和 JSON 的本质差异、命名空间和 XPath 10 条常用表达式

· 约 4 分钟 </> XML 工具

JSON 出现后,XML 的新项目份额大幅缩减——但 XML 从未消亡。SOAP/WSDL、SVG、XHTML、Android 布局文件、Maven POM、Office Open XML(.docx/.xlsx)全都是 XML。遇到 XML 时,会读 namespace、会用 XPath,能省掉大量循环代码。

XML vs JSON:各自的地盘

维度XMLJSON
语法标签 + 属性 + 文本,层次明确键值对 + 数组,简洁
类型系统一切字符串,靠 XSD 约束原生 number/bool/null
命名空间有(xmlns),可混合多来源无标准机制
注释<!-- -->不支持(JSON5 支持)
混合内容支持(文本+子元素并列)不支持
Schema 成熟度XSD 极强JSON Schema 较弱
主要场景企业集成/文档/配置/Web标准Web API / 配置文件

XML 没被取代的核心原因:namespace 和混合内容(mixed content)是 JSON 没有的能力,复合文档场景无可替代。

命名空间(Namespace)实战

读 SOAP 消息

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:biz="http://example.com/bizservice">
  <soap:Header/>
  <soap:Body>
    <biz:GetOrder>
      <biz:orderId>12345</biz:orderId>
    </biz:GetOrder>
  </soap:Body>
</soap:Envelope>

解读:

  • xmlns:soap="..." → 前缀 soap: 绑定到 SOAP 规范的 URI
  • xmlns:biz="..." → 前缀 biz: 绑定到业务服务的 URI
  • <soap:Body> 是 SOAP 协议的 Body,<biz:GetOrder> 是业务方法
  • URI 只是标识符,不能访问(不是 REST endpoint)

默认命名空间

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <groupId>com.example</groupId>  <!-- 无前缀,属于默认 namespace -->
  <artifactId>myapp</artifactId>
</project>

xmlns="..." 不带前缀 → 该元素及所有无前缀子元素都属于这个 namespace。Maven POM 就是这样——所有元素无前缀,但都在 Maven 的 namespace 下。

XPath 10 条常用表达式

以这个 XML 为例:

<catalog>
  <book id="1" lang="zh">
    <title>深入理解计算机系统</title>
    <price currency="CNY">99.9</price>
    <tags><tag>计算机</tag><tag>经典</tag></tags>
  </book>
  <book id="2" lang="en">
    <title>Clean Code</title>
    <price currency="USD">45.0</price>
    <tags><tag>编程</tag></tags>
  </book>
</catalog>
#表达式结果
1/catalog/book所有 book 元素
2//book任意位置的 book 元素(同上,因为只有一层)
3//book[1]第一个 book(id=1)
4//book[@lang="zh"]lang 属性为 zh 的 book
5//book/@id所有 book 的 id 属性值
6//title/text()所有 title 的文本:深入理解…、Clean Code
7//price[@currency="CNY"]/text()人民币价格文本:99.9
8//book[price > 50]price 大于 50 的 book
9//tag[text()="计算机"]/../../title/text()含”计算机”标签的书名
10count(//book)book 总数:2

// vs / 的区别/ 是绝对/相对路径中的层级分隔,// 表示”跳过任意层级”。/catalog/book 要求 book 直接在 catalog 下;//book 在任意深度都能找到。

常见 XML 格式速查

SVG(可缩放矢量图形)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <path d="M12 2L2 7v10l10 5 10-5V7z" fill="currentColor"/>
</svg>

SVG 是 XML,可以用 XPath 分析图层结构,用 XML 工具格式化查看节点。

Maven POM

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>6.1.0</version>
    </dependency>
  </dependencies>
</project>

Android 布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
  <TextView android:text="Hello" android:textSize="16sp"/>
</LinearLayout>

android: 前缀绑定到 Android 命名空间,属性名才不和自定义属性冲突。

工具使用技巧

  • 格式化:粘入压缩的单行 XML(SOAP 响应、日志里的 XML),点格式化变成可读的缩进树
  • 验证:上传 XSD 文件校验 XML 是否符合 Schema 约束
  • XPath 查询:在工具里直接输入 XPath 表达式,高亮匹配节点——比肉眼找节省 90% 时间
  • 压缩:多行格式化 XML 压缩成单行,用于 HTTP 请求体

配套工具

❓ 常见问题

XML 和 JSON 有什么本质区别?

结构、类型系统、扩展性三个维度都不同(1) 结构:XML 是树状节点(元素、属性、文本、注释),JSON 是键值对/数组/原始值;XML 能在一个节点上同时有属性和子元素,JSON 只有嵌套对象。(2) 类型系统:JSON 原生区分 number/string/boolean/null,XML 一切皆字符串,类型靠 Schema 约定或应用自己解析;XML Schema(XSD)比 JSON Schema 更成熟,能表达复杂约束。(3) 扩展性:XML 有 namespace(命名空间),不同来源的元素可以在同一文档共存而不冲突——SOAP/WSDL/XHTML 复合文档依赖这个特性;JSON 没有标准的命名空间机制。(4) 可读性:JSON 更简洁;XML 因属性/元素双通道反而表达力更丰富,但啰嗦。

namespace(命名空间)是什么,为什么 XML 里到处是 xmlns?

namespace 解决"同名不同义"的冲突问题。示例:SOAP 消息里既有自定义业务元素 <Body>,又有 SOAP 协议自己的 <Body>——两个 <Body> 含义完全不同,必须区分。解法:每个 <Body> 加前缀,前缀绑定到 URI:<soap:Body><biz:Body>,前缀在元素上用 xmlns:soap="..." 声明。xmlns 的本质xmlns:前缀="URI",URI 只是唯一标识符(不一定是真实 URL),前缀是局部缩写。xmlns="URI"(不带前缀)是默认命名空间,当前元素及子元素无前缀的都属于这个 namespace。常见误区:URI 看起来像网址但不代表可以访问——W3C 的 http://www.w3.org/2001/XMLSchema 是标识符,不是 endpoint。

XPath 怎么选取子节点、属性、文本?

XPath 核心语法:(1) /root/child — 绝对路径,从根元素到 child;(2) //child — 任意位置的 child 元素;(3) @attr — 选属性;(4) text() — 选文本节点;(5) [n] — 第 n 个(从 1 开始);(6) [@attr="val"] — 按属性过滤;(7) [text()="val"] — 按文本过滤;(8) .. — 父节点。示例//item[@type="A"]/price/text() — 找所有 type 属性为 A 的 item 下的 price 文本内容。

XML 属性和子元素有什么区别,什么时候用哪个?

经验法则:元数据/标识符用属性,内容/可嵌套的数据用子元素。用属性<user id="42" role="admin">——id 和 role 是标识这个节点的元数据,不是内容,值是原子类型(字符串/数字),不需要嵌套。用子元素<user><address><city>北京</city></address></user>——地址是可结构化的内容,本身可能还有子元素。XML Schema 的角度:属性只能是简单类型,子元素可以是复杂类型(有子元素)。实践:看 <price currency="CNY">99.9</price>——currency 是属性(描述 price 的货币单位),price 值是文本内容。

CDATA 是什么,什么时候需要用?

CDATA 段让解析器把内容当纯文本,不解析里面的 XML 特殊字符。格式:<![CDATA[任意内容,包括 < > & " 都不用转义]]>。需要用 CDATA 的场景:(1) 元素内容包含大量 < > &(比如内嵌 HTML 片段、JavaScript 代码);(2) SQL 语句内嵌到 XML;(3) Markdown / 正则表达式。不需要 CDATA 时,应该用实体转义:<&lt;>&gt;&&amp;"&quot;。CDATA 里的 ]]> 序列是结束标记,内容中不能出现,这是 CDATA 的唯一限制。

</> 打开 XML 工具 格式化/压缩·校验定位·XPath 查询·树视图浏览·转义/CDATA·本地运行