不管个人喜好如何,以下是一组基本问题:
当排序不重要时,使用属性将值映射到唯一名称。否则,使用元素。
- 值:数字、字符串、日期等,但不是多属性对象。
- 唯一名称:元素上的每个属性名称都必须是唯一的。如果一个元素表示的事物可以有多个 Foo 与之关联,则 Foo 不应该是一个属性。
- 顺序不重要:应用程序不能依赖于以特定顺序呈现给进程的值。
一个例子:如果你想在(比如)ADO.NET 和 XML 之间来回传输数据,你应该将列值存储在属性还是元素中? (暂时不要介意 ADO.NET 会为您执行此操作。)好吧,列名唯一地映射到值,并且列值是易于序列化的数据类型。这么确定,为什么不这样做呢?
<Person FirstName="John" MiddleName="Q." LastName="Smith"/>
但实际上这是一种破坏信息的转变。列出现在 ADO.NET 记录中的顺序很重要。如果转换之前第 2 列中有内容,则之后应该在第 2 列中。将它们转换为属性将丢失此信息。 (例如,我知道一种 DOM 实现,它按名称的字母顺序检索属性。)
这就是为什么 ADO.NET 表示这样的行,虽然它很冗长:
<Person>
<FirstName>John</FirstName>
<MiddleName>Q.</MiddleName>
<LastName>Smith</LastName>
</Person>
关于元素用于信息,属性用于元信息的常识:这通常是非常好的建议。也往往只是迷信将你带入坏境。
一方面,元信息可能需要包含与同名关联的多个值。比如说,你可能想用一个将要使用它的页面列表来标记一个元素:
<Person Pages="B1,B2,B3,B4">
<FirstName>John...
曾经尝试过编写解析逗号分隔列表的 XSLT 模板吗?通过这样做你会学到很多东西,但这可能不是你想知道的。
另一方面,不知道自己要面对什么的 XML 设计人员让这个建议引导他们将真正应该在元素标签名称中的属性放入一个属性中。例如:
<Person Type="Employee">
<SSN>123-45-6789</SSN>
<Extension>123</Extension>
</Person>
<Person Type="Customer">
<PhoneNumber>123-456-7890</PhoneNumber>
<BillingAddress>...
等等。猜猜当您尝试编写一个基于Type 属性对Person 元素强制执行不同规则的模式时会发生什么?失败。模式绑定到元素名称。所有Person 元素必须具有相同的架构。在这种情况下,元素应命名为Employee 和Customer。