2024-09-15 07:00:01

XML属性vs XML元素

在工作中,我们被要求创建XML文件来将数据传递给另一个脱机应用程序,然后该应用程序将创建第二个XML文件来传递回去,以更新我们的一些数据。在这个过程中,我们一直在与另一个应用程序的团队讨论XML文件的结构。

我提出的样本基本上是这样的:

<INVENTORY>
   <ITEM serialNumber="something" location="something" barcode="something">
      <TYPE modelNumber="something" vendor="something"/> 
   </ITEM>
</INVENTORY>

另一个团队说,这不是行业标准,属性应该只用于元数据。他们建议:

<INVENTORY>
   <ITEM>
      <SERIALNUMBER>something</SERIALNUMBER>
      <LOCATION>something</LOCATION>
      <BARCODE>something</BARCODE>
      <TYPE>
         <MODELNUMBER>something</MODELNUMBER>
         <VENDOR>something</VENDOR>
      </TYPE>
   </ITEM>
</INVENTORY>

我建议使用第一个方法的原因是,创建的文件的大小要小得多。在传输过程中,文件中将有大约80000个项目。事实上,他们的建议比我的建议大三倍。我搜索了提到的神秘的“行业标准”,但我能找到的最接近的是XML属性应该只用于元数据,但争论的焦点是什么才是实际的元数据。

在冗长的解释(抱歉)之后,如何确定什么是元数据,以及在设计XML文档的结构时,如何决定何时使用属性或元素?


存储对象属性的两种方法都是完全有效的。你应该放弃实用主义的考虑。试着回答以下问题:

哪种表示方式可以更快地生成数据解析? 哪种表示法可以更快地传输数据? 可读性重要吗? ...


这是个价值百万美元的问题!

首先,现在不要太担心性能。您会惊讶于优化的XML解析器解析XML的速度有多快。更重要的是,您对未来的设计是什么:随着XML的发展,您将如何保持松耦合和互操作性?

更具体地说,您可以使元素的内容模型更加复杂,但扩展属性则更加困难。


这两种方式都有争议,但您的同事认为XML应该用于“标记”或围绕实际数据的元数据,这一点是正确的。对您来说,在用XML建模域时,有时很难确定元数据和数据之间的界限。实际上,我所做的是假装标记中的任何内容都是隐藏的,只有标记之外的数据是可读的。这份文件在这方面有意义吗?

XML是出了名的庞大。对于运输和存储,如果你能负担得起处理能力,强烈建议压缩。XML压缩得很好,有时压缩得非常好,因为它具有重复性。我曾经把大文件压缩到不到原始大小的5%。

