Расширение сложных типов из существующей схемы - PullRequest
2 голосов
/ 29 июля 2010

Мне нужно расширить существующий документ XML новыми элементами, не теряя возможности проверять его как на неизмененной исходной схеме, так и на расширенной схеме, определенной мной.

Например, допустим, я хочу добавить элементы Code и Price в существующий документ Book следующим образом:

<aa:Book xmlns:aa="http://www.aa.com"
         xmlns:bb="http://www.bb.com">
  <aa:Title>Complete Works</aa:Title>
  <aa:Author>Shakespeare</aa:Author>
  <bb:Code>98</bb:Code>
  <bb:Price>31.6</bb:Price>
</aa:Book>

Исходная схема (которую я не могу изменить) будет выглядеть примерно так:

<xs:schema targetNamespace="http://www.aa.com"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://www.aa.com"
           elementFormDefault="qualified">
  <xs:element name="Book" type="Book--type" />
  <xs:complexType name="Book--type">
    <xs:sequence>
      <xs:element name="Title" type="xs:string" />
      <xs:element name="Author" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Как мне создать новую схему, которая определяет эти новые элементы, так что SchemaSet, содержащий обе эти схемы, может успешно проверить расширенный XML-документ, приведенный выше?

Я пробовал следующий обычный шаблон расширения сложного типа:

<xs:schema targetNamespace="http://www.bb.com"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://www.bb.com"
           xmlns:aa="http://www.aa.com"
           elementFormDefault="qualified">
  <xs:import namespace="http://www.aa.com" />
  <xs:complexType name="Book--type">
    <xs:complexContent>
      <xs:extension base="aa:Book--type">
        <xs:sequence>
          <xs:element name="Code" type="xs:int" />
          <xs:element name="Price" type="xs:double" />
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

Однако это приводит к ошибкам, утверждающим, что элемент aa:Book не определяет дочерний элемент bb:Code, что имеет смысл.

Возможно ли это вообще?

Для справки, вот код, который я использую для проверки документа:

var fail = new ValidationEventHandler((sender, e) => Debug.Fail(e.Message));
var schemaSet = new XmlSchemaSet();
schemaSet.Add(XmlSchema.Read(new StringReader(original), fail));
schemaSet.Add(XmlSchema.Read(new StringReader(extension), fail));
var settings = new XmlReaderSettings
    {
        ValidationType = ValidationType.Schema,
        Schemas = schemaSet
    };
settings.ValidationEventHandler += fail;
using (var stream = File.OpenRead(fileName))
using (var reader = XmlReader.Create(stream, settings))
{
    while (reader.Read()) {}
}

Ответы [ 2 ]

1 голос
/ 03 августа 2010

Оказывается, что xs:redefine - это то, что я искал.Это позволяет вам переопределить существующий элемент в новой схеме, не касаясь исходной схемы или проверяемого документа.

Используя мой оригинальный пример, книгу можно расширить, используя следующие две схемы:

<xs:schema targetNamespace="http://www.bb.com"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://www.bb.com"
           elementFormDefault="qualified">
  <xs:element name="Code" type="xs:int" />
  <xs:element name="Price" type="xs:double" />
</xs:schema>

<xs:schema targetNamespace="http://www.aa.com"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://www.aa.com"
           xmlns:bb="http://www.bb.com"
           elementFormDefault="qualified">
  <xs:import namespace="http://www.bb.com" />
  <xs:redefine schemaLocation="http://www.aa.com">
    <xs:complexType name="Book--type">
      <xs:complexContent>
        <xs:extension base="Book--type">
          <xs:sequence>
            <xs:element ref="bb:Code" />
            <xs:element ref="bb:Price" />
          </xs:sequence>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
</xs:schema>
0 голосов
/ 30 июля 2010

Проблема в том, что, хотя у вас есть новый тип, определенный в вашей схеме B, корневой элемент в вашем образце документа имеет тип Book--type из исходной схемы A.

Вам необходимо использоватьвведите переопределение в вашем документе, например так:

<aa:Book xmlns:aa="http://www.aa.com"
         xmlns:bb="http://www.bb.com"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:type="bb:Book--type">
  <aa:Title>Complete Works</aa:Title>
  <aa:Author>Shakespeare</aa:Author>
  <bb:Code>98</bb:Code>
  <bb:Price>31.6</bb:Price>
</aa:Book>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...