2010-06-11 51 views
4

我试图让我的XML模式处理一点追踪功能,因为我在阅读某些功能规范时收集了需求。 (不理想的需求管理,但至少它是一个开始。)XSD的可追溯性

我在做什么是创造我正在读通过每一个功能规范< functionalSpec>标签。我为每个需求创建一个< 要求>标签。由于我希望能够跟踪需求来自何处,因此我创建了一个元素,其中元素为< 10功能规格>元素。我不希望自己在标签中输入任何普通旧文本,而是希望XSD验证并确保我只输入存在现有功能规范的ID。我的问题即将到来,看起来XML Schema W3C Recommendations文档说,我想要做的是不可能的。 (约1/2一路下滑)

{selector} specifies a restricted XPath ([XPath]) expression relative to instances of the element being declared. This must identify a node set of subordinate elements (i.e. contained within the declared element) to which the constraint applies.

我用氧气来创建这个,因为我是相当新的XSD文件,它给我下面的错误:

E [Xerces] Identity Constraint error: identity constraint "[email protected]" has a keyref which refers to a key or unique that is out of scope.

所以我问题是否有人知道一种方法可以让我通过使用XSD使用下面的相同XML结构?

以下是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> 

回答

3

我很确定我已经完成了您在此尝试实现的目标。 诀窍在于定义更高级别的唯一键,key和keyref约束(在您的案例中为srs元素)。 下面是一些代码示例,用于检查项目/ @名称中的“要求”元素:

请注意约束是如何在项目级别定义的。

<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>