XML 属性和子元素有什么区别?什么时候该用哪个?
XML 属性适合放元数据——ID、类型、状态这类简单的键值对;子元素适合放实际数据和可能变复杂的内容。属性的硬限制是:只能存纯文本、同一元素内不能重复、不能嵌套子结构。所以只要信息有可能扩展、可能多值、可能变复杂,就应该用子元素。
一个实用的判断方法:如果你犹豫"这个该放属性还是子元素",大概率该用子元素。属性只在你非常确定它永远是一个简单原子值时才用。W3C 和 Google XML Style Guide 的建议一致:元数据用属性,数据本身用子元素。
追问
属性和子元素的核心区别是什么?
属性是开始标签上的 name="value" 对,值只能是纯文本,同名属性在同一元素内只能出现一次。子元素是嵌套在父元素内的独立元素,可以重复、可以嵌套、可以有混合内容(文本和子元素混排),且保持文档顺序。
用代码看最直观:
xml<!-- 属性:简单键值对 --> <book id="B001" category="programming" lang="zh"> <title>XML 实战</title> </book> <!-- 子元素:可以重复、嵌套、保持顺序 --> <book> <id>B001</id> <categories> <category>programming</category> <category>reference</category> </categories> </book>
category 如果可能多值,属性就搞不定——它不能重复,只能用子元素。
实际项目里选错会怎样?
配置文件把数据库连接参数全写成属性:
xml<db driver="mysql" host="127.0.0.1" port="3306"/>
后来要给 host 加 failover 列表、给连接加 SSL 配置,属性扩展不了,只能全部拆成子元素重写。如果一开始就用子元素,加字段只是多写几行的事。
再比如 SOAP 协议里,早期版本大量使用属性传业务数据,后来扩展性需求上来后不得不迁移到子元素,导致版本兼容成了大坑。
Google 和 W3C 的官方建议是什么?
Google XML Style Guide 明确说:属性只用于 ID 引用等元数据,其他一律用子元素。W3C 的 XML 推荐标准虽然没有强制规定,但示例中始终把元数据(id、class)放属性,内容数据放子元素。两条规则的内核一样——属性是"关于数据的数据",子元素是"数据本身"。
有没有属性确实更合适的场景?
HTML/SVG 是属性发挥优势的典型场景:<div id="main" class="container">、<rect x="10" y="20" width="100"/>——id、class、坐标、尺寸都是纯元数据,不会变复杂,用属性比嵌套子元素简洁得多,解析也更快。
另外在 SAX 流式解析中,一个元素的所有属性一次性报出,而子元素逐个触发事件。如果你需要快速读取元数据做路由分发,属性在性能上有微小优势。
属性值有长度限制吗?多行文本能放属性吗?
XML 规范没有规定属性值长度上限,但实际中有两个问题:很多 SAX 解析器实现在属性值超过一定长度时性能下降甚至截断;更关键的是,属性值中的换行符会被 XML 解析器规范化为空格——多行文本放属性里会丢失格式。所以长文本、多行内容、含换行的代码片段,必须用子元素。
写段代码
xml<!-- 推荐:元数据用属性,数据用子元素 --> <book id="B001" isbn="978-0-123456-78-9" lang="zh"> <title>XML 实战</title> <authors> <author>张三</author> <author>李四</author> </authors> </book>