我应该在XML中使用元素还是属性?

94

我正在学习来自W3Schools的XML属性

作者提到了以下内容(重点是我的):

XML Elements vs. Attributes

<person sex="female">
  <firstname>Anna</firstname>
  <lastname>Smith</lastname>
</person>

<person>
  <sex>female</sex>
  <firstname>Anna</firstname>
  <lastname>Smith</lastname>
</person>

In the first example sex is an attribute. In the last, sex is an element. Both examples provide the same information.

There are no rules about when to use attributes and when to use elements. Attributes are handy in HTML. In XML my advice is to avoid them. Use elements instead.

Avoid XML Attributes?

Some of the problems with using attributes are:

  • attributes cannot contain multiple values (elements can)
  • attributes cannot contain tree structures (elements can)
  • attributes are not easily expandable (for future changes)

Attributes are difficult to read and maintain. Use elements for data. Use attributes for information that is not relevant to the data.

作者的观点是否很有名,或者这是XML中最佳实践?

在XML中应该避免使用属性吗?

W3Schools还提到了以下内容(重点是我的):

XML Attributes for Metadata

Sometimes ID references are assigned to elements. These IDs can be used to identify XML elements in much the same way as the ID attribute in HTML. This example demonstrates this:

<messages>
  <note id="501">
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
  </note>
  <note id="502">
    <to>Jani</to>
    <from>Tove</from>
    <heading>Re: Reminder</heading>
    <body>I will not</body>
  </note>
</messages>

The ID above is just an identifier, to identify the different notes. It is not a part of the note itself.

What I'm trying to say here is that metadata (data about data) should be stored as attributes, and that data itself should be stored as elements.

13个回答

74

通常,属性或元素的使用取决于您正在尝试建模的数据。

例如,如果某个实体是数据的一部分,则最好将其作为一个元素。例如,员工姓名是员工数据的重要部分。

现在,如果您想传达有关数据的元数据(提供有关数据的附加信息)但实际上不是数据的组成部分,则最好将其作为属性。 例如,假设每个员工都有一个需要用于后端处理的GUID,则将其作为属性更好。(GUID不是向查看xml的人传达真正有用信息的东西,但可能对其他目的很必要)

没有硬性规定说某些东西应该是属性还是元素。

并非必须完全避免属性。有时,它们比元素更容易建模。这确实取决于您正在尝试表示的数据。


3
属性不仅用于元数据 - 它们也用于任何非分层数据。请参阅William Walseth的答案。 - Bip901

47

五年后,我的0.02完全相反。让我来解释一下。

  1. 当您对类似数据及其属性进行分组时,请使用元素。
  2. 不要为所有内容使用元素。
  3. 如果数据重复(1-多个),则可能是元素。
  4. 如果数据从未重复,并且仅在与其他内容相关联时才有意义,则它是属性。
  5. 如果数据没有其他属性(即名称),则它是属性。
  6. 将类似元素分组在一起以支持集合解析(例如/xml/character)。
  7. 重用类似的元素名称以支持解析数据。
  8. 绝不要在元素名称中使用数字来表示位置。(即character1、character2)。此做法使解析变得非常困难(请参见#6,解析代码必须是/character1、/character2等,而不仅仅是/character)。

换个角度考虑:

  • 首先将所有数据视为属性。
  • 将属性逻辑地分组成元素。如果您了解自己的数据,您很少需要将属性转换为元素。您可能已经知道何时需要元素(集合或重复数据)。
  • 逻辑地将元素组合在一起。
  • 当您遇到需要扩展的情况时,请根据上述的逻辑结构和过程添加新元素/属性。添加一个子元素集合将不会“破坏”您的设计,并且随着时间的推移,它将更易于阅读。

例如,查看一组简单的书籍和主要角色,标题永远不会有“子项”,它只是一个简单的元素。每个角色都有姓名和年龄。

    <book title='Hitchhiker&apos;s Guide to the Galaxy' author='Douglas Adams'>
        <character name='Zaphod Beeblebrox' age='100'/>
        <character name='Arthur Dent' age='42'/>
        <character name='Ford Prefect' age='182'/>
    </book>

    <book title='On the Road' author='Jack Kerouac'>
        <character name='Dean Moriarty' age='30'/>
        <character name='Old Bull Lee' age='42'/>
        <character name='Sal Paradise' age='42'/>
    </book>

你可以认为一本书可能有多个作者。好的,只需添加新的作者元素(可选删除原始的 @author),即可进行扩展。 当然,这样做会破坏原始结构,但在实践中这种情况相当罕见,并且很容易解决。 任何最初假定只有一个作者的您原始 XML 的消费者都必须进行更改(他们可能正在更改其数据库,将作者从“书”表中的列移动到“作者”表中)。

<book title='Hitchhiker&apos;s Guide to the Galaxy'>
    <author name='Douglas Adams'/>
    <author name='Some Other Guy'/>
    <character name='Zaphod Beeblebrox' age='100'/>
    <character name='Arthur Dent' age='42'>
    <character name='Ford Prefect' age='182'/>
</book>

4
避免使用下列两个经典错误:1)绝不要将元素名称命名为<attribute>。2)避免使用<attribute name='Name' value='Douglas Adams'/>,应该使用<author name='Douglas Adams'/>。 - William Walseth

