使用XSD更清晰地扩展元素

时间:2010-09-07 10:17:02

标签: xml xsd xsd-validation

我定义了xml架构,其中包含一个名为'field'的元素及其扩展名为'composite-field'。 它的定义如下:

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

为了在我的XML中使用它必须是:

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

我不希望我的XML用户使用架构语法,例如 xsi:type = ...“”
因此我的问题是:有没有办法让XML的语法成为:

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

因此元素的名称将暗示其继承性并且不会强制用户添加类型属性 ??

我试过这个:

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

然后:

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

但它也没有通过XSD架构验证


12/09/2010:作为对建议答案的回答,我对问题进行了改进。
架构看起来像这样:

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

并且所需的xml看起来像这样:

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

使用这个组合我得到了错误消息:

  

cvc-complex-type.2.4.a:无效   内容被发现开头   元素'MyCompositeField'。之一   预计会有“{field}”。

1 个答案:

答案 0 :(得分:1)

您的问题更新显示真正的问题出在<general>元素中。有效的文件是

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

扩展类型“字段”不会修改原始类型。相反,它会创建一个基于旧“字段”类型的新类型。如果您希望同时将<value><length>元素作为<field>元素的chlidren,则应将<field>元素的类型从“field”更改为“composite-领域”。

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

验证文件

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

其他解决方案是更改<general>元素包含子元素<MyCompositeField>而不是元素<field>,因为<MyCompositeField>已经有内容类型“composite-Field”

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

将验证文件

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

更新2010-08-14

原始海报评论:

  

但我希望'general'元素能够包含'field'或'composite-field'。不要严格要求只有其中一种类型。

您真正的问题是,您希望您的架构验证这两个文档吗?

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

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

在这种情况下,整个问题可以看作:

  1. “如何让元素将这些选择中的一个作为子元素?” 或者因为你的类型几乎相似:
  2. “如何允许可选元素(可以缺席的元素)?”
  3. 如果您最初清楚地说明了您希望实现的目标/代码是什么以及您目前使用哪些代码导致您的问题,那么整个问题可以更快地得到解决

    回答#1 使用<xs:choice>允许其中一个独立的子内容。

    使用此结构,您可以允许<general>拥有<field><MyCompositeField>子元素

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

    因此,您的架构中的这一更改将允许我在上面发布的两个文档。

    回答#2 如果composite-Field类型的唯一原因是允许使用可选的<length>元素,则可以轻松修改原始field类型并使用它而不是类型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> 
    

    此架构定义创建一个允许可选长度元素的类型,从而验证这两个文档

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

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