【问题标题】:In XML Schema, why does an element group tag even exist?在 XML Schema 中,为什么还存在元素组标记?
【发布时间】:2014-10-09 01:27:58
【问题描述】:

据我了解,group 用于创建以后可以引用的命名序列(选择、序列、全部)。

但是,当complexType 可以用来完成同样的事情并且功能更强大时,为什么还要这样做呢?这不是很不干燥吗?更不用说group 标记本质上既可以作为类型的定义,同时也可以作为对该类型的引用,具体取决于您使用的是ref 还是name 属性。这不是非常令人困惑和不必要的吗?还是我错过了什么重要的东西?

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    命名元素和属性组(xs:groupxs:attributeGroup)非常重要。

    实际上,它们允许您定义一种代理 complexTypes,但不受实际 complexTypes 的限制。

    xs:complexType 的限制

    假设您像这样定义基本的 complexType:

    <xs:complexType name="Base">
      (base element model)
    </xs:complexType>
    

    然后,您想在您的 XML 模式中重用 (base element model), 您只能通过像这样导出其他 complexTypes 来做到这一点:

    <xs:complexType name="Derived">
      <xs:complexContent>
        <xs:extension base="Base">
          (extension element model)
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
    

    但是当一个 complexType 被扩展时,新元素会作为序列添加到基础元素中。新的内容模型如下所示:

    (base element model), (extension element model)
    

    你不能有任何不同(例如,将扩展元素放在基本元素的前面)。这就是 XSD 中类型扩展的工作原理!

    在这里,我可以停下来,说 XSD 语言就是这样设计的。 但是,问题仍然存在。为什么会这样设计? 为什么 XSD 中 complexTypes 的派生不能更方便? 原因是这样的: 派生类型必须符合基类型。 你不能有任何东西作为基础的延伸!

    假设您有一个知道如何处理A 类型元素的软件。 软件可能会假设实际上A 类型可能会被扩展,但无论如何, 它必须能够在一个应该是A 类型的元素中找到它知道/期望来自A 类型的所有内容... 并且类型 A 所固有的元素内容必须排在第一位!

    因此,使用 complexType 派生,您无法生成具有如下内容模型的 Derived 类型:

    (extension element model), (base element model)
    

    也就是说,将扩展元素放在基础元素的前面。

    再次,您可能想知道为什么?也许,软件可以做得更复杂,甚至可以解决这个问题?

    也许吧。但这违反了 XSD 语言中的基本原则之一:任何元素内容模型都必须是确定性。 这意味着对于任何元素序列,必须始终可以使用单通道识别特定的内容模型(在 XML 模式中定义)。 如果软件只知道A 类型,它必须首先以某种方式传递(extension element model) 的元素才能找到它知道如何处理的内容。当然,这不可能是确定性的!

    xs:group 如何拯救世界

    当你定义一个组时,它不应该表现得像一个独立的 complexType(能够被分配给元素作为它们的类型)。 它只是一个可以在其他地方重复使用的内容模型。

    您想将扩展元素放在基础元素之前吗?没问题! 只需将Base 定义为一个组:

    <xs:group name="Base">
      (my base element model)
    </xs:group>
    

    然后,您可以像这样导出您的Derived complexType:

    <xs:complexType name="Derived">
      <xs:sequence>
        (my extension element model)
        <xs:group ref="Base"/>
      </xs:sequence>
    </xs:complexType>
    

    【讨论】:

    • 谢谢。非常好的点。本质上,complexType 缺乏该组所拥有的内联替换能力。
    【解决方案2】:

    当您提出“为什么”的问题时,有两种可能的回答方式:(a) 委员会指定此功能时的想法,以及 (b) 我为什么要使用此功能?即使您是委员会成员,回答 (a) 也可能非常困难;回答(b)通常更容易。有时答案是,永远不要尝试使用此功能:XSD 中肯定有一些类似的东西,但命名模型组不是其中之一。

    本质上,它是一种重用和模块化机制。如果您有 17 个不同的元素,并且每个元素都可以以 Note、Author 和/或 DateCreated 中的任何一个或多个元素结尾,那么将这三个元素放入一个组中并引用该组会在添加第 18 个元素时更容易具有相同模式的元素,或者当您想要添加 DateModified 作为附加选项时。模型组也可以是 xs:redefines 的目标 - 尽管我会尽可能避免使用重新定义。

    根据是否存在@name 或@ref 属性,使用具有不同含义的一个元素名称(xs:group)的设计是您喜欢或不喜欢的东西。 (他们为什么把前门漆成红色?回答,他们喜欢那样。) XML 没有严格的设计规则,不同的人会做出不同的设计选择,这没什么大不了的。在 XSD 的具体语法设计中,还有比这更糟糕的事情要抱怨。

    【讨论】:

    • 谢谢,迈克尔。我现在看到了它的用处,并且我明白所有的设计决策都是按照惯例做出的,或者有时是个人喜好。我没有选择你的答案的唯一原因是因为另一个答案更深入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多