如何在XML模式中使任一字段成为必需字段

时间:2015-10-17 07:00:36

标签: asp.net xml xsd

我有一个如下所示的架构,我有一些关于架构的问题

1.如何强制CourierNumberWorkLocationCoordinate。我使用了下面显示的一种全局类型

修改 仍然没有运气,因为Abel提到我修改了架构,但它失败了。输入xml是

<?xml version="1.0" encoding="utf-8"?>
<NOCPlantMapRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <NOCTypeID>0</NOCTypeID>
  <WorkLocation>
    <ParcelNumber>4545</ParcelNumber>
    <Roads>
      <WorkLocationRoad>
        <RoadName>dubai road</RoadName>
      </WorkLocationRoad>
    </Roads>
    <WorkArea>
      <WorkArea>
        <Coordinates>
          <WorkLocationCoordinate>
            <CoordinateX>56</CoordinateX>
            <CoordinateY>23</CoordinateY>
          </WorkLocationCoordinate>
        </Coordinates>
        <Communities />
      </WorkArea>
    </WorkArea>
  </WorkLocation>
</NOCPlantMapRequest>

模式是

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    attributeFormDefault="unqualified"
    elementFormDefault="qualified">
  <xsd:element name="NOCPlantMapRequest">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="NOCReference" minOccurs="0" type="xsd:string" />
        <xsd:element name="NOCTypeID" minOccurs="0" type="xsd:unsignedByte" />
        <xsd:element name="NOCTypeName" minOccurs="0" type="xsd:string" />
        <xsd:element name="ApplicationName" minOccurs="0" type="xsd:string" />
        <xsd:element name="Applicationtype" minOccurs="0" type="xsd:string" />
        <xsd:element name="RelatedNOCRefNumber" minOccurs="0" type="xsd:string" />
        <xsd:element name="WorkLocation" minOccurs="1" maxOccurs="1"  type="LocationType">
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:complexType name="LocationType">
    <xsd:choice>
      <xsd:sequence>
        <xsd:element name="ParcelNumber" type="ParcelNumberType" />
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element name="WorkArea" type="WorkAreaType" />
      </xsd:sequence>
    </xsd:choice>
  </xsd:complexType>
  <xsd:simpleType name="ParcelNumberType">
    <xsd:restriction base="xsd:string"/>
  </xsd:simpleType>
  <xsd:complexType name="WorkAreaType">
    <xsd:sequence>
      <xsd:element name="WorkArea" minOccurs="0" maxOccurs="unbounded">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="Coordinates" minOccurs="1" type="CoordinatesType" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="CoordinatesType">
    <xsd:sequence>
      <xsd:element name="WorkLocationCoordinate" type="WorkLocationCoordinateType"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="WorkLocationCoordinateType">
    <xsd:sequence>
      <xsd:element name="CoordinateX" type="xsd:string" />
      <xsd:element name="CoordinateY" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

但我收到的错误如下所示 无效。

Error - Line 6, 12: org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 12; cvc-complex-type.2.4.d: Invalid content was found starting with element 'Roads'. No child element is expected at this point.
Error - Line 19, 24: org.xml.sax.SAXParseException; lineNumber: 19; columnNumber: 24; cvc-complex-type.2.4.d: Invalid content was found starting with element 'Communities'. No child element is expected at this point.

我的主要要求是ParcelNumberWorkLocationCoordinateType应该出现,出了什么问题?

2 个答案:

答案 0 :(得分:4)

  

1.如何强制使用CourierNumber或WorkLocationCoordinate。我使用了下面显示的一种全局类型

在你给定的代码中,这两个定义并不紧密相关(一个是在第二个子级别,另一个是深度嵌套的)所以我在理解你的意思时遇到了一些麻烦。

不可能在同一级别(相同的XPath)具有两个具有相同名称但不同类型的元素。如果您尝试它,您将获得(取决于您的XSD解析器):

E [Xerces] cos-element-consistent: Error for type 'LocationType'. 
Multiple elements with name 'WorkArea', with different types, appear in the model group.

