Могу ли я создать схему XSD, которая помещает атрибут во все сложные типы? - PullRequest
3 голосов
/ 31 мая 2009

Я хотел бы создать XSD, который определяет атрибут, который может быть помещен в элементы из других схем или элементы, которых нет ни в одной схеме. Например, схема будет выглядеть примерно так:

<xs:schema id="MySchema"
    targetNamespace="http://tempuri.org/MySchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/MySchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:attribute name="myAttribute" />
</xs:schema>

И документ может выглядеть примерно так:

<someElement xmlns="http://tempuri.org/OtherSchema" xmlns:m="http://tempuri.org/MySchema">
  <someOtherElement someAttribute="value" m:myAttribute="value2" />
</someElement>

«OtherSchema» для этого примера выглядит так:

<xs:schema id="OtherSchema"
    targetNamespace="http://tempuri.org/OtherSchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/OtherSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:element name="someElement">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" name="someOtherElement">
          <xs:complexType>
            <xs:attribute name="someAttribute" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Полный пример, включая консольное приложение C #, которое выполняет проверку, можно загрузить с http://dl.getdropbox.com/u/407740/SchemaTest.zip. Моя цель - выполнить проверку без изменения «OtherSchema». Это возможно?

Ответы [ 4 ]

1 голос
/ 03 июня 2009

Мне пришлось добавить оболочку, чтобы импортировать две разные схемы в одну (поскольку xmllint принимает только одну XML-схему):

<xs:schema id="Wrapper" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import schemaLocation="MySchema.xsd" namespace="http://tempuri.org/MySchema"/>
  <xs:import schemaLocation="OtherSchema.xsd" namespace="http://tempuri.org/OtherSchema"/>
</xs:schema>

Единственный способ получить что-то вроде Вопроса для работы - это отредактировать OtherSchema, xsd (что запрещено вопросом), поэтому добавьте подстановочный знак атрибута (после существующего):

 <xs:attribute name="someAttribute" />
 <xs:anyAttribute namespace="##other"/>

Мне не хватает специалиста по XML-схеме, чтобы сказать «это невозможно», но мне кажется, что это невозможно.

Одна проблема с вашим предложением заключается в том, что вы не указываете , где должен появиться новый атрибут. Обычно, если вы объявляете атрибут (или complexElement, modelgroup и т. Д.), Вы можете ссылаться на него или нет. Если вы явно не ссылаетесь на это, это не имеет никакого эффекта. Поэтому я думаю, что ваше предложение будет рассматриваться как атрибут, который объявлен, но не упомянут.

То, что вам действительно нужно, это способ сказать «добавить этот атрибут к каждому существующему complexType», но вы этого не говорите. И, к сожалению, кажется, нет способа сказать это. (нет даже способа сказать «добавить этот атрибут в этот конкретный существующий complexType» - вы должны включить его в исходное определение или не включать вовсе).

Один из способов частично сделать это - <redefine> печатать в другой схеме - я добавлю это во втором ответе.

1 голос
/ 03 июня 2009

Вы можете переопределить схему , расширяя их по своему усмотрению. Таким образом, вы можете изменить определения существующей схемы без фактического изменения файла. НО ЭТО НЕ РАБОТАЕТ ДЛЯ ВАШЕГО ПРИМЕРА как дано, потому что нельзя переопределить элементы (только complexTypes и т. Д. См. http://www.w3.org/TR/xmlschema-1/#element-redefine). Поэтому я разбил ваш пример на явные complexTypes, чтобы они были доступны для переопределения.

RedefineOtherSchema.xsd:

<xs:schema id="RedefineOtherSchema"
    targetNamespace="http://tempuri.org/OtherSchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/OtherSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:m="http://tempuri.org/MySchema">          <!-- for the ref -->

  <xs:import schemaLocation="MySchema.xsd"
    namespace="http://tempuri.org/MySchema"/>       <!-- import -->

  <xs:redefine schemaLocation="OtherSchema.xsd">    <!-- redefine -->
    <xs:complexType name="SomeOtherElement">
      <xs:complexContent>
        <xs:extension base="SomeOtherElement">
          <xs:attribute ref="m:myAttribute" />      <!-- the ref -->
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
</xs:schema>

OtherSchema:

<xs:schema id="OtherSchema"
    targetNamespace="http://tempuri.org/OtherSchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/OtherSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:element name="someElement" type="SomeElement"/>

    <xs:complexType name="SomeElement">
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded"
                    name="someOtherElement" type="SomeOtherElement"/>
      </xs:sequence>
    </xs:complexType>

    <xs:complexType name="SomeOtherElement">
      <xs:attribute name="someAttribute" />
    </xs:complexType>
</xs:schema>

MySchema: (без изменений)

<xs:schema id="MySchema"
    targetNamespace="http://tempuri.org/MySchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/MySchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:attribute name="myAttribute"/>
</xs:schema>

Почему <complexContent>? Переопределение должно быть расширением (или ограничением) существующего типа - так оно и изменяет предыдущее определение. Расширение должно быть в <complexContent> (я считаю).

Почему <import>? Вы не можете определять вещи в более чем одном пространстве имен в xsd (есть только одно «targetNamespace»). Но вы можете обойти это, импортировав определение из другого xsd (тогда вы его не «определяете»). [есть другой способ?]

HTH: -)

0 голосов
/ 05 июня 2009

Это именно то, что обеспечивает NVDL (язык проверки и диспетчеризации на основе пространства имен). Это позволяет комбинировать несколько схем / словарей для проверки документа без необходимости изменения этих схем. NVDL - это стандарт ISO.

Рабочий скрипт NVDL, который обрабатывает ваше дело, ниже

<rules xmlns="http://purl.oclc.org/dsdl/nvdl/ns/structure/1.0" startMode="other">
  <mode name="other">
    <namespace ns="http://tempuri.org/OtherSchema">
      <validate schema="other.xsd" useMode="validateMyAttributes"/>
    </namespace>
  </mode>
  <mode name="validateMyAttributes">
    <namespace ns="http://tempuri.org/MySchema" match="attributes">
      <validate schema="my.xsd"/>
    </namespace>
  </mode>
</rules>

По сути, это говорит о том, что нужно проверить, что это в пространстве имен ... tempuri.org/OtherSchema с помощью схемы other.xsd и атрибутов из ... tempuri.org/MySchema с помощью схемы my.xsd.

Для получения дополнительной информации о NVDL см. Www.nvdl.org. Вышеуказанный скрипт был протестирован с oNVDL.

0 голосов
/ 31 мая 2009

Рассмотрим xsi: nil, xsi: schemaLocation и xsi: noNamespaceSchemaLocation. Ответ - да.

Также не заняло бы много времени, чтобы попробовать и посмотреть.


Вам не хватало targetNamespace в схеме. Попробуйте это:

<xs:schema xmlns="MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="MySchema">
  <xs:attribute name="myAttribute" />
</xs:schema>
...