如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

时间:2022-01-26 17:18:56

Given an XSD as follows:

鉴于XSD如下:

<xs:schema elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"  xmlns:std="http://..." targetNamespace="...">
  <xs:element name="SomeRootNode" type="std:SomeRootNodeType" />
  ...
</xs:schema>

that defines some elements which allow any child from a different namespace.

它定义了一些允许来自不同命名空间的子进程的元素。

I want to extend this schema with my own and insert child elements and attributes of specific elements in the base document. For example, myElementX or myAttributeY must have parent node std:SomeRootNode. The combined document should then be capable of allowing any third parties to continue to extend the document in any way already allowed by the base schema, but for elements and attributes from my namespace I want to validate that all elements and attributes have the correct parent nodes and appear only in the allowed places in the base document.

我想用自己的方式扩展这个模式,并在基础文档中插入子元素和特定元素的属性。例如,myElementX或myAttributeY必须具有父节点std:SomeRootNode。然后,组合文档应该能够允许任何第三方继续以基本模式已经允许的任何方式扩展文档,但是对于来自我的命名空间的元素和属性,我想验证所有元素和属性是否具有正确的父节点并仅出现在基本文档中允许的位置。

How can this be achieved?

怎么能实现这一目标?

I hope there is a clean solution that does not resort to redefining the base schema I am extending. I want to be able to easily adapt if new versions of the base schema are released. I do not want to have to change mine with new redefinitions each time a new version of the base document is released (unless it has breaking changes for my design).

我希望有一个干净的解决方案,而不是重新定义我扩展的基础架构。如果发布新版本的基础架构,我希望能够轻松适应。每次发布新版本的基础文档时,我都不想用新的重新定义来改变我的(除非它对我的设计有重大改变)。

1 个解决方案

#1


11  

When it comes to extending existing XML Schema, there are a few options.

在扩展现有的XML Schema时,有一些选择。

Using the base schema

使用基础架构

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Root" type="RootType" />
    <xs:complexType name="RootType">
        <xs:sequence>
            <xs:element name="OriginalContent" />
        </xs:sequence>
    </xs:complexType>
</xs:schema>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

Extension/Restriction

You can extend/restrict a type, which effectively creates a new type with additional/less elements/attributes, however there is no way to force the use of this new type. The creator of the XML can tell you they are using their new type using the xsi:type="MyCustomType", but you can not insist its used.

您可以扩展/限制类型,这有效地创建了具有额外/更少元素/属性的新类型,但是无法强制使用此新类型。 XML的创建者可以使用xsi:type =“MyCustomType”告诉您他们正在使用他们的新类型,但您不能坚持使用它。

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:include schemaLocation=".\Root.xsd" />
    <xs:complexType name="MyNewRoot">
        <xs:complexContent>
            <xs:extension base="RootType">
                <xs:sequence>
                    <xs:element name="AdditionalElement" type="xs:string" />
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

Sample XML File

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="Extension.xsd" 
      xsi:type="MyNewRoot">
    <OriginalContent />
    <AdditionalElement/>
</Root>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

Redefine

The other alternative is to use <redefine>. Basically replaces the definition of RootType, so wherever RootType appears our new version must now be used.

另一种方法是使用 。基本上取代了RootType的定义,因此无论RootType出现在哪里,我们现在都必须使用新版本。

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:redefine schemaLocation="root.xsd">
        <xs:complexType name="RootType">
            <xs:complexContent>
                <xs:extension base="RootType">
                    <xs:sequence>
                        <xs:element name="MyContent" type="xs:string" />
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:redefine>
</xs:schema>

Sample XML File

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Redefine.xsd">
    <OriginalContent></OriginalContent>
    <MyContent>stuff</MyContent>
</Root>

Any

Another solution is to include a xs:any in the base elements definition. However, this is not possible if you don't control the base schema.

另一种解决方案是在基本元素定义中包含xs:any。但是,如果您不控制基础架构,则无法执行此操作。

Open Content

** Only available in XSD 1.1 **

**仅适用于XSD 1.1 **

