Переопределение допустимого содержимого элемента при изменении контекста элемента - PullRequest
1 голос
/ 09 декабря 2011

Фон

Хотите определить тот же тип элемента XML, но в одном контексте в качестве определения, а в другом - в качестве ссылки. Это может быть ситуация для key и keyref.

Проблема

Рассмотрим следующий XML:

<recipe>
<equipment>
  <bakeware>
    <object id="1">pan</object>
  </bakeware>
  <cookware>
    <object id="2">pot</object>
  </cookware>
</equipment>

<directions label="dough">
  <step action="roll" time="3">dough on <object id="1" /> until thin</step>
</directions>
</recipe>

Внутри любого подэлемента элемента equipment элемент object должен иметь как id, так и текстовое значение. Внутри любого элемента step может появиться элемент object, но его атрибут id должен ссылаться на существующий object и может не содержать текстового узла.

Я подхожу к этой проблеме, создав два определения для object: (1) objectType; и (2) objectDefType. Это может быть ошибкой (кажется, что наследование должно быть возможным).

Вот что у меня есть:

  <xsd:simpleType name="rString">
    <xsd:restriction base="xsd:normalizedString">
      <xsd:minLength value="1" />
      <xsd:maxLength value="64" />
      <xsd:whiteSpace value="collapse" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:complexType name="objectDefType">
    <xsd:simpleContent>
      <xsd:extension base="rString">
        <xsd:attribute name="id" type="rId" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

Я бы хотел переопределить элементы minLength и maxLength следующим образом:

  <xsd:complexType name="objectType">
    <xsd:simpleContent>
      <xsd:extension base="rString">
        <xsd:attribute name="id" type="rId" use="required" />

        <xsd:minLength value="0" />
        <xsd:maxLength value="0" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

Это приводит к ошибке:

Содержание недействительно. Ожидается (аннотация ?, ((attribute | attributeGroup) *, anyAttribute?)).

Я пробовал несколько способов определить этот элемент, включая изменение его на complexContent, но каждая попытка приводила к отдельной ошибке.

Вопрос

Что такое XSD для определения объекта с помощью <object id="1">pan</object> и обращения к нему по его ключу <object id="1" /> в другом месте документа?

Большое спасибо.

1 Ответ

1 голос
/ 10 декабря 2011

Чтобы исправить ошибку XSD, вот как должно выглядеть исправленное определение - оно в основном определяет элемент с содержимым emtpy.

<xsd:complexType name="objectType">
    <xsd:attribute name="id" type="rId" use="required"/>
</xsd:complexType>

Это единственный способ, на самом деле. Попытка использования других комбинаций, которые будут работать с точки зрения структуры (с ограничением objectType objectDefType), не будет работать с точки зрения значения «производного» фасета: они не могут быть меньше значения родительского элемента.

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

Я начал с того, что взял ваш XML и сгенерировал из него фиктивный XSD. Вот что он придумал, и он работает (он проверяет конкретный экземпляр XML):

<?xml version="1.0" encoding="utf-16"?>
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)-->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="recipe">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="equipment">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="bakeware">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="object">
                      <xs:complexType>
                        <xs:simpleContent>
                          <xs:extension base="xs:string">
                            <xs:attribute name="id" type="xs:unsignedByte" use="required" />
                          </xs:extension>
                        </xs:simpleContent>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="cookware">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="object">
                      <xs:complexType>
                        <xs:simpleContent>
                          <xs:extension base="xs:string">
                            <xs:attribute name="id" type="xs:unsignedByte" use="required" />
                          </xs:extension>
                        </xs:simpleContent>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="directions">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="step">
                <xs:complexType mixed="true">
                  <xs:sequence>
                    <xs:element name="object">
                      <xs:complexType>
                        <xs:attribute name="id" type="xs:unsignedByte" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="action" type="xs:string" use="required" />
                  <xs:attribute name="time" type="xs:unsignedByte" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="label" type="xs:string" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Из этого первое, что вы заметите, это то, что с этим авторским стилем, называемым Russian Doll, поскольку все вложено, у вас будет два локальных, а следовательно, полностью независимых определения для тега объекта. Тогда это может стать основой для вашего решения, в зависимости от того, что и как вы хотите повторно использовать XSD-контент.

Самый простой способ иметь «контекст» - это сделать элемент локальным для вашего контекста. Для повторного использования частей одним из способов может быть либо сделать атрибут id и / или его тип глобальным. Или вернитесь к обсуждению сложных типов выше.

Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...