xml - 具有多个可选子元素和公共(public)必需元素的 xsd

标签 xml xsd

我正在尝试为以下需要创建并提供给某些遗留代码的 XML 创建一个 xsd。该产品已经推出,我没有更改 xml 定义的选项。目标是保持兼容性创建单元测试以确保模式符合遗留期望。 (注意:我对创建 xsd 还很陌生,但过去经常使用它们)。

系统必须为预期的错误条件创建以下简化结构之一:

<Customer>
    <CustomerNumber>A12</CustomerNumber>
    <ErrorText>Some kind of error description</ErrorText>
</Customer>

当成功找到客户时,它期望:

<Customer>
    <CustomerNumber>A12</CustomerNumber>
    <Name>data</Name>
    <Address>data</Address>
    <City>data</City>    
</Customer>

我已经尝试过各种 xsd 方法,下面是我最后一次使用组的尝试。每次我基本上以 Multiple definition of element 'CustomerNumber' 导致内容模型变得不明确。必须形成一个内容模型,以便在元素验证期间......

一个解决方案是将其分成两个单独的 xsd 文件并选择合适的文件用于单元测试验证,在我这样做之前,有没有办法在顶级元素中包含可选元素?

<xs:group name="missinggroup">
    <xs:sequence>
       <xs:element name="CustomerNumber" type="xs:string" minOccurs="1" maxOccurs="1" />
       <xs:element name="ErrorText" type="xs:string" minOccurs="1" maxOccurs="1" />
    </xs:sequence>
</xs:group>

<xs:group name="foundgroup">
    <xs:sequence>
       <xs:element name="CustomerNumber" type="xs:string" minOccurs="1" maxOccurs="1" />
       <xs:element name="Name" type="xs:string" minOccurs="0" maxOccurs="1" />
       <xs:element name="Address" type="xs:string" minOccurs="0" maxOccurs="1" />
       <xs:element name="City" type="xs:string" minOccurs="0" maxOccurs="1" />
     </xs:sequence>
</xs:group>

<xs:element name="Customer">
    <xs:complexType>
      <xs:choice>
         <xs:group ref="missinggroup" />
         <xs:group ref="foundgroup" />
      </xs:choice>
    </xs:complexType>
</xs:element>

已经尝试过的另一种选择是:

<xs:element name="Customer">
    <xs:complexType>
      <xs:choice>
         <xs:element name="CustomerNumber" type="xs:string" minOccurs="1" maxOccurs="1" />
         <xs:group ref="missinggroup" />
         <xs:group ref="foundgroup" />
      </xs:choice>
    </xs:complexType>
</xs:element>

最佳答案

你几乎已经解决了这个问题。如果您查看您的类型,您可以找到问题的原因。这些是模棱两可的,因为任何一组都不允许处理器通过查看第一个元素来查看哪条路径是正确的,因此是错误的。

现在,在两个选项中<CustomerNumber>是必需的,以便可以从选择中删除。如果这样看,您可以将其视为 <CustomerNumber> 的序列。其次是选择。这可以在 XML Schema 中构建为:

<xs:element name="Customer">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="CustomerNumber" type="xs:string"/>
        <xs:choice>
          <xs:element name="ErrorText" type="xs:string"/>
          <xs:sequence>
            <xs:element name="Name" type="xs:string"/>
            <xs:element name="Address" type="xs:string"/>
            <xs:element name="City" type="xs:string"/>
          </xs:sequence>
        </xs:choice>
      </xs:sequence>
  </xs:complexType>
</xs:element>

minOccurs 的默认值和 maxOccurs都是 1,所以为了清楚起见,我删除了它们。您可能还需要 <Name> , <Address><City>发生一次,否则你只允许选择 <CustomerNumber>发生,所以我也将它们设置为 1。

这是满足您要求的最简单的架构。在现实世界中,我可能会编写多个顶级定义并引用它们,因为它使模式更易于维护,但这对您来说可能不是问题。我更喜欢这样的东西:

<xs:element name="Customer">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="CustomerNumber"/>
        <xs:choice>
          <xs:element ref="ErrorText"/>
          <xs:group ref="AddressGroup"/>
        </xs:choice>
      </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="CustomerNumber" type="xs:string"/>    
<xs:element name="ErrorText" type="xs:string"/>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Address" type="xs:string"/>   
<xs:element name="City" type="xs:string"/>

<xs:group name="AddressGroup">
    <xs:sequence>
        <xs:element ref="Name"/>
        <xs:element ref="Address"/>
        <xs:element ref="City"/>    
    </xs:sequence>
</xs:group>

这更易于重用和维护,但如果您使用的是遗留应用程序,则更改的可能性较小,您可以使用简单版本。

关于xml - 具有多个可选子元素和公共(public)必需元素的 xsd,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22600782/

相关文章:

xml - 如何排除 XSD 中的根元素?

javascript - 数组被覆盖

Web服务中的java/soapfault问题

c# - 如何使用 C# 将 XML 解析为 lisp 的 S-Expression?

java - String类型的Xml数据

java - JaxB - 如何不映射特定的 XML 节点

java - JAXB 问题 : nameXmlTransform typeName prefix not working

xml - 原子提要中的自定义标签

java - 用 Java 生成 XML 内容的正确方法是什么?

java.lang.NoClassDefFoundError java 中的异常