31

放置属性不仅重要,而且可以让XML更加简洁。

做个比较

<person name="John" age="23" sex="m"/>

反对

<person>
    <name>
        John
    </name>
    <age>
        <years>
            23
        </years>
    </age>
    <sex>
        m
    </sex>
</person>
是的,那有点带偏且夸张了,但你明白我的意思。

1
但是使用属性难道不会使它更加复杂,即使不啰嗦吗? - Ibn Saeed
6
@Ibn Saeed,我认为这并不更加复杂。从XML或元素中获取属性同样容易。 - Nathan Koop
3
我同意,尤其是在处理非常大的文件时,大量的空白区域会使它们难以阅读。 - William Walseth
5
如果需要包括John的五个孩子及其年龄,应该怎么办? - dbasnett
12
@dbasnett,然后你为单个<person>元素下的每个子元素创建一个子元素。这两者并不互斥。如果将元素视为“对象”,将属性视为该对象中的数据点,则很容易确定何时使用它们。 - gbjbaanb
也许有些离题,但如果您使用更优秀的 SGML,则使用元素实际上会更少冗长,因为您可以使结束标记变为可选! - fabspro

20
我使用 Google 搜索了确切的问题。首先我找到了这篇文章:XML设计原则 - 何时使用元素和属性。尽管它对于这样一个简单的问题来说感觉太长了。无论如何,我已经阅读了关于这个主题的所有答案,并没有找到一个令人满意的总结。因此,我又回到了后面那篇文章。这是一个总结:

何时使用元素和何时使用属性呈现信息?

  • 如果所涉及的信息本身可以用元素标记,就将其放在一个元素中。
  • 如果信息适合使用属性形式,但可能会成为同一元素上多个具有相同名称的属性,请改用子元素。
  • 如果信息需要符合标准 DTD 类似的属性类型,例如 ID、IDREF 或 ENTITY,请使用属性。
  • 如果信息不应规范化空格,请使用元素。(XML 处理器规范化属性 可以改变属性值的原始文本。)

核心内容原则

如果你认为所涉及的信息是表达或传达在 XML 中的基本材料的一部分,请把它放在一个元素中。如果你认为该信息是与主要通信边缘相关或次要的,或者纯粹是为了帮助应用程序处理主要通信,请使用属性。

结构化信息原则

如果信息以结构化形式表示,特别是如果该结构可以扩展,请使用元素。如果信息表示为原子令牌,请使用属性。

可读性原则

如果信息旨在供人阅读和理解,请使用元素。如果信息最容易被机器理解和处理,请使用属性。

元素/属性绑定原则

如果您需要另一个属性修改其值,请使用元素。[..]让一个属性修改另一个属性几乎总是一个糟糕的主意。

这是文章重要部分的简要摘要。如果您想查看每种情况的示例和完整描述,请参考原始文章。

已被机器处理,使用属性。


