Ограничить глубину вложенных элементов в XSD - PullRequest
4 голосов
/ 02 сентября 2010

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

В этом контексте я собираю сигналы тревоги из системы управления и хочу предоставить документ XML, который позволяет завершатьПользователь определяет некоторые правила для фильтрации сигналов тревоги в папках в пользовательском интерфейсе.Я хочу ограничить глубину вложенных папок до 3, чтобы конечный пользователь не мог вкладывать сотни уровней в глубину - поскольку фильтрация на стольких уровнях в конечном итоге может привести к сбою приложения., но представляется целесообразным определить это в схеме, если это возможно.

Например, это было бы хорошо:

<group name="Folder 1">
        <group name="Folder 2">
            <group name="Folder 3">
                <group name="Folder 4">
                </group>
            </group>
        </group>
    </group>

Это было бы неверно, так как папка 5 слишком глубокая.

<group name="Folder 1">
        <group name="Folder 2">
            <group name="Folder 3">
                <group name="Folder 4">
                    <group name="Folder 5">
                    </group>
                </group>
            </group>
        </group>
    </group>

Моя схема выглядит следующим образом, но она не ограничивает глубину для приведенного выше фрагмента.

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="hierarchy">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="group" type="GroupType" />
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" />
    </xs:complexType>
  </xs:element>

  <xs:complexType name="GroupType">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="group" type="GroupType" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:string" use="required" />
    <xs:attribute name="filterOn" type="xs:string" use="optional" />
    <xs:attribute name="operator" type="xs:string" use="optional" />
    <xs:attribute name="value" type="xs:string" use="optional" />
  </xs:complexType>
</xs:schema>

Любые указатели очень ценятся!

1 Ответ

4 голосов
/ 02 сентября 2010

Красивое и простое решение недоступно в XML-схеме (но есть и на других языках), но вы можете сделать это, вложив все это самостоятельно, что я не могу рекомендовать.

Итак, на вашем месте я бы сделал одну из двух вещей:

  1. Выберите альтернативу XML-схеме (или расширению). См .: http://en.wikipedia.org/wiki/XML_schema#XML_schema_languages (взгляните на RELAX и Schematron)
  2. Выполните проверку глубины в своем приложении и отклоните ее, если depth > 3, и разъясните поведение в документации для вашей XML-схемы и приложения.

Цитата из Wiki о XML Schema версии 1.1 (рекомендация кандидата):

Возможность определять утверждения относительно содержимого документа с помощью выражений XPath 2.0 (идея заимствована из Schematron)

<- это позволит легко определить глубину. </p>

Для комментариев о том, как представить глубину вложения в XMLSchema :

По сути, вы можете сделать что-то вроде следующего (все еще рекомендует делать это в коде). Затем вы добавляете атрибуты, регулируете глубину и т. Д. (Возможно, вы сможете повторно использовать атрибуты с extension или restrict, но я не уверен на 100%). Этот метод может стать довольно неприятным (экспоненциальным), если вы разрешите несколько видов подэлементов:

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://somenamespace.com"
           xmlns="http://somenamespace.com">

  <xs:element name="hierarchy">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="group" type="GroupTypeDepth0" />
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" />
    </xs:complexType>
  </xs:element>

  <xs:complexType name="GroupTypeDepth0">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="group" type="GroupTypeDepth1" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="GroupTypeDepth1">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="group" type="GroupTypeDepth2" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="GroupTypeDepth2"/>
</xs:schema>

Действительно:

<hierarchy xmlns="http://somenamespace.com">
  <group>
    <group>
      <group/>
    </group>
  </group>
</hierarchy>

Invalid:

<hierarchy xmlns="http://somenamespace.com">
  <group>
    <group>
      <group>
        <group/>
      </group>
    </group>
  </group>
</hierarchy>
...