Open Content was added specifically to allow you to create open schemas, it has 2 'mode's interleave and suffix. When set to interleave additional elements (matching the contained xs:any clause) can be interleaved through out the element (before, between and after any of the existing elements). When in suffix mode then additional elements (matching the contained xs:any clause) can be added after the existing elements.

Open Content是专门添加的,允许您创建开放模式,它有2'模式的交错和后缀。当设置为交错时,其他元素(匹配包含的xs:any子句)可以在元素之间交错(在任何现有元素之前,之间和之后)。在后缀模式下,可以在现有元素之后添加其他元素(匹配包含的xs:any子句)。

OpenContent can be applied to specific complexTypes or it can be applied at schema level, in which it applies to all the elements declared within it.

OpenContent可以应用于特定的complexTypes,也可以在模式级别应用,其中它适用于在其中声明的所有元素。

If you are using XSD 1.1, this is definitely the way to go in order to make your schemas extensible, however XSD 1.1 is still not well supported.

如果您使用的是XSD 1.1,那么这绝对是让您的模式可扩展的方法,但是XSD 1.1仍然不受支持。

<xs:complexType name="BookType">
    <xs:openContent mode="interleave">
        <xs:any />
    </xs:openContent>
    <xs:sequence>
        <xs:element name="Title"  type="xs:string" />
        <xs:element name="Author" type="xs:string" maxOccurs="unbounded" />
        <xs:element name="ISBN"   type="xs:string" />
    </xs:sequence>
</xs:complexType>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

It should also be noted that if you interleave elements between runs of existing elements (i.e. Title, Author, NewElement, Author, ISBN), then most parsers will treat the second Author as a 'new' element and validate it using the openContent rules not the xs:element name="Author" type="xs:string", furthermore if the Author had a minOccurs of 2, this clause may fail as its seeing 1xAuthor, 1xNewElement, 1xAuthor and the first 1xAuthor does not for full the minoccurs clause.

还应该注意的是,如果您在现有元素的运行之间交错元素(即标题,作者,新元素,作者,ISBN),那么大多数解析器会将第二个作者视为“新”元素并使用openContent规则验证它xs:element name =“Author”type =“xs:string”,此外如果作者的minOccurs为2,则该子句可能会失败,因为它看到1xAuthor,1xNewElement,1xAuthor并且第一个1xAuthor没有完全使用minoccurs子句。

Summary

All these methods have there ups and downs, but having a good XML Editor, makes it much easier to figure out what's going on.

所有这些方法都有起伏,但拥有一个好的XML编辑器,可以更容易地弄清楚发生了什么。

I recommend Liquid XML Studio which is made by my company, as it has a good XSD Editor, can create sample XML from your schemas, making it easy to see the result of your work, also the XML Intellisense makes it easy to see the valid options.

我推荐由我公司制作的Liquid XML Studio,因为它有一个很好的XSD编辑器,可以从您的模式创建示例XML,使您可以轻松查看工作结果,XML Intellisense也可以轻松查看有效选项。

#1


11  

When it comes to extending existing XML Schema, there are a few options.

在扩展现有的XML Schema时,有一些选择。

Using the base schema

使用基础架构

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Root" type="RootType" />
    <xs:complexType name="RootType">
        <xs:sequence>
            <xs:element name="OriginalContent" />
        </xs:sequence>
    </xs:complexType>
</xs:schema>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

Extension/Restriction

You can extend/restrict a type, which effectively creates a new type with additional/less elements/attributes, however there is no way to force the use of this new type. The creator of the XML can tell you they are using their new type using the xsi:type="MyCustomType", but you can not insist its used.

您可以扩展/限制类型,这有效地创建了具有额外/更少元素/属性的新类型,但是无法强制使用此新类型。 XML的创建者可以使用xsi:type =“MyCustomType”告诉您他们正在使用他们的新类型,但您不能坚持使用它。

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:include schemaLocation=".\Root.xsd" />
    <xs:complexType name="MyNewRoot">
        <xs:complexContent>
            <xs:extension base="RootType">
                <xs:sequence>
                    <xs:element name="AdditionalElement" type="xs:string" />
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

Sample XML File

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="Extension.xsd" 
      xsi:type="MyNewRoot">
    <OriginalContent />
    <AdditionalElement/>