3
遵循链接中提供的信息帮我省了许多麻烦。虽然它会生成更冗长的XML,但它是值得的。遵循这些原则,就难以出错。 - dbasnett
“Principles of XML design - When to use elements versus attributes” by Uche Ogbuji的链接对我无效。但是,我可以通过以下方式访问文档:https://web.archive.org/web/20170307092058/https://www.ibm.com/developerworks/library/x-eleatt/index.html - andypea

7

属性模型映射。元素上的一组属性直接等同于一个名称/值映射,其中值为文本或任何可序列化的值类型。例如,在C#中,任何Dictionary<string, string>对象都可以表示为XML属性列表,反之亦然。

这绝不适用于元素。虽然您始终可以将名称/值映射转换为一组元素,但反过来不行,例如:

<map>
   <key1>value</key1>
   <key1>another value</key1>
   <key2>a third value</key2>
</map>

如果您将此转换为地图,则会失去两个东西:与key1相关联的多个值以及key1出现在key2之前的事实。如果您查看用于更新类似格式中的信息的DOM代码,这一点变得更加清晰。例如,编写以下内容轻而易举:
foreach (string key in map.Keys)
{
   mapElement.SetAttribute(key, map[key]);
}

那段代码简洁明了,没有歧义。相比之下,可以看看这个例子:
foreach (string key in map.Keys)
{
   keyElement = mapElement.SelectSingleNode(key);
   if (keyElement == null)
   {
      keyElement = mapElement.OwnerDocument.CreateElement(key);
      mapElement.AppendChild(keyElement);
   }
   keyElement.InnerText = value;
}

4

在属性中无法使用CDATA。根据我的经验,您可能会想要将单引号、双引号和/或整个XML文档放入“成员”中,如果它是一个属性,您将会咒骂使用属性而不是元素的人。

注意:我的XML经验主要涉及清理别人的代码。这些人似乎遵循老话:“XML就像暴力。如果使用它没有解决您的问题,那么您没有使用足够多。”


2
如果你正在使用DOM构建,那么在属性中放置单引号或双引号不是问题。但如果你正在将XML作为字符串构建,则会遇到这个问题以及其他很多问题。 - William Walseth

3

这是一个关于属性作为数据的例子。

数据库通过它们的ID属性进行命名。

数据库标签中的"type"属性表示预期在其中找到的内容。

  <databases>

      <database id='human_resources' type='mysql'>
        <host>localhost</host>
        <user>usrhr</user>
        <pass>jobby</pass>
        <name>consol_hr</name>
      </database>

      <database id='products' type='my_bespoke'>
        <filename>/home/anthony/products.adb</filename>
      </database>

  </databases>

3

这完全取决于XML的使用目的。当它主要用于软件和机器之间的交互,比如Web服务时,为了保持一致性(以及某些框架的偏好,如WCF),全部采用元素更容易。如果它是面向人类消费的,即主要由人创建和/或阅读,那么明智地使用属性可以显著提高可读性;XHTML就是一个合理的例子,还有XSLT和XML Schema。


2

我通常的工作方式是将属性视为元数据 - 也就是关于数据的数据。但我避免在属性中放置列表,例如:

attribute="1 2 3 7 20"

否则,您需要额外解析每个元素。如果XML提供了列表的结构和工具,则为什么还要自己添加呢。
在使用SAX解析器进行处理时,您可能希望优先编写属性方面的代码以提高处理速度。使用SAX解析器,您将获得一个元素回调,其中包含元素名称和属性列表。如果您使用多个元素,则会获得多个回调(每个元素一个)。当然,这是否会带来太大的负担/时间成本是有争议的,但也值得考虑。

在属性中进行列表的标准方式是attribute="1 2 3 7 20",这是XML Schema支持的。 - John Saunders
3
我不知道那个。现在,我能用XPath和其他标准工具提取它们吗? - Brian Agnew

2
作者的观点是正确的(除了属性可能包含值列表之外)。问题在于你是否关心他的观点。
取决于你。

我将使用PHP和MySQL来处理XML。主要是为了创建图表或将数据传递给桌面应用程序进行操作。 - Ibn Saeed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接