使用 XSD 更清晰地扩展元素

发布于 2024-09-18 05:14:01 字数 3125 浏览 1 评论 0原文

我定义的 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=..." " < br> 因此我的问题是:有什么方法可以使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}”。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇俏 2024-09-25 05:14:01

您的问题更新表明真正的问题在于 元素。有效的文档将

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

扩展类型“字段”不会修改原始类型。相反,它创建了一个基于旧“字段”类型的新类型。如果您想将 元素作为 元素的子元素,则应该更改 元素的类型从“field”到“composite-Field”。

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

其他解决方案是更改 元素的子元素 而不是元素 因为 已经具有内容类型“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

原发帖者评论:

但我希望“常规”元素能够包含“字段”或“复合字段”。不要严格要求只有其中一种类型。

那么您真正的问题是您希望您的模式验证这两个文档吗?

<?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. “如何允许可选元素(可以不存在的元素)?”

如果您最初明确说明您想要实现的目标/代码是什么以及您当前拥有哪些代码会导致您的问题,那么整个问题可能会更快地得到解决

回答 #1 使用 < code>以允许多个独立子内容之一。

使用此结构,您可以允许 具有 子元素,

<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 类型的唯一原因是允许可选的 元素,您可以轻松修改原始 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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文