элемент встречается с указанным номером

#xml #xsd

#xml #xsd

Вопрос:

вот мой XML-документ

 <root>
 <num>3</num>
 <a>
  <b>
   <c n="m"></c>
   <c></c>
   <c n="e"></c>
  </b>
  <b>
   <c n="s"></c>
   <c n="w"></c>
   <c></c>
  </b>
  <b>
   <c n="q"></c>
   <c></c>
   <c n="u"></c>
  </b>
 </a>
</root>
  

Я хочу создать XML-схему.
Элемент c в b должен встречаться только n раз.(n находится в элементе num)
Я думаю, что он использует key, keyref или unique.

Ответ №1:

Это невозможно.

Key, keyref и unique не помогут. Уникальность гарантирует, что у вас нет повторяющихся элементов. А key и keyref гарантируют, что элементы на месте B соответствуют элементам на месте A.

Ограничение maxOccurs требует простого целочисленного аргумента. Невозможно вычислить целое число с помощью какого-либо выражения Xpath. Смотрите здесь: http://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints

Обновить

Если вы хотите решить свою проблему с помощью unique, key и key ref, вы должны создать числовой индекс в атрибуте. Следующее изображение иллюстрирует схему:

введите описание изображения здесь

Вы должны добавить атрибут к своим c узлам, который ссылается на индекс главного атрибута. В этом примере он хранится в нескольких элементах num. Вы можете установить ограничение на целое число, ограничение на уникальность и ограничение на ключ /root/num@count . После этого вы создаете ограничение ссылки от /root/a/b/c@count до /root/num@count . Это создаст максимальное ограничение. У вас может быть столько c узлов, сколько num узлов, но у вас может быть и меньше.

Это схема:

 <?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="root">
    <xs:annotation>
      <xs:documentation>Comment describing your root element</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element name="num" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="count" type="xs:unsignedInt" use="required"/>
          </xs:complexType>
        </xs:element>
        <xs:element name="a" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="b" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="c" maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:attribute name="count" type="xs:integer" use="required"/>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
    <xs:unique name="num_unique">
      <xs:selector xpath="num"/>
      <xs:field xpath="@count"/>
    </xs:unique>
    <xs:key name="num_key">
      <xs:selector xpath="num"/>
      <xs:field xpath="@count"/>
    </xs:key>
    <xs:keyref name="num_ref" refer="num_key">
      <xs:selector xpath="a/b/c"/>
      <xs:field xpath="@count"/>
    </xs:keyref>
  </xs:element>
</xs:schema>
  

И это был бы допустимый файл:

 <?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="root.xsd">
  <num count="1"/>
  <num count="2"/>
  <num count="3"/>
  <a>
    <b>
      <c count="1"/>
    </b>
    <b>
      <c count="1"/>
      <c count="2"/>
    </b>
  </a>
</root>
  

Он станет недействительным, если вы добавите <c count="4"/> . Прямо сейчас я понятия не имею, как сделать это ссылкой на идентификатор. Возможно, возможно изменить направление ссылки…

Но тем не менее не стоит помещать ограничение в тот же файл, что и сами данные.Если вы не доверяете своему источнику данных, не имеет особого смысла запрашивать у вашего источника данных самостоятельно заданное ограничение. Вы должны поместить ограничение в схему или расширить проверку с помощью какой-либо программной логики. Например, вы можете подсчитать количество всех c узлов в их родительском элементе и проверить, все ли они одинаковы или все равны заданному числу. Это имело бы гораздо больше смысла, потому что это единственный безопасный способ принудительно ввести ограничение.

Комментарии:

1. таким образом, единственный способ — maxOccurs =»неограниченный»