支持您立场的另一点是,当其他团队在争论样式时(大多数XML工具处理全属性文档就像处理全#PCDATA文档一样容易),您在争论实用性。虽然不能完全忽视风格,但技术优点应该更重要。


如果有疑问,KISS——当您没有明确的理由使用属性时,为什么要混合使用属性和元素呢?如果稍后决定定义一个XSD,那么最终也会更简洁。然后,如果稍后决定从XSD生成类结构,也会更简单。


我的经验是这样的:

属性是自包含的东西,例如颜色、ID、名称。 元素是具有或可能具有自己的属性或包含其他元素的东西。

你的也很接近了。我会这样做:

编辑:根据下面的反馈更新了原始示例。

  <ITEM serialNumber="something">
      <BARCODE encoding="Code39">something</BARCODE>
      <LOCATION>XYX</LOCATION>
      <TYPE modelNumber="something">
         <VENDOR>YYZ</VENDOR>
      </TYPE>
   </ITEM>

这很大程度上是个人偏好的问题。在可能的情况下,我使用元素进行分组,并使用属性进行数据,因为我认为这比替代方法更紧凑。

例如,我更喜欢.....

<?xml version="1.0" encoding="utf-8"?>
<data>
    <people>
         <person name="Rory" surname="Becker" age="30" />
        <person name="Travis" surname="Illig" age="32" />
        <person name="Scott" surname="Hanselman" age="34" />
    </people>
</data>

...而不是……

<?xml version="1.0" encoding="utf-8"?>
<data>
    <people>
        <person>
            <name>Rory</name>
            <surname>Becker</surname>
            <age>30</age>
        </person>
        <person>
            <name>Travis</name>
            <surname>Illig</surname>
            <age>32</age>
        </person>
        <person>
            <name>Scott</name>
            <surname>Hanselman</surname>
            <age>34</age>
        </person>
    </people>
</data>

然而,如果我的数据不容易在20-30个字符内表示,或者包含许多引号或其他需要转义的字符,那么我会说,是时候拆分元素了……可能使用CData块。

<?xml version="1.0" encoding="utf-8"?>
<data>
    <people>
        <person name="Rory" surname="Becker" age="30" >
            <comment>A programmer whose interested in all sorts of misc stuff. His Blog can be found at http://rorybecker.blogspot.com and he's on twitter as @RoryBecker</comment>
        </person>
        <person name="Travis" surname="Illig" age="32" >
            <comment>A cool guy for who has helped me out with all sorts of SVn information</comment>
        </person>
        <person name="Scott" surname="Hanselman" age="34" >
            <comment>Scott works for MS and has a great podcast available at http://www.hanselminutes.com </comment>
        </person>
    </people>
</data>

这可能取决于你的用法。用于表示从数据库生成的结构化数据的XML可以很好地将字段值作为属性放置。

然而,XML用作消息传输通常使用更多的元素会更好。

例如,假设我们在答案中提出了这个XML:-

<INVENTORY>
   <ITEM serialNumber="something" barcode="something">
      <Location>XYX</LOCATION>
      <TYPE modelNumber="something">
         <VENDOR>YYZ</VENDOR>
      </TYPE>
    </ITEM>
</INVENTORY>

现在我们想要将ITEM元素发送到设备以打印条形码,但是有一种编码类型可供选择。我们如何表示所需的编码类型?突然,我们意识到,有点晚了,条形码不是一个单一的自动值,而是它可能符合打印时所需的编码。

   <ITEM serialNumber="something">
      <barcode encoding="Code39">something</barcode>
      <Location>XYX</LOCATION>
      <TYPE modelNumber="something">
         <VENDOR>YYZ</VENDOR>
      </TYPE>
   </ITEM>

关键是,除非您构建某种XSD或DTD以及名称空间来固定结构,否则最好保留自己的选择。

当IMO XML可以在不破坏现有代码的情况下进行伸缩时,它是最有用的。


属性的一些问题是:

属性不能包含多个值(子元素可以) 属性不容易扩展(用于将来的更改) 属性不能描述结构(子元素可以) 属性更难以用程序代码操作 属性值不容易根据DTD进行测试

如果您使用属性作为数据的容器,那么您最终会得到难以阅读和维护的文档。尝试使用元素来描述数据。仅在提供与数据无关的信息时使用属性。

不要像这样结束(这不是XML应该使用的方式):

<note day="12" month="11" year="2002" 
      to="Tove" to2="John" from="Jani" heading="Reminder"  
      body="Don't forget me this weekend!"> 
</note>

来源:http://www.w3schools.com/xml/xml_dtd_el_vs_attr.asp


使用元素作为数据,使用属性作为元数据(关于元素数据的数据)。

如果一个元素在选择字符串中显示为谓词,那么很明显它应该是一个属性。同样地,如果一个属性从未被用作谓词,那么它可能不是有用的元数据。

请记住,XML应该是机器可读的,而不是人类可读的,对于大型文档来说,XML压缩得非常好。


我同意芬斯特的观点。如果可以的话,远离属性。元素是进化友好的,并且在web服务工具包之间具有更强的互操作性。您永远不会发现这些工具包使用属性序列化您的请求/响应消息。这也是有意义的,因为我们的消息是web服务工具包的数据(而不是元数据)。


这个问题没有统一的答案(我曾大量参与W3C规范的创建)。XML可以用于许多目的——类似文本的文档、数据和声明性代码是其中最常见的三种。我也经常把它用作数据模型。在这些应用程序的某些方面,属性更常见,而在其他方面,子元素更自然。各种工具的特性也使它们的使用变得更容易或更困难。

XHTML is one area where attributes have a natural use (e.g. in class='foo'). Attributes have no order and this may make it easier for some people to develop tools. OTOH attributes are harder to type without a schema. I also find namespaced attributes (foo:bar="zork") are often harder to manage in various toolsets. But have a look at some of the W3C languages to see the mixture that is common. SVG, XSLT, XSD, MathML are some examples of well-known languages and all have a rich supply of attributes and elements. Some languages even allow more-than-one-way to do it, e.g.

<foo title="bar"/>;

or

<foo>
  <title>bar</title>;
</foo>;

注意,它们在语法上是不等价的,需要处理工具的显式支持)

我的建议是,查看与您的应用程序最接近的领域的常见实践,并考虑您可能希望应用什么工具集。

最后,确保将名称空间与属性区分开来。一些XML系统(例如Linq)在API中将名称空间表示为属性。在我看来,这很丑陋,而且可能令人困惑。


只是对一些不好的信息做一些更正:

属性可以包含任何字符数据。< > & " '需要转义到&lt;&gt;,“;事情就让它,,,分别。如果您使用XML库,它将为您处理这些问题。

一个属性可以包含二进制数据,如图像,如果你真的需要,只需通过base64编码并将其设置为data: URL。

@feenster:在IDS或NAMES的情况下,属性可以包含空格分隔的多个项,其中包括数字。吹毛求疵,但这最终可以节省空间。

使用属性可以保持XML与JSON的竞争力。参见脂肪加价:每次减少一卡路里的脂肪加价神话。


其他人已经介绍了如何区分属性和元素,但是从更一般的角度来看,把所有东西都放在属性中,因为这会使生成的XML更小,这是错误的。

XML的设计不是为了紧凑,而是为了便于移植和人类可读。如果您想减少传输中的数据大小,则使用其他方法(例如谷歌的协议缓冲区)。


“XML”代表“可扩展标记语言”。标记语言意味着数据是文本,用关于结构或格式的元数据标记。

