【问题标题】:XSD to constrain XML element values to existing XML attribute values?XSD 将 XML 元素值限制为现有 XML 属性值?
【发布时间】:2016-11-12 23:25:31
【问题描述】:

目标是限制BEST_FRIEND_ID 在此XML 中具有现有FRIEND_ID 属性的值:

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_IDelement 的值更改为 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-assertion:断言评估 ('$value = @FRIEND_ID') 用于模式类型上的元素“BEST_FRIEND_ID” “IdConstrain”没有成功。开始地点:6:10 结束地点: 6:25 网址:http://www.w3.org/TR/xmlschema11-1/#cvc-assertion

我也尝试过BEST_FRIEND_ID[contains(., @FRIEND_ID)] 之类的方法,但效果不佳。

【问题讨论】:

    标签: xml xsd xsd-validation xml-validation


    【解决方案1】:

    您应该使用以下方法来检查每个最好的朋友 id 是否都是现有的朋友 id。您还应该检查 bestfriend 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>
    

    您还可以检查 bestfriend id 是否与 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>
    

    【讨论】:

    • 遍历FRIEND/BEST_FRIEND_ID 可以按预期工作。即使创建了一个新的FRIEND 实例,也不需要将其FRIEND_ID 分配给任何BEST_FRIEND_ID。所有这一切都使这个答案正确 - 接受...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多