</Root>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

Redefine

The other alternative is to use <redefine>. Basically replaces the definition of RootType, so wherever RootType appears our new version must now be used.

另一种方法是使用 。基本上取代了RootType的定义,因此无论RootType出现在哪里,我们现在都必须使用新版本。

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:redefine schemaLocation="root.xsd">
        <xs:complexType name="RootType">
            <xs:complexContent>
                <xs:extension base="RootType">
                    <xs:sequence>
                        <xs:element name="MyContent" type="xs:string" />
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:redefine>
</xs:schema>

Sample XML File

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Redefine.xsd">
    <OriginalContent></OriginalContent>
    <MyContent>stuff</MyContent>
</Root>

Any

Another solution is to include a xs:any in the base elements definition. However, this is not possible if you don't control the base schema.

另一种解决方案是在基本元素定义中包含xs:any。但是,如果您不控制基础架构,则无法执行此操作。

Open Content

** Only available in XSD 1.1 **

**仅适用于XSD 1.1 **

Open Content was added specifically to allow you to create open schemas, it has 2 'mode's interleave and suffix. When set to interleave additional elements (matching the contained xs:any clause) can be interleaved through out the element (before, between and after any of the existing elements). When in suffix mode then additional elements (matching the contained xs:any clause) can be added after the existing elements.

Open Content是专门添加的,允许您创建开放模式,它有2'模式的交错和后缀。当设置为交错时,其他元素(匹配包含的xs:any子句)可以在元素之间交错(在任何现有元素之前,之间和之后)。在后缀模式下,可以在现有元素之后添加其他元素(匹配包含的xs:any子句)。

OpenContent can be applied to specific complexTypes or it can be applied at schema level, in which it applies to all the elements declared within it.

OpenContent可以应用于特定的complexTypes,也可以在模式级别应用,其中它适用于在其中声明的所有元素。

If you are using XSD 1.1, this is definitely the way to go in order to make your schemas extensible, however XSD 1.1 is still not well supported.

如果您使用的是XSD 1.1,那么这绝对是让您的模式可扩展的方法,但是XSD 1.1仍然不受支持。

<xs:complexType name="BookType">
    <xs:openContent mode="interleave">
        <xs:any />
    </xs:openContent>
    <xs:sequence>
        <xs:element name="Title"  type="xs:string" />
        <xs:element name="Author" type="xs:string" maxOccurs="unbounded" />
        <xs:element name="ISBN"   type="xs:string" />
    </xs:sequence>
</xs:complexType>

如何使用自定义元素扩展基础架构,同时保持对新版本的更改?

It should also be noted that if you interleave elements between runs of existing elements (i.e. Title, Author, NewElement, Author, ISBN), then most parsers will treat the second Author as a 'new' element and validate it using the openContent rules not the xs:element name="Author" type="xs:string", furthermore if the Author had a minOccurs of 2, this clause may fail as its seeing 1xAuthor, 1xNewElement, 1xAuthor and the first 1xAuthor does not for full the minoccurs clause.

还应该注意的是,如果您在现有元素的运行之间交错元素(即标题,作者,新元素,作者,ISBN),那么大多数解析器会将第二个作者视为“新”元素并使用openContent规则验证它xs:element name =“Author”type =“xs:string”,此外如果作者的minOccurs为2,则该子句可能会失败,因为它看到1xAuthor,1xNewElement,1xAuthor并且第一个1xAuthor没有完全使用minoccurs子句。

Summary

All these methods have there ups and downs, but having a good XML Editor, makes it much easier to figure out what's going on.

所有这些方法都有起伏,但拥有一个好的XML编辑器,可以更容易地弄清楚发生了什么。

I recommend Liquid XML Studio which is made by my company, as it has a good XSD Editor, can create sample XML from your schemas, making it easy to see the result of your work, also the XML Intellisense makes it easy to see the valid options.

我推荐由我公司制作的Liquid XML Studio,因为它有一个很好的XSD编辑器,可以从您的模式创建示例XML,使您可以轻松查看工作结果,XML Intellisense也可以轻松查看有效选项。