XHTML是按预期方式使用XML的一个例子:

<p><span lang="es">El Jefe</span> insists that you
    <em class="urgent">MUST</em> complete your project by Friday.</p>

这里,元素和属性之间的区别很明显。文本元素显示在浏览器中,属性是关于如何显示它们的指令(尽管有一些标记不是这样工作的)。

当XML不是作为标记语言,而是作为数据序列化语言使用时,就会出现混淆,在这种情况下,“数据”和“元数据”之间的区别更加模糊。因此,元素和属性之间的选择或多或少是任意的,除非不能用属性表示(参见feenster的回答)。


在我的模式设计中,我使用了以下关于属性和元素的指导原则:

Use elements for long running text (usually those of string or normalizedString types) Do not use an attribute if there is grouping of two values (e.g. eventStartDate and eventEndDate) for an element. In the previous example, there should be a new element for "event" which may contain the startDate and endDate attributes. Business Date, DateTime and numbers (e.g. counts, amount and rate) should be elements. Non-business time elements such as last updated, expires on should be attributes. Non-business numbers such as hash codes and indices should be attributes.* Use elements if the type will be complex. Use attributes if the value is a simple type and does not repeat. xml:id and xml:lang must be attributes referencing the XML schema Prefer attributes when technically possible.

属性的优先级是它提供了以下内容:

唯一的(该属性不能出现多次) 顺序不重要 上面的属性是可继承的(这是“所有”内容模型在当前模式语言中不支持的) 额外的好处是它们不那么冗长,占用的带宽也更少,但这并不是更喜欢属性而不是元素的真正原因。

我在技术上可能的情况下添加了属性,因为有时不可能使用属性。例如,属性集选择。例如,对于当前的模式语言,使用(startDate和endDate) xor (startTS和endTS)是不可能的

如果XML Schema开始允许限制或扩展“所有”内容模型,那么我可能会放弃它


如何利用我们来之不易的面向对象的直觉?我通常发现,思考哪个是对象,哪个是对象的属性,或者它指的是哪个对象是很直接的。

任何直观上作为对象有意义的东西都应该作为元素。它的属性(或属性)将是xml中这些元素的属性或带有attribute的子元素。

我认为对于更简单的情况,比如在例子中,面向对象的类比可以很好地找出哪个是元素,哪个是元素的属性。


随着时间的推移,属性很容易变得难以管理,相信我。我个人总是远离他们。元素对于解析器和用户来说更加显式和可读/可用。

我唯一一次使用它们是定义资产url的文件扩展名:

<image type="gif">wank.jpg</image> ...etc etc

我想如果你100%知道属性不需要扩展,你就可以使用它们,但你知道多少次。

<image>
  <url>wank.jpg</url>
  <fileType>gif</fileType>
</image>

这在HTML中非常明显,属性和标记的差异可以清楚地看到:

所有数据都在标记之间 属性用于描述数据的特征(例如格式)

如果只有XML格式的纯数据,区别就不那么明显了。数据可以位于标记之间,也可以作为属性。

大多数数据应该位于标记之间。

你可以把数据分为两类:数据和“元数据”,其中元数据不是记录的一部分,你想要呈现,但像“格式版本”,“创建日期”等。

<customer format="">
     <name></name>
     ...
</customer>

有人也可以说:“使用属性来描述标记,使用标记来提供数据本身。”


XML元素与XML属性

XML是关于协议的。首先遵循社区或行业中任何现有的XML模式或已建立的约定。

如果你真的需要从头定义你的模式,这里有一些关于元素与属性决策的一般考虑:

<versus>
  <element attribute="Meta content">
    Content
  </element>
  <element attribute="Flat">
    <parent>
      <child>Hierarchical</child>
    </parent>
  </element>
  <element attribute="Unordered">
    <ol>
      <li>Has</li>
      <li>order</li>
    </ol>
  </element>
  <element attribute="Must copy to reuse">
    Can reference to re-use
  </element>
  <element attribute="For software">
    For humans
  </element>
  <element attribute="Extreme use leads to micro-parsing">
    Extreme use leads to document bloat
  </element>
  <element attribute="Unique names">
    Unique or non-unique names
  </element>
  <element attribute="SAX parse: read first">
    SAX parse: read later
  </element>
  <element attribute="DTD: default value">
    DTD: no default value
  </element>
</versus>

我总是对这类讨论的结果感到惊讶。对我来说,有一个非常简单的规则来决定数据是否属于属性或内容,即数据是否具有可导航的子结构。

例如,非标记文本总是属于属性。总是这样。

列表属于子结构或内容。随着时间的推移,可能包含嵌入式结构化子内容的文本属于内容。(根据我的经验,在使用XML进行数据存储或交换时,这种带有标记的文本相对较少。)

以这种方式编写的XML模式非常简洁。

每当我看到像<car><make>Ford</make><color>Red</color></car>这样的情况时,我就会想“咦,作者认为make元素中会有子元素吗?”<car make="Ford" color="Red" />可读性明显更好,关于如何处理空白等问题毫无疑问。

考虑到空格处理规则,我相信这是XML设计者的明确意图。