Если у меня есть элемент в XML, который представляет собой целое число, представляющее счетчик n
. И если у меня есть элемент с последовательностью элементов, имеющих идентификатор атрибута, который должен начинаться с 1 и идти вверх до n
.
Есть ли какой-нибудь способ в xsd гарантировать, что последовательность элементов начинается с атрибута id=1, увеличивается на единицу для каждого следующего элемента и останавливается на номере, указанном значением другого элемента?
Спасибо за отзыв. Я посмотрю на это на следующей неделе.
Минимальный пример XML-файла может выглядеть так:
<root>
<meta>
<count>3</count>
</meta>
<data>
<row id = "1">2.1</row>
<row id = "2">3.6</row>
<row id = "3">5.4</row>
</data>
</root>
Таким образом, значение Meta.count должно соответствовать общему количеству элементов строки, и эти элементы должны начинаться с 1 до значения счетчика.
Я попробовал что-то подобное и обнаружил, что, поскольку я не могу охватить братьев и сестер в тесте, мне нужно перенести тест на более высокий элемент, и это работает.
Однако я не могу использовать значение одного из элементов как maxOccurs. Но, возможно, я смогу создать для этого третий тест. Обновлено: Да, можно сравнить количество строк со значением count. Спасибо за поддержку.
<?xml version = "1.0" encoding = "UTF-8"?>
<xs:schema attributeFormDefault = "unqualified" elementFormDefault = "qualified"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:vc = "http://www.w3.org/2007/XMLSchema-versioning"
xmlns:xerces = "http://xerces.apache.org" vc:minVersion = "1.1">
<xs:element name = "row">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:float">
<xs:attribute name = "id" use = "required" type = "xs:positiveInteger"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name = "root">
<xs:complexType>
<xs:sequence>
<xs:element name = "meta">
<xs:complexType>
<xs:sequence>
<xs:element name = "count" type = "xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "data">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs = "unbounded" ref = "row"/>
<!-- <xs:element maxOccurs = "root/meta/count" ref = "row"/> -->
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:assert test = "count(data/row) = meta/count"/>
<xs:assert test = "max(data/row/@id) = meta/count"/>
<xs:assert test = "every $x in (1 to meta/count) satisfies data/row[$x]/@id = $x"
xerces:message = "Rule #2.1: attribute id shall start at 1 and go up till @total value."/>
</xs:complexType>
</xs:element>
</xs:schema>
Утверждение XSD 1.1 должно справиться с этим.
Задавая вопрос XSD, вам необходимо предоставить минимальный воспроизводимый пример: (1) Правильно сформированный входной XML. (2) Ваша логика и полные исполняемые файлы XSD, которые пытаются ее реализовать. (3) Процессор XSD и его соответствие стандартам XSD: 1.0 или 1.1.
В XSD 1.1 вы можете написать что-то вроде
<xs:element name = "parent">
...
<xs:assert test = "every $child in ./child
satisfies @id = count($child/preceding-sibling::child)+1"/>
</xs:element>
Спасибо за подсказку. Это решает проблему возрастающего порядка IG.
Попробуйте следующее решение с помощью XSD 1.1 и Xerces.
Если внести небольшие изменения, он будет работать с Saxon и другими процессорами, совместимыми с XSD 1.1.
Даже в Python: Можно ли проверить XML-файл на соответствие XSD 1.1 в Python?
Он использует утверждение с количественным выражением для выражения желаемой логики.
XML
<root total = "5">
<r id = "1"/>
<r id = "2"/>
<r id = "3"/>
<r id = "4"/>
<r id = "5"/>
</root>
XSD 1.1
<?xml version = "1.0" encoding = "UTF-8"?>
<xs:schema attributeFormDefault = "unqualified" elementFormDefault = "qualified"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:vc = "http://www.w3.org/2007/XMLSchema-versioning"
xmlns:xerces = "http://xerces.apache.org" vc:minVersion = "1.1">
<xs:element name = "root">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs = "unbounded" ref = "r"/>
</xs:sequence>
<xs:attribute name = "total" use = "required" type = "xs:positiveInteger"/>
<xs:assert test = "every $x in (1 to @total) satisfies r[$x]/@id = $x"
xerces:message = "Rule #2.1: attribute id shall start at 1 and go up till @total value."/>
</xs:complexType>
</xs:element>
<xs:element name = "r">
<xs:complexType>
<xs:attribute name = "id" use = "required" type = "xs:positiveInteger"/>
</xs:complexType>
</xs:element>
</xs:schema>
Это выглядит многообещающе. Я не узнал о реферале, который вы используете. Пока что я решил навести порядок в своем xsd, определяя типы. Можно ли вместо maxOccurence = "unbounded" указать что-то вроде maxOccurs = "@total"? Можно ли использовать в качестве итогового значение другого элемента вместо значения атрибута родительского элемента?
Боюсь, принятие желаемого за действительное.
@FordPrefect, я предоставил вам надежное работающее решение. Была ли у вас возможность попробовать?
Пока нет, думаю, в понедельник попробую.
@YitzhakKhabinsky Сейчас я попытался преобразовать ваш пример xsd в мой минимальный пример xml, но не смог заставить его работать. Вероятно, нельзя ссылаться на братьев и сестер в утверждении xsd.
Я нашел решение. Спасибо за помощь.
Ничего не нашел. Вот ограничения схемы: w3schools.com/xml/schema_facets.asp