12

给定一个 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>

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

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

如何做到这一点?

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

4

1 回答 1

20

在扩展现有 XML 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>

图形模式表示

扩展/限制

您可以扩展/限制一个类型,这有效地创建了一个具有附加/较少元素/属性的新类型,但是没有办法强制使用这种新类型。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>

图形模式表示

示例 XML 文件

<?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>. 基本上替换了 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>

示例 XML 文件

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

任何

另一种解决方案是xs:any在基本元素定义中包含 a。但是,如果您不控制基本架构,则这是不可能的。

打开内容

** 仅在 XSD 1.1 中可用 **

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

OpenContent 可以应用于特定的复杂类型,也可以应用于模式级别,其中它应用于其中声明的所有元素。

如果您使用的是 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>

图形模式表示

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

概括

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

我推荐我公司的Liquid XML Studio ,因为它有一个很好的 XSD 编辑器,可以从你的模式中创建示例 XML,让你很容易看到你的工作结果,而且 XML Intellisense 也可以很容易地看到有效的选项。

于 2010-08-06T11:05:27.520 回答