ChatGPT解决这个技术问题 Extra ChatGPT

XML 属性与 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 文档的结构时,您应该如何决定何时使用属性或元素?

我发现这个非常好的资源:ibm.com/developerworks/xml/library/x-eleatt.html
+1 表示“......辩论是关于什么是元数据。”
请注意带有连字符的小写标记名称:stackoverflow.com/questions/1074447/…

C
CMircea

我使用这个经验法则:

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

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

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

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

我通读了一些答案,根据我的经验,没有得到足够强调的是,如果您在“属性”中数据并且突然有 > 或 < 您的 XML 文档将会中断,我认为有五个 ascii 字符 (>, <, &, ?,") 会杀死它。如果这个特殊字符在一个元素中,你可以简单地在这个数据周围添加一些 CDATA 标记。我想说,只有当你 100% 知道要放置什么值时才使用属性在那里,例如,整数或日期,可能是计算机生成的任何东西。如果条形码是由人生成的,那么它不应该是属性。
真的迟到了,但是特殊的 ASCII char 参数是错误的——这就是转义的目的,对于属性和文本数据都是如此。
@donroby - 对不起,那是我沟通的错误。通过转义,我的意思是 XML 编码。 '<' = <等等。对我来说,根据构成内容的字符而不是内容的含义来决定属性或元素似乎很奇怪。
@donroby:这是不正确的。 &lt; 的替换文本是 &#60;,它是字符引用,而不是实体引用。 &lt; 在属性上是可以的。请参阅:w3.org/TR/REC-xml/#sec-predefined-ent
@John:如果这是一个问题,那么您的工具链中有一些东西没有产生有效的 XML。我不认为这是在属性或元素之间进行选择的理由。 (此外,您不能在用户输入周围“仅添加 CDATA 标记”,因为它可能包含 ]]>!)
g
gorn

属性的一些问题是:

属性不能包含多个值(子元素可以)

属性不易扩展(以备将来更改)

属性不能描述结构(子元素可以)

属性更难被程序代码操作

属性值不容易针对 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
d
dan04

“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 不是用作标记语言,而是用作数据序列化语言时,就会出现混淆,其中“数据”和“元数据”之间的区别更加模糊。所以元素和属性之间的选择或多或少是任意的,除了不能用属性表示的东西(见芬斯特的回答)。


对我来说,属性和元素之间的区别非常清楚:属性允许执行处理,而元素为从 XML 文档生成的数据对象带来语义值。
k
kjhughes

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>

A
AnthonyWJones

这可能取决于您的使用情况。用于表示从数据库生成的结构化数据的 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 上也有好处。
A
Archimedes Trajano

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

对长时间运行的文本使用元素(通常是字符串或规范化字符串类型的元素)

如果一个元素有两个值(例如 eventStartDate 和 eventEndDate)的分组,则不要使用属性。在前面的示例中,“event”应该有一个新元素,其中可能包含 startDate 和 endDate 属性。

业务日期、日期时间和数字(例如计数、金额和比率)应该是元素。

非业务时间元素,如 last updated、expires on 应该是属性。

哈希码和索引等非业务数字应该是属性。* 如果类型很复杂,请使用元素。

如果值是简单类型且不重复,则使用属性。

xml:id 和 xml:lang 必须是引用 XML 模式的属性

在技术上可能的情况下首选属性。

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

唯一(属性不能出现多次)

顺序无所谓

上述属性是可继承的(这是“所有”内容模型在当前模式语言中不支持的东西)

好处是它们不那么冗长并且占用的带宽更少,但这并不是更喜欢属性而不是元素的真正理由。

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

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


L
Luke

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


p
peter.murray.rust

这个问题没有统一的答案(我大量参与了 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 这很丑陋并且可能令人困惑。


P
Patrick

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

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


更小的 XML 文本更易于人类阅读,因为它更小!
A
Adam

百万美元的问题!

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

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


C
Community

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

哪种表示导致更快的数据解析\生成?哪种表示会导致更快的数据传输?可读性重要吗? ...


M
Michael J

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

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

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


e
erickson

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

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

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


R
Rory Becker

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

比如我更喜欢......

<?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 推荐(我是其中的参与者)允许根据用户的需要和风格使用元素和属性。
r
rpattabi

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

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

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


b
brianary

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

@John Ballinger:属性可以包含任何字符数据。 < > & " ' 需要分别转义为 < > & " 和 ' 。如果您使用 XML 库,它会为您解决这个问题。

地狱,一个属性可以包含二进制数据,如图像,如果你真的想要,只需通过 base64 编码并将其设为 data: 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。
M
MGrier

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

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

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

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

每当我看到像 <car><make>Ford</make><color>Red</color></car> 这样的情况时,我都会想“哎呀,作者认为 make 元素中会有子元素吗?” <car make="Ford" color="Red" /> 更具可读性,毫无疑问如何处理空格等。

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


我能读到的为数不多的解释之一。不知道这是否是个好主意……但至少我明白这一点;)
<color roof="black" doors="red"/>
W
Walter A. Jablonowski

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

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

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

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

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

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

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


o
ottodidakt

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


o
oh pot

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

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

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

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

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