【问题标题】:Why is node order important in XML?为什么节点顺序在 XML 中很重要?
【发布时间】:2011-09-16 18:01:00
【问题描述】:

我最近一直在处理一个 API,它要求 XML 文档的节点按特定顺序排列。我想知道为什么当我完全找不到事情应该这样的原因时,他们为什么觉得有必要强制执行。

例如,这是正确的(大大简化了xml)

<transaction>
    <address>1 main st</address>
    <amount>100</amount>
    <orderId>1234</orderId>
</transaction>

但这会返回错误

<transaction>
    <address>1 main st</address>
    <orderId>1234</orderId>
    <amount>100</amount>
</transaction>

起初我认为这样他们就可以以列表/数组的形式存储东西,并让索引始终引用同一个节点。我理解为什么按照in this question 的解释,以相同的顺序发送具有相同名称的兄弟节点很重要。但是,有些节点可以省略:

<transaction>
    <amount>100</amount>
    <orderId>1234</orderId>
</transaction>

因此,在第三个示例中,amount 和 orderId 现在将位于 [0] 和 [1] 而不是第一个(正确)示例中的 [1] 和 [2]。

另一种想法是他们将 XML 处理为字符串并要求他们始终知道哪些节点彼此接连出现,但同样由于允许省略节点,该理论没有意义。

谁能向我解释为什么我给节点的顺序很重要?还是我只是在处理一个陈旧且脾气暴躁的 API?

【问题讨论】:

  • 我不明白这里的反对票或接近票。

标签: xml xsd


【解决方案1】:

节点顺序在 XML 中显然很重要,如下所示:

<p>
   <span>This wouldn't make much sense</span>
   <span>if the order of these nodes were reversed.</span>
</p>

在 XML 中不像您提供的那样明显,这似乎是某种序列化格式。但是,如果属性设置不正确,则其属性设置器具有副作用的对象可能会失败。

想象一个具有私有Person 字段的类,该字段公开PersonIDName 属性。 PersonID 设置器创建Person 的私有实例,Name 设置器在私有Person 字段上设置Name 属性。在这种情况下,在设置PersonID 之前设置Name 会失败,因为Person 尚不存在。

在这种情况下,在 XML 中实现一个要求 PersonID 出现在 Name 之前的架构可以防止发生此错误,但代价是迫使其他开发人员做一些显然是荒谬的事情。

在这种情况下,显而易见的事情就是找到编写该类的开发人员并击败他。这几乎是不可能的,尽管思考它所处的世界很有趣。

【讨论】:

    【解决方案2】:

    XML 节点顺序很重要的一个原因是应用程序在何处使用流解析器。具有按预期顺序的依赖元素可以使应用程序更有效地处理 XML 数据。对于处理大规模 XML 数据的应用程序尤其如此。

    【讨论】:

      【解决方案3】:

      答案在于XML-DTD/Schema。 API 中如此定义的底层架构会导致错误。虽然我想我不想在这里教 XML,但看看下面的内容就会清楚。

      XML有两点需要考虑:

      • 格式良好的 XML: 完美的语法
      • 有效的 XML: 完全适用于 DTD(文档类型定义)/架构

      关于 DTD 的要点: 根据您的问题建议的 DTD:

      <!DOCTYPE transaction
      [
      <!ELEMENT address (#PCDATA)>
      <!ELEMENT amount (#PCDATA)>
      <!ELEMENT orderid (#PCDATA)>
      ]>
      

      以上是根据您在问题中提供的结构建议的 DTD。由于您正在处理特定的 API,因此它已经在其中定义了这种类型的结构。 XML 模式 可以替代它。

      关于 XML Schema 的要点:

      <xs:element name="transaction">    
      <xs:complexType>
        <xs:sequence>
          <xs:element name="address" type="xs:string"/>
          <xs:element name="amount" type="xs:string"/>
          <xs:element name="orderid" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>
      </xs:element>
      

      目前,XML 模式被使用而不是 DTD,因为它们在为用户定义数据结构和提供面向对象的方法方面要优越得多

      【讨论】:

      • +1 您能否举例说明如何修改 DTD 和模式以使 addressamountorderid 按任何顺序有效?会是更复杂的 DTD/模式吗?如果是这样,那么这可能是开发人员强制执行命令的原因之一......
      • 排序的答案在于这些文件是从 TAG 解析到 TAG 的。解析文件的相关应用程序将按照模式中提供的顺序解析文件。好吧,如果您构建自定义解析器库,您绝对可以更改排序.. 只是为了使解析逻辑更复杂!
      【解决方案4】:

      代码依赖于元素的顺序更快更简单。

      当允许任意顺序时,它还可以防止某些歧义问题。

      此外,XML 对人类读者的意义不如它对计算机程序消费的意义。计算机不介意按顺序做事。

      【讨论】:

      • 但我的问题是开发人员/库是否需要更多的努力来验证元素的正确顺序?
      • 验证它可能需要更多的努力,但要假设订单。
      【解决方案5】:

      强制订单让消费者更简单,如下所示:

      consumeTransation:
          consumeAddressIfPresent;
          consumeAmountIfPresent;
          consumeOrderIDIfPresent;
      

      更重要的是,XML Schema 用于结构定义使得订单更有可能成为一种要求。这是因为 XML Schema 对有序列表 (xs:sequence) 的支持比对无序列表 (xs:all) 的支持更丰富。后者有出现限制,更难验证,并且不能以序列的方式扩展。其中一些在 XML Schema 1.1 中得到了改进,但大多数工具/API 还没有。

      【讨论】:

        猜你喜欢
        • 2013-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多