2016-11-12 141 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