如果您可以使用XSD 1.1,则can work around this by using assertions。由于WorkArea中的唯一信息是坐标,我认为您的意思是在第一个位置CourierNumber或第二个位置WorkArea之间切换,但不能同时切换两个(实际上,它会有帮助显示了包含您想要的变体的实例文档。

  

如果是这样,如何在元素名称CourierNumber和WorkLocationCoordinate中应用类型,因为'CourierNumber'已经包含类型xsd:unsignedShort

这是你真正的问题所在。由于您不使用命名类型(一切都是具有匿名复杂类型定义的大元素),因此您无法引用这些类型。一种解决方案是重复定义,但这可能变得乏味并且有其局限性。

我在下面提供的解决方案只是将您的代码重构为“类型优先”方法。也就是说,您可以获得一小块命名类型定义,而不是一个大的(难以阅读的)元素定义。意见可能会有所不同,但我相信这更具可读性,而且它肯定更灵活。一个good introduction of this approach and what its drawbacks and features are can be found on XFront

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified">

    <!-- belonging to SO question https://stackoverflow.com/questions/33183835/how-to-make-either-of-the-fields-mandatory-in-xml-schema -->

    <xsd:complexType name="CoordinatesType">
        <xsd:sequence>
            <xsd:element name="WorkLocationCoordinate" type="WorkLocationCoordinateType"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:simpleType name="CourierNumberType">
        <xsd:restriction base="xsd:unsignedShort"/>
    </xsd:simpleType>

    <xsd:complexType name="WorkLocationCoordinateType">
        <xsd:sequence>
            <xsd:element name="CoordinateX" type="xsd:unsignedByte" />
            <xsd:element name="CoordinateY" type="xsd:unsignedByte" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="WorkAreaType">
        <xsd:sequence>
            <xsd:element name="WorkArea">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="Coordinates" type="CoordinatesType" />
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="LocationType">
        <xsd:choice>
            <xsd:sequence>
                <xsd:element name="CourierNumber" type="CourierNumberType" />
                <xsd:element name="Roads" />
            </xsd:sequence>
            <xsd:sequence>
                <xsd:element name="Roads" />
                <xsd:element name="WorkArea" type="WorkAreaType" />
            </xsd:sequence>
        </xsd:choice>
    </xsd:complexType>

    <xsd:element name="Request">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="Location" type="LocationType" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

这证实了这一点:

<Request>
    <Location>
        <CourierNumber>12</CourierNumber>
        <Roads></Roads>
    </Location>
</Request>

或者这个:

<Request>
    <Location>
        <Roads></Roads>
        <WorkArea>
            <WorkArea>                
                <Coordinates>
                    <WorkLocationCoordinate>
                        <CoordinateX>34</CoordinateX>
                        <CoordinateY>66</CoordinateY>
                    </WorkLocationCoordinate>
                </Coordinates>
            </WorkArea>
        </WorkArea>
    </Location>
</Request>

答案 1 :(得分:0)

您需要修改“CourierNumber”元素的定义以包含必需的属性。更新此代码:

 <xsd:element name="CourierNumber" type="xs:string"/>

到此:

   <xsd:element name="CourierNumber">
   <xsd:complexType>
   <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="Option" type="xsd:string" use="required"/>
    </xsd:extension>
    </xsd:simpleContent>
    </xsd:complexType>
   </xsd:element>

来自Element-Mandatory Attribute declaration in XSD Schema

的参考资料
       <xsd:element name="Coordinates"> 
        <xsd:complexType> 
          <xsd:sequence> 
            <xsd:element name="WorkLocationCoordinate" 
             type="Test" minOccurs="1" maxOccurs="99"
             />
            </xsd:sequence> 
        </xsd:complexType> 
       </xsd:element> 
      <xsd:complexType name="Test">
    <xsd:sequence>
      <xsd:element name="CoordinateX" type="xsd:unsignedByte" />
      <xsd:element name="CoordinateY" type="xsd:unsignedByte" />
         </xsd:sequence>
          </xs:complexType>

如果您定义内联元素的类型,则无法为其命名,因此请删除type="WorkLocationCoordinate"属性(以及name="WorkLocationCoordinate"属性)。

如果要使用这些属性,则需要分离元素和类型定义,例如<xsl:element name="WorkLocationCoordinate" type="WorkLocationCoordinate"/><xsl:complexType name="WorkLocationCoordinate">...</xsl:complexType>

有关您在评论中提及的错误的详细信息,请参阅the type attribute cannot be present with either simpleType or complexType