【问题标题】:XML attribute vs XML elementXML 属性与 XML 元素
【发布时间】:2008-08-29 01:15:52
【问题描述】:

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

【问题讨论】:

  • 我发现了这个非常好的资源:@​​987654321@
  • +1 for "...辩论是关于什么实际上是元数据。"
  • 请注意带有连字符的小写标签名称:stackoverflow.com/questions/1074447/…

标签: xml xsd


【解决方案1】:

我使用这个经验法则:

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

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

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

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

【讨论】:

  • 我通读了一些答案,我认为如果你在一个“属性”中数据并且突然有一个 > 或 、
  • 真的迟到了,但是特殊的 ASCII 字符参数是错误的——这就是转义的目的,对于属性和文本数据。
  • @donroby - 对不起,那是我沟通的错误。通过转义,我的意思是 XML 编码。 '
  • @donroby:这是不正确的。 &amp;lt;的替换文本是&amp;#60;,是字符引用,不是实体引用。 &amp;lt; 属性没问题。见:w3.org/TR/REC-xml/#sec-predefined-ent
  • @John:如果这是一个问题,那么您的工具链中有一些东西没有生成有效的 XML。我不认为这是在属性或元素之间进行选择的理由。 (此外,您不能在用户输入周围“仅添加 CDATA 标记”,因为它可能包含 ]]&gt;!)
【解决方案2】:

属性的一些问题是:

  • 属性不能包含多个值(子元素可以)
  • 属性不易扩展(以备将来更改)
  • 属性不能描述结构(子元素可以)
  • 属性更难被程序代码操作
  • 属性值不容易针对 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

