22

这是一个 XML 模式问题。

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

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

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

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

重要提示:添加和删除可能只出现一次,但它们的顺序无关紧要:

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

但不是:

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

5 回答 5

17

如果我理解您的要求,您的要求是正确的,那么您唯一缺少的就是您选择的 maxOccurs="unbounded" 。

我创建了以下架构:

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

它适用于

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

但不是为了

<ns0:Root xmlns:ns0="http://someNamespace">
  <ns0:ADD />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:DELETE />
</ns0:Root>
于 2009-01-06T10:15:05.190 回答
6

我认为您正在寻找“全部”元素,它允许无序列表。但是,您可以在其中放置的元素受到限制。请参阅http://www.w3.org/2005/07/xml-schema-patterns.html#Collection

于 2010-02-05T13:00:36.157 回答
6

很抱歉,您已经为这个问题苦苦挣扎了 7 年,却没有任何答案。

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

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

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

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

这是一个支持 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>

示例 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>

这是一个嵌套在占位符标记中的命令。“命令分组.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>

示例 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>

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

于 2016-06-06T16:29:30.677 回答
3

我不相信如果不枚举 ADD、DELETE 等的每个组合就可以做到这一点。一般来说,无论是使用 DTD 还是模式,无序列表都不能很好地发挥作用。

于 2009-01-08T00:32:30.920 回答
3

您可以使用序列类型实现无序列表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>

通过这种方式,您可以限制用户在元素内使用他们想要的任何标签,<NAME/>但允许他们尽可能频繁<ADD/>地使用。<DELETE/>

于 2014-11-26T10:53:05.857 回答