xml XSD - 如何描述一组无序的元素类型,其中第一个元素必须首先出现在序列中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/415955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 12:16:22  来源:igfitidea点击:

XSD - How to describe an unordered set of element types where the first element must appear first in the sequence?

xmlschemaxsd

提问by ogee

This is an XML schema question.

这是一个 XML 模式问题。

I know that xsd:allelement can't appear in a sequence (must be the top level element of its type).

我知道该xsd:all元素不能出现在序列中(必须是其类型的顶级元素)。

That is, I cannot use the following:

也就是说,我不能使用以下内容:

<xsd:complexType name="Application">
  <xsd:sequence>
    <xsd:element ref="Name"></xsd:element>
    <xsd:all>
      <xsd:element ref="ADD"></xsd:element>
      <xsd:element ref="DELETE"></xsd:element>
    </xsd:all>
  </xsd:sequence>
</xsd:complexType>

My question is how to declare the "ADD" and "DELETE" elements above in any order (unordered set) but still make sure that the element "Name" would be the first and always appear. (Think of the situation where I have not only "ADD" and "DELETE" but about 10 or more unordered elements set: ADD, DELETE, EDIT etc...)

我的问题是如何以任何顺序(无序集合)声明上面的“ADD”和“DELETE”元素,但仍然确保元素“Name”是第一个并且总是出现。(想想我不仅有“添加”和“删除”而且还有大约 10 个或更多无序元素集的情况:添加、删除、编辑等...)

IMPORTANT NOTE: the ADD and DELETE may appear only ONCE, but their order is not matter:

重要提示:ADD 和 DELETE 可能只出现一次,但它们的顺序无关紧要:

<Application>
  <NAME>
   <DELETE>
   <ADD>
</Application>

but NOT:

但不是:

<Application>
  <NAME>
  <DELETE>
  <ADD>
  <DELETE> <!--cannot appear twice-->
</Application>

回答by Yossi Dahan

If I understand your request you are right on track, the only thing you're missing is maxOccurs="unbounded" on your choice.

如果我理解您的要求,您就走上了正轨,您唯一缺少的就是您选择的 maxOccurs="unbounded" 。

I created the following schema:

我创建了以下架构:

<?xml version="1.0"?>
<xs:schema targetNamespace="http://someNamespace" xmlns="http://someNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Root" type="Application">
  </xs:element>

  <xs:complexType name="Application">
    <xs:sequence>
      <xs:element ref="Name"></xs:element>
      <xs:choice maxOccurs="unbounded">
        <xs:element ref="ADD"></xs:element>
        <xs:element ref="DELETE"></xs:element>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Name"/>
  <xs:element name="ADD"/>
  <xs:element name="DELETE"/>
</xs:schema>

And it worked well for

它适用于

<ns0:Root xmlns:ns0="http://someNamespace">
  <ns0:Name />
  <ns0:ADD />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:DELETE />
</ns0:Root>

but not for

但不是为了

<ns0:Root xmlns:ns0="http://someNamespace">
  <ns0:ADD />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:DELETE />
</ns0:Root>

回答by Dirkjan Krijnders

I think you're looking for the "all" element, it allows for unordered list. However there are restrictions on the elements you can put in there. See http://www.w3.org/2005/07/xml-schema-patterns.html#Collection

我认为您正在寻找“所有”元素,它允许无序列表。但是,您可以放入的元素有限制。见http://www.w3.org/2005/07/xml-schema-patterns.html#Collection

回答by James Daily

I'm sorry you've been toiling with this problem for 7 years now with no answer.

很抱歉,您已经为这个问题苦苦挣扎了 7 年,但一直没有答案。

I'm going to help by revisiting your assumptions.

我将通过重新审视您的假设来提供帮助。

By treating "Name" as a piece of data that must come first, and requiring that it must be a child of Application, and then in general saying you don't care about the order of its siblings, you're making a confusing situation for yourself. Why is Name a sibling of ADD and DELETE if it follows different rules and serves a different purpose? If you had to model this in any other data structure, you wouldn't include "Name" in a list of things alongside "ADD" and "DELETE". You would say two things: An Application has a Name, and it also has a list of commands such as ADD and DELETE.

通过将“名称”视为必须首先出现的数据,并要求它必须是 Application 的子项,然后通常说您不关心其兄弟姐妹的顺序,您正在制造一种混乱的情况为自己。如果 Name 遵循不同的规则并用于不同的目的,为什么它是 ADD 和 DELETE 的兄弟?如果您必须在任何其他数据结构中对此进行建模,则不会在“添加”和“删除”旁边的内容列表中包含“名称”。你会说两件事:一个应用程序有一个名称,它还有一个命令列表,如 ADD 和 DELETE。