【讨论】:

  • 第一点不正确,见:w3.org/TR/xmlschema-2/#derivation-by-list
  • 我想说第一点是正确的,list 是这个问题的部分解决方法。不能有多个同名的属性。 list 属性仍然只有一个值,它是一些数据类型的空格分隔列表。分隔字符是固定的,因此如果所需数据类型的单个值可以包含空格,则不能有多个值。这排除了在一个“地址”属性中包含多个地址的可能性。
  • '属性更难被程序代码操纵' - 不能同意那个。事实上,我发现事实恰恰相反。真正说明任何一种方式都没有足够的区别。
  • 我还要补充一点,针对 DTD 的验证不再真正相关,对于 XML-Schema、Schematron 和 Relax 等。人。所有这些都提供了更强大且在某些情况下更直观的验证 XML 文档的方法。另外,W3Schools is a really poor reference for anything
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    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>
    

    【讨论】:

      【解决方案5】:

      这可能取决于您的使用情况。用于表示从数据库生成的结构化数据的 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 最有用的是它可以在不破坏现有代码的情况下使用它。

      【讨论】:

      • 关于“条码”的好点,我匆匆举了我的例子,肯定会把它分解成它自己的元素。在 XSD/DTD 上也有好处。
      【解决方案6】:

      关于属性与元素,我在架构设计中使用以下准则:

      • 为长时间运行的文本使用元素(通常是字符串或 normalizedString 类型)
      • 如果有两个值的分组(例如 元素的 eventStartDate 和 eventEndDate)。在前面的例子中, “事件”应该有一个新元素,其中可能包含开始日期和 endDate 属性。
      • 营业日期、日期时间和数字(例如计数、金额和费率)应为 元素。
      • 非业务时间元素,如上次更新、到期时间应为 属性。
      • 哈希码和索引等非商业数字应该是属性。*如果类型复杂,请使用元素。
      • 如果值是简单类型且不重复,则使用属性。
      • xml:id 和 xml:lang 必须是引用 XML 架构的属性
      • 在技术上可行时优先选择属性。

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

      • 唯一(属性不能出现多次)
      • 顺序无关紧要
      • 上述属性是可继承的(这是当前模式语言中“全部”内容模型不支持的)
      • 好处是它们不那么冗长并且占用的带宽更少,但这并不是更喜欢属性而不是元素的真正理由。

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

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

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

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

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

          <foo title="bar"/>;
          

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

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

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

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

          【讨论】:

            【解决方案9】:

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

            XML 的设计目的不是为了紧凑,而是为了便于移植和人类可读。如果您想减少传输中数据的大小,请使用其他内容(例如 google's protocol buffers)。

            【讨论】:

            • 更小的 XML 文本更易于阅读,因为它更小!
            【解决方案10】:

            百万美元的问题!

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

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

            【讨论】:

              【解决方案11】:

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

              1. 哪种表示会导致更快的数据解析\生成?

              2. 哪种表示可以加快数据传输速度?

              3. 可读性重要吗?

                ...

              【讨论】:

                【解决方案12】:

                将元素用于数据,将属性用于元数据(关于元素数据的数据)。

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

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

                【讨论】:

                  【解决方案13】:

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

                  XML 是出了名的笨重。对于传输和存储,如果您负担得起处理能力,强烈建议进行压缩。 XML 压缩得很好,有时甚至非常好,因为它具有重复性。我已经将大文件压缩到其原始大小的 5% 以下。

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

                  【讨论】:

                    【解决方案14】:

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

                    例如我更喜欢.....

                    <?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>
                    

                    【讨论】:

                    • 恐怕这是完全错误的——你应该遵循 W3C 的指导方针:w3schools.com/DTD/dtd_el_vs_attr.asp——XML 不应该在可读性或使其“紧凑”的情况下形成——而是正确地使用元素或属性它们的设计目的。
                    • 对不起,这是误导。 W3schools 页面不是 W3C 指南。 W3C XML 推荐(我是其中的参与者)允许根据用户的需求和风格使用元素和属性。
                    【解决方案15】:

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

                    凡是直觉上有意义的对象都应该作为元素。它的属性(或属性)将是 xml 中这些元素的属性或具有属性的子元素。

                    我认为对于示例中的面向对象类比等更简单的情况,可以确定哪个是元素,哪个是元素的属性。

                    【讨论】:

                      【解决方案16】:

                      只是对一些错误信息的一些更正:

                      @John Ballinger:属性可以包含任何字符数据。 & " ' 需要分别转义为 < > & " 和 ' 。如果您使用 XML 库,它将为您处理。

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

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

                      使用属性可以使 XML 与 JSON 保持竞争力。请参阅Fat Markup: Trimming the Fat Markup Myth one calorie at a time

                      【讨论】:

                      • 不只是 ID 或名称。它们可以包含几乎所有内容的空格分隔列表。
                      • @JohnSaunders IDS 或 NAMES 是特定的 DTD 类型(我认为也是 XML Schema),大多数 XML 处理器都在低级别支持。如果由应用层而不是 XML 库处理,则任何类型的字符数据都可以工作(分隔值或其他)。
                      • 就个人而言,你可以并不意味着你应该。
                      • @Lankymart 正如我所说,我只是在纠正一些不正确的信息(由于某种原因得分很高)。二进制数据通常根本不属于 XML。
                      【解决方案17】:

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

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

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

                      这样写的 XML 模式很简洁。

                      每当我看到像&lt;car&gt;&lt;make&gt;Ford&lt;/make&gt;&lt;color&gt;Red&lt;/color&gt;&lt;/car&gt; 这样的案例时,我都会想:“哎呀,作者是否认为 make 元素中会有子元素?” &lt;car make="Ford" color="Red" /&gt; 可读性更强,毫无疑问如何处理空格等。

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

                      【讨论】:

                      • 我能读到的少数解释之一。不知道这是否是个好主意......但至少我明白这一点;)
                      • &lt;color roof="black" doors="red"/&gt;
                      【解决方案18】:

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

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

                      如果您只是将纯数据作为 XML,则存在不太明显的区别。数据可以位于标记之间或作为属性。

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

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

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

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

                      【讨论】:

                        【解决方案19】:

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

                        【讨论】:

                          【解决方案20】:

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

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

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

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

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

                          【讨论】:

                            猜你喜欢
                            • 2014-06-19
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2020-05-14
                            • 2016-10-03
                            • 2011-03-04
                            • 1970-01-01
                            相关资源
                            最近更新 更多