cleaner extension of elements using XSD

放肆的年华 提交于 2019-12-25 03:13:07

问题


I defined xml schema the contains an element called 'field' and an extension to it called 'composite-field'. it is defined as following:

<xs:complexType name="field">
        <xs:sequence>
            <xs:element name="value" type="xs:string" />
        </xs:sequence>      
</xs:complexType>
<xs:complexType name="composite-Field">
        <xs:complexContent>
          <xs:extension base="field">
            <xs:sequence>
                    <xs:element name="length" type="xs:integer" />
                  </xs:sequence>
                </xs:extension>
        </xs:complexContent>
</xs:complexType>

in order to use it in my XML ut has to be:

<field xsi:type="composite-Field">
  <value>enjoy</value>
  <length>30</length>
</field>

I don't want my XML users to use schema syntax such as xsi:type=..." "
Therefore my question is: Is there any way to make the syntax of the XML be:

<composite-Field>
      <value>enjoy</value>
      <length>30</length>
</composite-Field>

so the name of the element will imply its inheritence and wouldn't force the users add type attribute ??

I tried this:

<xs:element name="MyCompositeField" type="composite-field"/>

and then:

<MyCompositeField>
          <value>enjoy</value>
          <length>30</length>
</MyCompositeField>

but it also didn't pass the XSD schema validation


12/09/2010: In response the suggested answer I refined my question a liitle bit.
The schema looks like that:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 

    <xs:element name="general">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="field" type="field" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="field"> 
        <xs:sequence> 
            <xs:element name="value" type="xs:string" /> 
        </xs:sequence> 
    </xs:complexType> 



    <xs:complexType name="composite-Field" > 
        <xs:complexContent> 
            <xs:extension base="field" > 
                <xs:sequence> 
                    <xs:element name="length" type="xs:integer" /> 
                </xs:sequence> 
            </xs:extension> 
        </xs:complexContent> 
    </xs:complexType> 

    <xs:element name="MyCompositeField" type="composite-Field"/> 

</xs:schema> 

and the required xml looks like that:

<?xml version="1.0" encoding="UTF-8"?>
 <general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <MyCompositeField> 
        <value>enjoy</value> 
        <length>30</length> 
    </MyCompositeField> 

 </general>

using this combination I get in response the error message:

cvc-complex-type.2.4.a: Invalid content was found starting with element 'MyCompositeField'. One of '{field}' is expected.


回答1:


Your question update shows that the real problem is in the <general> element. A valid document would be

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
    </field> 
</general>

Extending the type "field" does not modify the original type. Instead it creates a new type that is based on the old "field" type. If you wanted to have both <value> and <length> elements as the chlidren of <field> element, you should change the type of the <field> element from "field" to "composite-Field".

<xs:element name="general">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="field" type="composite-Field" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

This validates document

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
        <length>30</length> 
    </field> 
</general>

Other solution would be to change the <general> element have child element <MyCompositeField> instead of element <field> since <MyCompositeField> already has content type "composite-Field"

<xs:element name="general">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="MyCompositeField" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

which would validate document

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <MyCompositeField>
        <value>enjoy</value>
        <length>30</length>
    </MyCompositeField>
</general>

Update 2010-08-14

Comment by original poster:

But I want 'general' element to have the ability to contain either 'field' or 'composite-field'. Not to strict it to have ONLY one of those types.

So is your real problem is that you want your schema to validate both of these documents?

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
    </field> 
</general>

and

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <MyCompositeField>
        <value>enjoy</value>
        <length>30</length>
    </MyCompositeField>
</general>

In that case the whole question can be seen as:

  1. "how to allow an element to have one of these choices as a child element?"
    or because your types are almost similar:
  2. "how to allow an optional element (element that can be absent)?"

The whole question could have been solved much faster if you had initially clearly stated what is your goal/code that you want to achieve and what code do you currently have that causes your problems

Answer to #1 Use <xs:choice> to allow one of several independent child contents.

With this structure you can allow <general> to have either <field> or <MyCompositeField> child element

<xs:element name="general">
    <xs:complexType>
        <xs:choice>
            <xs:element name="field" type="field" />
            <xs:element name="MyCompositeField" type="composite-Field" />
        </xs:choice>
    </xs:complexType>
</xs:element>

So this change in your schema would allow both of the documents I posted above.

Answer to #2 If the only reason to have type composite-Field is to allow an optional <length> element you could just easily modify the original field type and use it instead of type composite-Field

<xs:complexType name="field"> 
    <xs:sequence> 
        <xs:element name="value" type="xs:string" /> 
        <xs:element name="length" type="xs:integer" minOccurs="0" /> 
    </xs:sequence> 
</xs:complexType> 

This schema definition creates a type that allows an optional length element and thus validates both of these documents

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
    </field> 
</general>

and

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
        <length>30</length> 
    </field> 
</general>


来源:https://stackoverflow.com/questions/3657714/cleaner-extension-of-elements-using-xsd

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