Since Name is a special thing as compared to ADD and DELETE, then it should be modeled separately from those other tags.

由于与 ADD 和 DELETE 相比,Name 是一个特殊的东西,因此它应该与其他标签分开建模。

So, you can either make Name an attribute of Application, and keep Add and Delete as child elements, or you can keep Name as a child element but then surround ADD and DELETE with a placeholder/grouping tag, such as Commands. The Commands tag would be the only sibling of Name.

因此,您可以将 Name 作为 Application 的一个属性,并将 Add 和 Delete 作为子元素,或者您可以将 Name 作为子元素,然后用占位符/分组标签(例如 Commands)包围 ADD 和 DELETE。Commands 标签将是 Name 的唯一兄弟。

Here's a schema supporting Name as an attribute, with an arbitrary number of commands in any order. "Name as Attribute.xsd":

这是一个支持 Name 作为属性的模式,具有任意顺序的任意数量的命令。“命名为 Attribute.xsd”:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Application" type="Application_Type" />
    <xs:complexType name="Application_Type">
            <xs:all>
                <xs:element minOccurs="0" ref="ADD"/>
                <xs:element minOccurs="0" ref="DELETE"/>
                <xs:element minOccurs="0" ref="THIRD"/>
                <xs:element minOccurs="0" ref="FOURTH"/>
            </xs:all>
            <xs:attribute name="Name"/>
    </xs:complexType>
    <xs:element name="ADD"/>
    <xs:element name="DELETE"/>
    <xs:element name="THIRD"/>  
    <xs:element name="FOURTH"/> 
</xs:schema>

Example XML:

示例 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="text" xsi:noNamespaceSchemaLocation="Name as Attribute.xsd">
    <THIRD>text</THIRD>
    <ADD>text</ADD>
    <FOURTH>text</FOURTH>
    <DELETE>text</DELETE>
</Application>

And here's one with the commands nested within a placeholder tag. "Commands Grouping.xsd":

这是一个嵌套在占位符标签中的命令。“命令分组.xsd”:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Application" type="Application_Type"/>
    <xs:complexType name="Application_Type">
        <xs:sequence>
            <xs:element ref="Name"/>
            <xs:element name="Commands" type="Commands_Type"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Commands_Type">
        <xs:all>
            <xs:element minOccurs="0" ref="ADD"/>
            <xs:element minOccurs="0" ref="DELETE"/>
            <xs:element minOccurs="0" ref="THIRD"/>
            <xs:element minOccurs="0" ref="FOURTH"/>
        </xs:all>
    </xs:complexType>
    <xs:element name="Name"/>
    <xs:element name="ADD"/>
    <xs:element name="DELETE"/>
    <xs:element name="THIRD"/>
    <xs:element name="FOURTH"/>
</xs:schema>

Example XML:

示例 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Commands Grouping.xsd">
    <Name>text</Name>
    <Commands>
        <THIRD>text</THIRD>
        <ADD>text</ADD>
        <FOURTH>text</FOURTH>
        <DELETE>text</DELETE>
    </Commands>
</Application>

One note about either of these is that messages with zero commands are still valid message. Perhaps that's okay, but if it's a problem, perhaps that validation belongs in the Application layer rather than the XSD.

关于其中任何一个的注意事项是具有零命令的消息仍然是有效消息。也许这没问题,但如果这是一个问题,也许该验证属于应用程序层而不是 XSD。

回答by Alohci

I don't believe this can be done without enumerating every combination of ADD, DELETE etc. Generally speaking unordered lists don't play well, either with DTDs or schemas.

我不相信这可以在不枚举 ADD、DELETE 等的每个组合的情况下完成。一般来说,无序列表不能很好地发挥作用,无论是使用 DTD 还是模式。

回答by Daniel Lee

You can implement unordered lists using the sequence type xs:choice.

您可以使用序列类型实现无序列表xs:choice

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="Application"/>
  <xs:complexType>
   <xs:element name="NAME">
    <xs:sequence>
     <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="ADD" type="xs:string"/>
      <xs:element name="DELETE" type="xs:string"/>
     </xs:choice>
    </xs:element>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

This way you restrict the user from using any tag they want inside the <NAME/>element but allow them to use <ADD/>and <DELETE/>as often as they like.

这样,您就限制使用他们想要的任何内标签的用户<NAME/>元素,但允许他们使用<ADD/>,并<DELETE/>尽可能经常等。