在工作中,我们被要求创建 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 文档的结构时,您应该如何决定何时使用属性或元素?

有帮助吗?

解决方案

我使用这个经验法则:

  1. 属性是独立的东西,即颜色、ID、名称。
  2. 元素是具有或可能具有自己的属性或包含其他元素的东西。

所以你的很接近。我会做类似的事情:

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

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

其他提示

属性的一些问题是:

  • 属性不能包含多个值(子元素可以)
  • 属性不易扩展(以供将来更改)
  • 属性不能描述结构(子元素可以)
  • 属性更难通过程序代码操作
  • 属性值不容易根据 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”代表“可扩展 标记 语言”。标记语言意味着数据是文本, 已标记 包含有关结构或格式的元数据。

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 的回答)。

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 通常使用更多元素会更好。

例如,假设我们有答案中建议的 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 当可以在不破坏现有代码的情况下进行调整时,它是最有用的。

我在模式设计中使用以下关于属性与属性的指南。要素:

  • 使用长期运行的元素(通常是字符串或标准化类型的元素)
  • 如果有两个值分组(例如元素的 eventStartDate 和 eventEndDate)。在上一个示例中,“事件”应该有一个新元素,该元素可能包含起点和端代属性。
  • 营业日期、日期时间和数字(例如计数,数量和费率)应为要素。
  • 非企业的时间元素,例如上次更新,到期应为属性。
  • 非业务数字(例如哈希码和索引)应该是属性。* 如果类型很复杂,请使用元素。
  • 如果值是简单类型且不重复,则使用属性。
  • xml:id 和 xml:lang 必须是引用 XML 模式的属性
  • 在技​​术上可行的情况下优先选择属性。

对属性的偏好是它提供以下内容:

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

我添加了 当技术上可行时 因为有时无法使用属性。例如,属性集选择。例如,当前模式语言无法使用 (startDate 和 endDate) xor (startTS 和 endTS)

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

这个问题没有通用的答案(我积极参与了 W3C 规范的创建)。XML 可用于多种用途 - 类似文本的文档、数据和声明性代码是最常见的三种用途。我也经常使用它作为数据模型。在这些应用程序的某些方面,属性更为常见,而在其他方面,子元素则更为自然。各种工具的一些功能也使它们的使用变得更容易或更困难。

XHTML 是属性具有自然用途的领域(例如在类='foo')。属性没有顺序,这可能使某些人更容易开发工具。如果没有模式,OTOH 属性就很难键入。我还发现命名空间属性 (foo:bar="zork") 在各种工具集中通常更难管理。但看看一些 W3C 语言,您就会发现常见的混合情况。SVG、XSLT、XSD、MathML 是一些著名语言的示例,并且都具有丰富的属性和元素。有些语言甚至允许不止一种方法来做到这一点,例如

<foo title="bar"/>;

或者

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

请注意,这些在语法上并不等效,需要处理工具的明确支持)

我的建议是查看最接近您的应用程序的领域的常见做法,并考虑您可能希望应用哪些工具集。

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

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

百万美元的问题!

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

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

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

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

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

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

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

无论哪种方式都是有争议的,但您的同事是正确的,因为 XML 应该用于“标记”或围绕实际数据的元数据。就您而言,您是对的,因为在使用 XML 进行域建模时,有时很难确定元数据和数据之间的界线在哪里。在实践中,我所做的就是假装标记中的任何内容都是隐藏的,并且只有标记之外的数据是可读的。从这个意义上说,这份文件有意义吗?

XML 的体积是出了名的大。对于运输和存储,如果您有足够的处理能力,强烈建议您进行压缩。由于其重复性,XML 的压缩效果很好,有时甚至非常好。我已经将大文件压缩到原始大小的 5% 以下。

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

这两种存储对象属性的方法都是完全有效的。你应该脱离务实的考虑。尝试回答以下问题:

  1. 哪种表示形式可以加快数据解析\生成速度?
  2. 哪种表示形式可以加快数据传输速度?
  3. 可读性重要吗?

    ...

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

比如我比较喜欢......

<?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 库,它会为您处理好这些事情。

天哪,如果您确实需要,属性可以包含图像等二进制数据,只需对其进行 base64 编码并将其设为数据即可:网址。

@费恩斯特:在 IDS 或 NAMES 的情况下,属性可以包含以空格分隔的多个项目,其中包括数字。挑剔,但这最终可以节省空间。

使用属性可以使 XML 与 JSON 保持竞争。看 脂肪标记:消除一次一卡路里的脂肪标记神话.

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

例如,非标记文本始终属于属性。总是。

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

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

每当我看到类似的案例 <car><make>Ford</make><color>Red</color></car>, ,我心里想“哎呀,作者是否认为 make 元素中会有子元素?” <car make="Ford" color="Red" /> 明显更具可读性,毫无疑问如何处理空格等。

只要给出空白处理规则,我相信这是 XML 设计者的明确意图。

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

  1. 所有数据都在标记之间
  2. 属性用于表征该数据(例如格式)

如果您只有 XML 形式的纯数据,则差异不太明显。数据可以位于标记之间或作为属性。

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

如果你想在这里使用属性:您可以将数据分为两类:数据和“元数据”,其中元数据不是您想要呈现的记录的一部分,而是诸如“格式版本”、“创建日期”等内容。

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

也可以说:“使用属性来表征标签,使用标签来提供数据本身。”

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

随着时间的推移,属性很容易变得难以管理,相信我。我个人总是远离他们。元素更加明确,并且解析器和用户都可以读取/使用。

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

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

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

<image>
  <url>wank.jpg</url>
  <fileType>gif</fileType>
</image>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top