Отслеживание с XSD
Я пытаюсь позволить моей XML-схеме обрабатывать небольшую функциональность трассируемости, поскольку я собираю требования, пока читаю некоторые функциональные спецификации. (Не идеально для управления требованиями, но, по крайней мере, это начало.)
То, что я делаю, - это создание тега < functionsSpec> для каждой функциональной спецификации, которую я сейчас читаю. Я создаю тег < требование> для каждого требования, которое я нахожу. Поскольку я хочу иметь возможность отслеживать происхождение требования, я создаю элемент < trace> с идентификатором элемента < functionsSpec>. Вместо того, чтобы позволять себе вводить какой-либо простой старый текст в тег < functionsSpecId>, я хочу, чтобы XSD проверил и убедился, что я ввожу только идентификатор, который существует для существующей функциональной спецификации. Моя проблема заключается в том, что, как мне кажется, в документации по рекомендациям XML-схемы W3C говорится, что то, что я хочу сделать, невозможно. (около 1/2 пути вниз)
{selector} определяет ограниченное выражение XPath ([XPath]) относительно экземпляров объявленного элемента. Это должно идентифицировать набор узлов подчиненных элементов (т. Е. Содержащихся в объявленном элементе), к которым применяется ограничение.
Я использую Oxygen для создания этого, так как я довольно плохо знаком с файлами XSD, и он выдает мне следующую ошибку:
E [Xerces] Ошибка ограничения идентификации: ограничение идентификации "KeyRef@1045a2" имеет ссылку на ключ, которая ссылается на ключ или уникальную информацию, которая находится вне области действия.
Поэтому мой вопрос: знает ли кто-нибудь способ, который позволит мне использовать ту же структуру XML, что и у меня ниже, с помощью XSD?
Ниже приведен XML-файл.
<?xml version="1.0" encoding="UTF-8" ?>
<srs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="srs req2.xsd"
xmlns="srs">
<requirements>
<requirement DateCreated="2010-06-11" id="1">
<Text>The system shall...</Text>
<trace>
<functionalSpecId>B010134</functionalSpecId>
</trace>
<revisions>
<revision date="2010-06-11" num="0">
<description>Initial creation.</description>
</revision>
</revisions>
</requirement>
</requirements>
<functionalSpecs>
<functionalSpec id="B010134" model="Model-T">
<trace>
<meeting></meeting>
</trace>
<revisions>
<revision date="2009-07-08" num="0">
<description>Initial creation.</description>
</revision>
<detailer>Me</detailer>
<engineer>Me</engineer>
</revisions>
</functionalSpec>
</functionalSpecs>
</srs>
Ниже приведен файл XSD.
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="srs"
xmlns="srs"
xmlns:srs="srs"
elementFormDefault="qualified">
<!-- SRS -->
<xs:element name="srs" type="SRSType">
</xs:element>
<xs:complexType name="SRSType">
<xs:sequence>
<xs:element ref="requirements" />
<xs:element ref="functionalSpecs" />
</xs:sequence>
</xs:complexType>
<!-- Requirements -->
<xs:element name="requirements" type="RequirementsType">
<xs:unique name="requirementId">
<xs:selector xpath="srs/requirements/requirement" />
<xs:field xpath="@id" />
</xs:unique>
</xs:element>
<xs:complexType name="RequirementsType">
<xs:choice maxOccurs="unbounded">
<xs:element name="requirement" type="RequirementType" />
</xs:choice>
</xs:complexType>
<xs:complexType name="RequirementType">
<xs:complexContent>
<xs:extension base="RequirementInfo">
<xs:sequence>
<xs:element name="trace" type="TraceType" maxOccurs="unbounded" minOccurs="1" />
<xs:element name="revisions" type="RequirementRevisions" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="RequirementRevisions">
<xs:sequence>
<xs:element name="revision" type="RevisionInfo" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="RequirementInfo">
<xs:sequence>
<xs:element name="Text" type="Description" />
</xs:sequence>
<xs:attribute name="DateCreated" type="xs:date" use="required" />
<xs:attribute name="id" type="xs:integer" use="required" />
</xs:complexType>
<!-- Functional Specs -->
<xs:element name="functionalSpecs" type="FunctionalSpecsType">
<xs:unique name="functionalSpecId">
<xs:selector xpath="srs/functionalSpecs/functionalSpec" />
<xs:field xpath="@id" />
</xs:unique>
</xs:element>
<xs:complexType name="FunctionalSpecsType">
<xs:choice maxOccurs="unbounded">
<xs:element name="functionalSpec" type="FunctionalSpecType" />
</xs:choice>
</xs:complexType>
<xs:complexType name="FunctionalSpecType">
<xs:complexContent>
<xs:extension base="FunctionalSpecInfo">
<xs:sequence>
<xs:element name="trace" type="TraceType" maxOccurs="unbounded" minOccurs="1" />
<xs:element name="revisions" type="FunctionalSpecRevisions" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="FunctionalSpecRevisions">
<xs:sequence>
<xs:element name="revision" type="RevisionInfo" minOccurs="1" maxOccurs="unbounded" />
<xs:element name="detailer" type="xs:string" />
<xs:element name="engineer" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="FunctionalSpecInfo">
<xs:attribute name="id" type="xs:string" use="required" />
<xs:attribute name="model" type="xs:string" use="required" />
</xs:complexType>
<!-- Requirements, Functional Specs -->
<xs:complexType name="TraceType">
<xs:choice>
<xs:element name="requirementId">
<xs:keyref refer="requirementId" name="requirementIdRef">
<xs:selector xpath="srs/requirements/requirement" />
<xs:field xpath="@id" />
</xs:keyref>
</xs:element>
<xs:element name="functionalSpecId">
<xs:keyref refer="functionalSpecId" name="functionalSpecIdRef">
<xs:selector xpath="srs/functionalSpecs/functionalSpec" />
<xs:field xpath="@id" />
</xs:keyref>
</xs:element>
<xs:element name="meeting" />
</xs:choice>
</xs:complexType>
<!-- Common -->
<xs:complexType name="RevisionInfo">
<xs:choice>
<xs:element name="description" type="Description" />
</xs:choice>
<xs:attribute name="date" type="xs:date" use="required" />
<xs:attribute name="num" type="xs:integer" use="required" />
</xs:complexType>
<xs:complexType name="Description" mixed="true">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Date" type="xs:date" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
1 ответ
Я почти уверен, что уже сделал то, что вы пытаетесь достичь здесь. Хитрость заключается в том, чтобы определить ограничения уникальности, ключа и ключевой ссылки на более высоком уровне (элемент srs в вашем случае). Вот пример кода, который проверяет, что "требуются" элементы, определенные в элементе /@name:
Обратите внимание, как ограничения определяются на уровне элементов.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="item">
<xs:complexType>
<xs:sequence>
<xs:element ref="special" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="requires" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="mana" type="xs:int"/>
<xs:attribute name="life" type="xs:int"/>
<xs:attribute name="manaRegen" type="xs:int"/>
<xs:attribute name="hitRegen" type="xs:int"/>
<xs:attribute name="damage" type="xs:int"/>
<xs:attribute name="armor" type="xs:int"/>
<xs:attribute name="attackSpeed" type="xs:int"/>
<xs:attribute name="moveSpeed" type="xs:int"/>
<xs:attribute name="str" type="xs:int"/>
<xs:attribute name="agi" type="xs:int"/>
<xs:attribute name="int" type="xs:int"/>
<xs:attribute name="cost" type="xs:int" use="required"/>
<xs:attribute name="image"/>
</xs:complexType>
</xs:element>
<xs:element name="items">
<xs:complexType>
<xs:sequence>
<xs:element ref="shop" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="version" type="xs:string"/>
</xs:complexType>
<xs:unique name="uniqueItemNames">
<xs:selector xpath="shop/item"/>
<xs:field xpath="@name"/>
</xs:unique>
<xs:unique name="uniqueShopNames">
<xs:selector xpath="shop"/>
<xs:field xpath="@name"/>
</xs:unique>
<xs:key name="itemKey">
<xs:selector xpath="shop/item"/>
<xs:field xpath="@name"/>
</xs:key>
<xs:keyref name="requiresValue" refer="itemKey">
<xs:selector xpath="shop/item/requires"/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>
<xs:element name="requires" type="xs:string"/>
<xs:element name="shop">
<xs:complexType>
<xs:sequence>
<xs:element ref="item" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="specialType">
<xs:restriction base="xs:string">
<xs:enumeration value="Activate"/>
<xs:enumeration value="Aura"/>
<xs:enumeration value="Effect"/>
<xs:enumeration value="Orb"/>
<xs:enumeration value="Info"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="special">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="specialType" use="required"/>
<xs:attribute name="mana" type="xs:int"/>
<xs:attribute name="cooldown" type="xs:int"/>
<xs:attribute name="chance" type="xs:int"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
Пример XML:
<?xml version="1.0" encoding="UTF-8"?>
<items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="dota.xsd" version="6.52d">
<shop name="Leragas The Vile">
<item name="Demon's Edge" image="FrostMourne.gif" cost="2600" damage="36"/>
<item name="Eaglehorn" image="INV_Weapon_Bow_06.gif" cost="3300" agi="25"/>
<item name="Messerschmidt's Reaver" image="SpiritWalkerMasterTraining.gif" cost="3200" str="25"/>
<item name="Sacred Relic" image="StaffOfTeleportation.gif" cost="3800" damage="60"/>
<item name="Hyperstone" image="Periapt1.gif" cost="2100" attackSpeed="55"/>
<item name="Ring of Health" image="GoldRing.gif" cost="875" hitRegen="5"/>
<item name="Void Stone" image="Periapt.gif" cost="875" manaRegen="100"/>
<item name="Mystic Staff" image="StaffOfNegation.gif" cost="2700" int="25"/>
<item name="Energy Booster" image="EnchantedGemstone.gif" cost="1000" mana="250"/>
<item name="Point Booster" image="UsedSoulGem.gif" cost="1200" life="200" mana="150"/>
<item name="Vitality Booster" image="SoulGem.gif" cost="1100" life="250"/>
</shop>
<shop name="Level 1 (Human) Recipes">
<item name="Perseverance" image="OrbOfFire.gif" cost="0" damage="10" hitRegen="5" manaRegen="125">
<requires>Ring of Health</requires>
<requires>Void Stone</requires>
</item>
<item name="Headdress of Rejuvenation" image="INV_Helmet_17.gif" cost="225" agi="2" int="2" str="2">
<special type="Aura">+2 HP/Sec regen (500 AoE)</special>
<requires>Ring of Regeneration</requires>
<requires>Ironwood Branch</requires>
</item>
</shop>
</items>