How to make either of the fields mandatory in XML schema

ぐ巨炮叔叔 提交于 2019-12-31 07:53:09

问题


I have a schema as shown below ,i have a few questions regarding the schema

1.How to make CourierNumber or WorkLocationCoordinate mandatory.I have used one global type shown below

EDIT Still no luck as Abel mentioned i modifed schema but it is failing.The input xml is

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

And the schema is

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

But i am getting error as shown below Not valid.

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.

My main requirement is either ParcelNumber or WorkLocationCoordinateType should present,what went wrong?


回答1:


1.How to make CourierNumber or WorkLocationCoordinate mandatory.I have used one global type shown below

In your given code, these two definitions are not close together (one is at the 2nd child level, the other is deeply nested) so I have some trouble understanding what you mean by this.

It is not possible to have two elements at the same level (same XPath) with the same name but different types. If you try it, you would get (depending on your XSD parser):

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

If you can use XSD 1.1, you can work around this by using assertions. Since the only information in WorkArea is the coordinates, I assume you mean to switch between either CourierNumber in first position, or WorkArea in second position, but not both (really, it would have helped to show an instance document with the variants you want).

If so how to apply the type in element name CourierNumber and WorkLocationCoordinate since 'CourierNumber' already contains type xsd:unsignedShort

This is where your real issue lies. Since you do not use named types (everything is one big element with anonymous complex type definitions), you cannot reference those types. One solution is to repeat the definitions, but this can become tedious and has its limitations.

The solution I provide you below simply refactors your code into a "type first" approach. That is, instead of one big (hard to read) element definition, you get small chunks of named type definitions. Opinions may vary, but I believe this is more readable, and it's definitely more flexible. A 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>

This validates either this:

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

Or this:

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



回答2:


You need to modify the definition of the "CourierNumber" element to include the required attribute. Update this code:

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

to this:

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

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

If you define the type of your element inline you can't name it so remove the type="WorkLocationCoordinate" attribute (and then the name="WorkLocationCoordinate" attribute as well).

If you want to use those attributes then you need to separate element and type definition e.g. <xsl:element name="WorkLocationCoordinate" type="WorkLocationCoordinate"/> and <xsl:complexType name="WorkLocationCoordinate">...</xsl:complexType>.

For more information on the error you mention in the comments, see the type attribute cannot be present with either simpleType or complexType



来源:https://stackoverflow.com/questions/33183835/how-to-make-either-of-the-fields-mandatory-in-xml-schema

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!