4

我不确定这是否可以通过 XML/XSD 实现,并且在搜索它时运气不佳。

您能否指定一个 XSD,以便在编写 XML 时,您可以拥有一个必须引用另一个 XML 元素中包含的值之一的元素?

例如,如果您有这个 XML:

<car>Audi</car>
<car>Ford</car>
<car>Honda</car>

<person>
  <drives>Audi</drives>
</person>

如何为驱动器指定 XSD,使其必须是为汽车输入的值之一?

4

3 回答 3

6

XSD 1.0 可以工作。理想情况下,您应该使用相同模式类型和参照完整性的组合。

一个 XSD:

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="sample">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element maxOccurs="unbounded" name="car" type="car"/>
                <xsd:element name="person">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="drives" type="car"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
        <xsd:key name="PKCars">
            <xsd:selector xpath="car"/>
            <xsd:field xpath="."/>
        </xsd:key>
        <xsd:keyref name="FKPersonCar" refer="PKCars">
            <xsd:selector xpath="person/drives"/>
            <xsd:field xpath="."/>
        </xsd:keyref>
    </xsd:element>
    <xsd:simpleType name="car">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="Audi"/>
            <xsd:enumeration value="Ford"/>
            <xsd:enumeration value="Honda"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

图表:

在此处输入图像描述

无效的 XML:

<sample>
    <car>Audi</car>
    <car>Ford</car>
    <car>Honda</car>

    <person>
        <drives>Aud</drives>
    </person>
</sample>

错误:

Error occurred while loading [], line 7 position 16
The 'drives' element is invalid - The value 'Aud' is invalid according to its datatype 'car' - The Enumeration constraint failed.
specify-xsd-such-that-an-xml-element-must-have-the-value-of-another-xml-element.xml is invalid.

这个错误告诉你使用枚举值会使 key/keyref 变得多余——你不会触发它。

但是,如果您的 XSD 中不能包含枚举值列表,则至少应该为该类型强制设置一个最小长度,以避免空值造成破坏。当然,虽然建议共享类型,但您不必这样做。

修改后的 XSD:

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="sample">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element maxOccurs="unbounded" name="car" type="car"/>
                <xsd:element name="person">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="drives" type="car"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
        <xsd:key name="PKCars">
            <xsd:selector xpath="car"/>
            <xsd:field xpath="."/>
        </xsd:key>
        <xsd:keyref name="FKPersonCar" refer="PKCars">
            <xsd:selector xpath="person/drives"/>
            <xsd:field xpath="."/>
        </xsd:keyref>
    </xsd:element>
    <xsd:simpleType name="car">
        <xsd:restriction base="xsd:normalizedString">
            <xsd:minLength value="1"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

错误信息:

Error occurred while loading [], line 9 position 4
The key sequence 'Aud' in Keyref fails to refer to some key.
specify-xsd-such-that-an-xml-element-must-have-the-value-of-another-xml-element.xml is invalid.
于 2012-11-09T01:49:53.907 回答
5

使用 XSD 1.1,您可以使用断言

断言组件约束相关元素和属性的存在和值。

您可以使用 XPath 2.0 表达式在断言中执行验证/测试。

此示例模式有一个/doc元素断言,可确保该/doc/person/drives值等于其中一个/doc/car元素:

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

    <xs:element name="car" type="xs:string" />  
    <xs:element name="drives" type="xs:string" />

    <xs:element name="person">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="drives"/>
            </xs:sequence>     
        </xs:complexType>
    </xs:element>

    <xs:element name="doc">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="car" maxOccurs="unbounded"/> 
                <xs:element ref="person"/>
            </xs:sequence> 
            <xs:assert test="person/drives = car"/>
        </xs:complexType>
    </xs:element>

</xs:schema>
于 2012-11-09T01:18:33.430 回答
1

这看起来像一个枚举,您的示例恰好与w3schools示例非常相似。

<xs:element name="car" type="carType"/>

<xs:simpleType name="carType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="Audi"/>
        <xs:enumeration value="Golf"/>
        <xs:enumeration value="BMW"/>
    </xs:restriction>
</xs:simpleType>

<xs:element name="person">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="drives" type="carType"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

如果不是,你可能想要 Pangaas 的答案。

于 2012-11-09T00:38:13.277 回答