2016-11-12 143 views
2

的目標是約束BEST_FRIEND_ID有這一個XML現有FRIEND_ID屬性的值:XSD將XML元素值約束爲現有的XML屬性值?

friends.xml

<?xml version="1.0"?> 
<FRIENDS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="friends.xsd"> 
    <FRIEND FRIEND_ID="1"> 
     <NAME>John</NAME> 
     <BEST_FRIEND_ID>2</BEST_FRIEND_ID> 
    </FRIEND> 
    <FRIEND FRIEND_ID="2"> 
     <NAME>Kate</NAME> 
     <BEST_FRIEND_ID>1</BEST_FRIEND_ID> 
    </FRIEND> 
</FRIENDS> 

例如對於給定的XML,如果我將任何BEST_FRIEND_ID元素的值更改爲3,則驗證應該失敗。

friends.xsd

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" 
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"> 
    <xs:complexType name="FriendsType"> 
     <xs:sequence> 
      <xs:element ref="FRIEND" maxOccurs="unbounded"/> 
     </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="FriendType"> 
     <xs:sequence> 
      <xs:element ref="NAME"/> 
      <xs:element ref="BEST_FRIEND_ID"/> 
     </xs:sequence> 
     <xs:attribute name="FRIEND_ID" type="xs:integer"/> 
    </xs:complexType> 

    <xs:element name="FRIENDS" type="FriendsType"/> 
    <xs:element name="FRIEND" type="FriendType"/> 
    <xs:element name="NAME" type="xs:string"/> 
    <xs:element name="BEST_FRIEND_ID" type="xs:integer"/> 
</xs:schema> 

我的想法是用權力的斷言(XSD 1.1)。這是我已經想通了,到目前爲止

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" 
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1"> 
    <xs:complexType name="FriendsType"> 
     <xs:sequence> 
      <xs:element ref="FRIEND" maxOccurs="unbounded"/> 
     </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="FriendType"> 
     <xs:sequence> 
      <xs:element ref="NAME"/> 
      <xs:element ref="BEST_FRIEND_ID"/> 
     </xs:sequence> 
     <xs:attribute name="FRIEND_ID" type="xs:integer"/> 
    </xs:complexType> 
    <xs:complexType name="IdConstrain"> 
     <xs:simpleContent> 
      <xs:extension base="xs:integer"> 
       <xs:assert test="$value = @FRIEND_ID"/> 
      </xs:extension> 
     </xs:simpleContent> 
    </xs:complexType> 

    <xs:element name="FRIENDS" type="FriendsType"/> 
    <xs:element name="FRIEND" type="FriendType"/> 
    <xs:element name="NAME" type="xs:string"/> 
    <xs:element name="BEST_FRIEND_ID" type="IdConstrain"/> 
</xs:schema> 

和驗證失敗:

嚴重性:錯誤描述:CVC-斷言:斷言評價 ( '$值= @FRIEND_ID')爲架構類型爲 'IdConstrain'的元素'BEST_FRIEND_ID'未成功。起始位置:6:10結束位置: 6:25網址:http://www.w3.org/TR/xmlschema11-1/#cvc-assertion

我也嘗試過的東西,如BEST_FRIEND_ID[contains(., @FRIEND_ID)]但它不正常工作。

回答

1

您應該使用以下內容來檢查每個最好的朋友ID是否是現有的朋友ID。您也應該檢查最好的朋友ID不等於本身:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified" 
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" 
    vc:minVersion="1.1"> 

    <xs:complexType name="FriendsType"> 
     <xs:sequence> 
      <xs:element ref="FRIEND" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:assert test="every $bfid in FRIEND/BEST_FRIEND_ID 
      satisfies $bfid = (FRIEND/@FRIEND_ID)"/> 
     <!-- Optional check best friend is not equals to itself --> 
     <xs:assert test="every $fr in FRIEND 
      satisfies $fr/@FRIEND_ID != $fr/BEST_FRIEND_ID"/> 
    </xs:complexType> 

    <xs:complexType name="FriendType"> 
     <xs:sequence> 
      <xs:element ref="NAME"/> 
      <xs:element ref="BEST_FRIEND_ID"/> 
     </xs:sequence> 
     <xs:attribute name="FRIEND_ID" type="xs:integer"/> 
    </xs:complexType> 

    <xs:element name="FRIENDS" type="FriendsType"/> 
    <xs:element name="FRIEND" type="FriendType"/> 
    <xs:element name="NAME" type="xs:string"/> 
    <xs:element name="BEST_FRIEND_ID" type="xs:integer"/> 
</xs:schema> 

你也可以檢查是最好的朋友ID是diferent裏面FRIEND標籤,而不是FRIENDS標籤的朋友id。

<xs:complexType name="FriendType"> 
    <xs:sequence> 
     <xs:element ref="NAME"/> 
     <xs:element ref="BEST_FRIEND_ID"/> 
    </xs:sequence> 
    <xs:attribute name="FRIEND_ID" type="xs:integer"/> 
    <xs:assert test="@FRIEND_ID != BEST_FRIEND_ID"/> 
</xs:complexType> 
+0

通過'FRIEND/BEST_FRIEND_ID'迭代按預期工作。即使創建了新的FRIEND實例,也不需要將其FRIEND_ID分配給任何「BEST_FRIEND_ID」。所有這使得這個答案正確 - 接受... – pbajsarowicz