XML 属性
本章定位 :属性是附加在元素上的"名称-值"对,提供元数据。理解属性的引号规则、设计原则和常见误区。
定义与作用
XML 属性 是写在元素 开始标签 中的名称-值对,提供关于该元素的额外信息。属性的设计初衷是存放 元数据——即描述数据的数据,而非数据本身。
<book category="web" cover="paperback" id="bk101">
<title>Learning XML</title>
</book>
上例中 category、cover、id 都是属性。它们描述 book 的分类、装帧和标识,而实际内容(书名)放在子元素中。
核心原理:属性在 DOM 树中的位置
图解释 :在 DOM 树中, 属性不是元素的子节点——属性是元素节点的附属信息。childNodes 不会包含属性节点,获取属性需要用 getAttribute() 或访问 attributes 属性。XPath 中需要用 @ 前缀来选择属性。
语法/结构要点
属性语法规则
| 规则 | 说明 | 示例 |
|---|---|---|
| 引号必须 | 属性值必须用单引号或双引号包裹 | category="web" |
| 单双引号均可 | 值含双引号时用单引号包裹,反之亦然 | title='He said "Hello"' |
| 一个元素中属性名唯一 | 不能有两个同名属性 | <book id="1" id="2"> ❌ |
值不能含 < | 必须用 < 替代 | <note text="a < b"> |
属性设计原则与误区
| 场景 | 推荐方案 | 反模式 |
|---|---|---|
| 唯一标识 | <student id="2024001"> | 正常 |
| 分类/类型 | <book category="web"> | 正常 |
| 用户姓名 | <name>小崔</name> | <student name="小崔"> ❌ |
| 多值列表 | <tags><tag>XML</tag><tag>Java</tag></tags> | <post tags="XML,Java"> ❌ |
| 长文本 | <description>很长很长的文本...</description> | <item desc="很长..."> ❌ |
完整示例:黄俪重构图书目录属性设计
场景说明
飞翔科技的测试工程师 黄俪 发现图书目录 XML 的一个设计问题:有些书的作者不止一个,但目前的设计把"所有作者"塞进一个属性中。前端开发 小崔 反馈说这样很难按作者检索。黄俪决定按照"数据用元素,元数据用属性"的原则重构。
操作前:属性滥用
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="bk101" category="web" authors="James McGovern, Per Bothner, Kurt Cagle, James Linn, Vaidyanathan Nagarajan"
title="XQuery Kick Start" year="2003" price="49.99"/>
<book id="bk102" category="cooking" authors="Giada De Laurentiis"
title="Everyday Italian" year="2005" price="30.00"/>
</bookstore>
问题:
authors属性含多个值,用逗号分隔——程序需要手动拆分- 无法为每个作者添加额外信息(如角色"主编/合著")
- 属性值过长降低可读性
操作后:属性用于元数据,元素用于数据
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="bk101" category="web" cover="paperback">
<title lang="en">XQuery Kick Start</title>
<authors>
<author role="lead">James McGovern</author>
<author role="co-author">Per Bothner</author>
<author role="co-author">Kurt Cagle</author>
<author role="co-author">James Linn</author>
<author role="co-author">Vaidyanathan Nagarajan</author>
</authors>
<year>2003</year>
<price currency="USD">49.99</price>
</book>
<book id="bk102" category="cooking">
<title lang="en">Everyday Italian</title>
<authors>
<author role="lead">Giada De Laurentiis</author>
</authors>
<year>2005</year>
<price currency="USD">30.00</price>
</book>
</bookstore>
操作结果
重构后,可以用 XPath 精确查询:
//book[authors/author='James McGovern']— 找某个作者的书//book[authors/author/@role='lead']— 找所有主编//book[@category='web']/price— 找 web 类图书的价格
黄俪总结:"属性就像贴在信封上的标签——适合简短、唯一的元信息。内容应该放在信封里。"
易错场景
错误一:属性值不加引号
<!-- ❌ XML 中属性值必须加引号(HTML 中有时可以省略) -->
<book category=web>
<!-- ✅ -->
<book category="web">
错误二:在属性值中使用 < 而不转义
<!-- ❌ -->
<condition expr="a < b">
<!-- ✅ -->
<condition expr="a < b">
错误三:试图在属性中存储结构化数据
<!-- ❌ 属性只能存字符串,无法存结构 -->
<person address="city:Guangzhou,district:Tianhe,street:No.123">
<!-- ✅ 结构数据应该用子元素 -->
<person>
<address>
<city>Guangzhou</city>
<district>Tianhe</district>
<street>No.123</street>
</address>
</person>
面试考点
| 考点 | 参考答案要点 |
|---|---|
| 属性值必须加引号吗?单引号和双引号有区别吗? | 必须加,二选一,功能无区别。值中含双引号用单引号包裹,反之亦然 |
| 为什么 DOM 中属性不是元素的子节点? | 属性是元素节点的附属元数据,不是文档层级结构的一部分。childNodes 只包含子元素和文本节点,属性需通过专门的 API 访问 |
| 什么情况下适合用属性而不是子元素? | ①ID/唯一标识符;②简短分类标签;③指向其他资源的引用(如 href);④不随国际化变化的元数据(如日期格式、单位) |