我不确定这是否可以通过 XML/XSD 实现,并且在搜索它时运气不佳。
您能否指定一个 XSD,以便在编写 XML 时,您可以拥有一个必须引用另一个 XML 元素中包含的值之一的元素?
例如,如果您有这个 XML:
<car>Audi</car>
<car>Ford</car>
<car>Honda</car>
<person>
<drives>Audi</drives>
</person>
如何为驱动器指定 XSD,使其必须是为汽车输入的值之一?
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.
使用 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>
这看起来像一个枚举,您的示例恰好与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 的答案。