XSD allowing both simpleType and complexType content for same element?

隐身守侯 提交于 2019-11-28 10:04:40

问题


I have a situation where I have different XMLs that will have different types of properties. Sometimes the element HEADER could have just a node or some XMLs could have elements within the HEADER node and values inside.

Example 1 (HEADER with just text):

<Details HeaderLabel="DETAILS">
   <HEADER Label="Header">2.5%</HEADER>
</Details>

Example 2 (HEADER with two child elements):

<Details HeaderLabel="DETAILS">
   <HEADER Label="Header">
       <HEAD Label="H1a">2.88%</HEAD>
       <HEAD Label="H2b">3.24%</HEAD>
   </HEADER>
</Details>

The XSD works as so: This will validate for example 1:

<xs:element name="HEADER">
   <xs:complexType>
      <xs:simpleContent>
         <xs:extension base="xs:string">
            <xs:attribute name="Label" type="xs:string" use="required" />
          </xs:extension>
       </xs:simpleContent>
    </xs:complexType>
 </xs:element>

This will validate the example 2:

<xs:element name="HEADER">
   <xs:complexType>
      <xs:sequence>
         <xs:element maxOccurs="unbounded" name="HEAD">
           <xs:complexType>
             <xs:simpleContent>
               <xs:extension base="xs:string">
                 <xs:attribute name="Label" type="xs:string" use="required" />
               </xs:extension>
             </xs:simpleContent>
           </xs:complexType>
         </xs:element>
       </xs:sequence>
     <xs:attribute name="Label" type="xs:string" use="required" />
   </xs:complexType>
 </xs:element>

I tried using xs:choice but it didn't seem to work well or maybe I don't have a clear understanding on how to implement choice in this situation.


回答1:


In XSD, you cannot allow both simple and complex content unless you're willing to have mix elements and text via mixed="true" (in this case Example 1 is not needed). You could then used XSD 1.1 assertions to exclude both from appearing simultaneously.

<xs:element name="HEADER">
<xs:complexType mixed="true">
  <xs:sequence>
    <xs:element minOccurs="0" maxOccurs="unbounded" name="HEAD">
      <xs:complexType>
        <xs:simpleContent>
          <xs:extension base="xs:string">
            <xs:attribute name="Label" type="xs:string" use="required" />
          </xs:extension>
        </xs:simpleContent>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
  <xs:attribute name="Label" type="xs:string" use="required" />
</xs:complexType>
</xs:element>

However, you're swimming against the current here. Instead, accept that you really have two different entities with two different content models and name the different entities differently: SIMPLE_HEADER and COMPLEX_HEADER comes to mind. Then you can use xs:choice/maxOccurs="unbounded" on Details to allow simple and complex headers to be freely interspersed.




回答2:


If the instances already exist, and you can't change them, and you are trying to write an XSD schema to describe them, and it has to be one schema that describes them all, then your options are very limited. As far as I'm aware the only solution is to define HEADER with mixed content -- and that's a lousy solution. It can be improved a bit (though not much) by using XSD 1.1 assertions.

If you can remove any of these requirements (e.g if you can change the instance documents, or if you can use RelaxNG to do the validation, or if you can use a different schema for each document type) then you have a chance of a more satisfactory solution.



来源:https://stackoverflow.com/questions/39751548/xsd-allowing-both-simpletype-and-complextype-content-for-same-element

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