Как расширить базовую схему с помощью пользовательских элементов, оставаясь открытыми для перехода с новых версий? - PullRequest
8 голосов
/ 03 августа 2010

Дано 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. Затем объединенный документ должен позволять любым третьим сторонам продолжать расширять документ любым способом, уже разрешенным базовой схемой, но для элементов и атрибутов из моего пространства имен я хочу проверить, что все элементы и атрибуты имеют правильные родительские узлы и появляются только в разрешенных местах в базовом документе.

Как этого достичь?

Я надеюсь, что есть чистое решение, которое не прибегает к переопределению базовой схемы, которую я расширяю. Я хочу иметь возможность легко адаптироваться, если новые версии базовой схемы выпущены. Я не хочу, чтобы мне приходилось менять мои новые переопределения каждый раз, когда выпускается новая версия базового документа (если только в нем нет принципиальных изменений для моего дизайна).

1 Ответ

12 голосов
/ 06 августа 2010

Когда речь идет о расширении существующей XML-схемы, есть несколько вариантов.

Использование базовой схемы

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

Graphical schema representation

Extension / ограничение

Вы можете расширять / ограничивать тип, что эффективно создает новый тип с дополнительными / меньшими элементами / атрибутами, однако нет способа принудительно использовать этот новый тип. Создатель 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>

Graphical schema representation

Пример 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>

Graphical schema representation

Заново

Другой альтернативой является использование <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 в определение базовых элементов. Однако это невозможно, если вы не управляете базовой схемой.

Открытый контент

** Доступно только в XSD 1.1 **

Открытый контент был добавлен специально, чтобы позволить вам создавать открытые схемы, он имеет чередование и суффикс режима 2 '. Когда установлено чередование, дополнительные элементы (соответствующие содержанию xs: any) могут чередоваться через элемент (до, между и после любого из существующих элементов). В суффиксном режиме дополнительные элементы (соответствующие содержанию xs: any) могут быть добавлены после существующих элементов.

OpenContent может применяться к конкретным complexTypes или к уровню схемы, в котором он применяется ко всем элементам, объявленным в нем.

Если вы используете 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>

Graphical schema representation

Следует также отметить, что если вы чередуете элементы между сериями существующих элементов (т. Е. Title, Author, NewElement , Author, ISBN), то большинство синтаксических анализаторов будут воспринимать второго Author как «новый». элемент и проверить его, используя правила openContent, а не xs: имя элемента = "Author" type = "xs: string" , более того, если у Author было minOccurs 2, это предложение может завершиться ошибкой, так как он видит 1xAuthor , 1xNewElement, 1xAuthor и первый 1xAuthor не для полного предложения minoccurs.

Краткое описание

У всех этих методов есть свои взлеты и падения, но наличие хорошего XML Editor значительно упрощает понимание того, что происходит.

Я рекомендую Liquid XML Studio , которая сделана моей компанией , так как она имеет хороший XSD-редактор, может создавать образцы XML из ваших схем, делая легко увидеть результат вашей работы, а XML Intellisense позволяет легко увидеть действительные параметры.

...