Ограничете броя на срещанията на елемент въз основа на стойност на атрибут

Имам XML, който изглежда така:

<Artifacts count="2">
  <Artifact>
    ...
  </Artifact>
  <Artifact>
    ...
  </Artifact>
 </Artifacts>

Търся начин да наложа, че броят на Artifact елементите, съдържащи се в Artifacts, трябва да бъде равен на стойността на атрибута "count", като използвам XSD схема.

Въпреки че намерих възможни начини да постигна това с помощта на спецификацията XSD 1.1, чудя се дали изобщо е възможно без нея, т.е. въз основа на спецификацията XSD 1.0.


Редактиране: Ще се опитам да осигуря малко повече контекст на въпроса, за да бъда по-прецизен.
XML файлът ще бъде предоставен като вход към C++ приложение. Проблемът е, че средата за разработка налага използването на библиотеката Xerces v. 2.8.0 за анализиране. Доколкото разбирам, тази версия не поддържа стандарта XSD 1.1.

Разбира се, мога да добавя допълнителен код, за да проверя за правилния брой срещания на Artifact елементи след валидирането на XSD. Надявах се, че ще има начин да избегна допълнителния кодов сегмент и напълно да валидирам входния файл въз основа само на XSD.


person Vag    schedule 01.04.2015    source източник


Отговори (2)


Правилният термин за вида ограничение, което искате да моделирате, е твърдение. Не, твърденията не са възможни в XML Schema 1.0. Единствените езици за валидиране, които поддържат твърдения, са XML Schema 1.1 (xs:assert) и Schematron (sch:assert и sch:report).

Освен това можете да напишете XPath изрази или XSLT таблици със стилове, които тестват правилния брой Artifact елементи:

/Artifacts/@count = count(/Artifacts/Artifact)

XML файлът ще бъде предоставен като вход към C++ приложение. Проблемът е, че средата за разработка налага използването на библиотеката Xerces v. 2.8.0 за анализиране. Доколкото разбирам, тази версия не поддържа стандарта XSD 1.1.

Предполагам, че Xerces 2.8.0 (остаряла версия, която вече не се поддържа) не съответства на XSD 1.1, но най-лесният начин да разберете е просто да го тествате. Включете всеки xs:assert в схема и вижте какво ще се случи.

Разбира се, мога да добавя допълнителен код, за да проверя за правилния брой срещания на елементите "Artifact" след валидирането на XSD. Надявах се, че ще има начин да избегна допълнителния кодов сегмент и напълно да валидирам входния файл въз основа само на XSD.

Не, само с XSD 1.0 не можете да избегнете тези допълнителни редове код.


РЕДАКТИРАНЕ Това, което @kjhughes написа в коментар, всъщност трябва да е част от отговора:

Това е правилно и аз също бих оспорил дизайна на OP, който изисква атрибут, който просто отразява броя на дъщерните атрибути.

От гледна точка на дизайна на XML, ако този атрибут не прави нищо друго освен да посочи колко Artifact елемента има, защо го включихте на първо място? Винаги трябва да не сте склонни да съхранявате излишна и възстановима информация. Например, няма нужда да съхранявате позицията на дъщерните елементи по следния начин:

<root>
  <child n="1"/>
  <child n="2"/>
</root>

И вашият атрибут count прави нещо много подобно.

person Mathias Müller    schedule 01.04.2015
comment
Благодаря ви за отговора. Надявах се, че ще има начин да манипулирам схемата, за да изпълня наддаването ми, но изглежда, че няма. Ще му дам още малко време, за да видя дали ще се появят луди идеи от други потребители, в противен случай този отговор е страхотен и правилен! Междувременно създавам схемата с предвид това ограничение и търся начини за включване на XLST и XPath. - person Vag; 01.04.2015
comment
Това е правилно и аз също бих оспорил дизайна на OP, който изисква атрибут, който просто отразява броя на дъщерните атрибути. - person kjhughes; 01.04.2015
comment
@kjhughes Добра точка, опитах се да редактирам това в отговора си - уведомете ме, ако все още има нужда от подобрение. - person Mathias Müller; 01.04.2015
comment
Съгласен съм, че това е лошо дизайнерско решение, но за съжаление не е моя идея да променям. Опитвам се само да информирам схема за дадения XML файл. - person Vag; 02.04.2015

Ще приема, че стойността на броя е динамична въз основа на действителния брой елементи на артефакта. Един от начините (тъй като не знам какъв е вашият контекст) може да бъде да модифицирам XSD с minOccurs и maxOccurs според тази стойност и след това да проверя спрямо новата схема...

<xsd:complexType name="Artifacts">
    <xsd:sequence>
      <xsd:element name="Artifact" minOccurs="COUNT_VALUE" maxOccurs="COUNT_VALUE" />      
    </xsd:sequence>   
</xsd:complexType>
person exoddus    schedule 01.04.2015
comment
Стойността на minOccurs трябва да бъде 0 или положително цяло число, COUNT_VALUE няма да работи. - person Mathias Müller; 01.04.2015
comment
прав си @Mathias за minOccurs! защо задаването на maxOccurs като същата стойност като атрибут count от анализиран xml вход, запазване в нова схема и валидиране спрямо тази нова няма да работят? - person exoddus; 01.04.2015
comment
Да, това ще свърши работа, но това е много ръчен труд, не мислите ли? Всеки път, когато искате да потвърдите документ, трябва да промените схемата. Според мен смисълът на схемите е автоматично валидиране, без да се изисква човешка намеса. - person Mathias Müller; 01.04.2015
comment
Сигурен! Ужасно е! Просто беше първият ми подход за решаване на проблем, без да знам целия контекст. Но след като напишете този процес, той също е автоматичен (не е оптималното, нито най-доброто решение, разбира се). - person exoddus; 01.04.2015
comment
Виждам - ​​това наистина би било опция, но след това 1) всеки документ има своя собствена схема, което е малко странно и 2) ако можете да модифицирате XSD документ, защо просто не тествате за това условие директно с XPath израз? - person Mathias Müller; 01.04.2015
comment
Благодаря ви за отговора. За съжаление редактирането на XSD, за да съответства на XML, изглежда малко неправилно, тъй като се опитвам да наложа шаблон на потребителя. Вашето предложение обаче ще доведе до желания резултат! - person Vag; 01.04.2015