我有这样的结构:
<EnumDefinitions>
<EnumDefinition enumName="MyEnum1">
<Values>
<Value value="1" valueName="MyEnumValue1"/>
<Value value="2" valueName="MyEnumValue2"/>
</Values>
</EnumDefinition>
<EnumDefinition enumName="MyEnum10">
<Values>
<Value value="10" valueName="MyEnumValue10"/>
<Value value="20" valueName="MyEnumValue20"/>
</Values>
</EnumDefinition>
</EnumDefinitions>
<EnumReference EnumName="MyEnum1" EnumValueName="MyEnumValue0"/>
<EnumReference EnumName="MyEnum1" EnumValueName="MyEnumValue10"/>
我希望第一个EnumReference有效,但第二个应该失败。 为此我尝试了这个独特的keyref:
<xs:keyref name="keyref_EnumNameValue" refer="unique_EnumNameValuePair">
<xs:selector xpath="EnumReference"/>
<xs:field xpath="@EnumName"/>
<xs:field xpath="@EnumValueName"/>
</xs:keyref>
<xs:unique name="unique_EnumNameValuePair">
<xs:selector xpath="EnumDefinitions/EnumDefinition"/>
<xs:field xpath="@enumName"/>
<xs:field xpath="Values/Value/@valueName"/>
</xs:unique>
然后我通过验证收到错误:
标识约束'unique_EnumNameValuePair'的字段'{anonymous}'评估为具有多个成员的节点集。
有可能这样做吗?
答案 0 :(得分:2)
使用XSD的key / unique和keyref:您可以单独确保@EnumName值的属性与现有的@enumName匹配,并且@EnumValueName由@valueName匹配;给定当前的EnumDefinition结构(从面向对象是有意义的),你不能同时实现。
我明白为什么 - 例如程序员使用XML的可用性 - 您可以选择通过在EnumReference的@EnumName和@EnumValueName中复制它们来复制(在数据库术语中使用非规范化)值。您可能需要考虑这会对XML的性能和大小产生负面影响;特别是如果你的XML中有很多EnumReference ......
与关系模型非常一致的替代方法可能是简单地为每个EnumDefinition的Value元素添加一个标识属性,比如@aid。您的XML将如此:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root>
<EnumDefinitions>
<EnumDefinition enumName="MyEnum1">
<Values>
<Value aid="a" value="1" valueName="MyEnumValue1"/>
<Value aid="b" value="2" valueName="MyEnumValue2"/>
</Values>
</EnumDefinition>
<EnumDefinition enumName="MyEnum10">
<Values>
<Value aid="c" value="10" valueName="MyEnumValue10"/>
<Value aid="d" value="20" valueName="MyEnumValue20"/>
</Values>
</EnumDefinition>
</EnumDefinitions>
<EnumReference aid="a"/>
<EnumReference aid="f"/>
</root>
带有约束的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="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="EnumDefinitions">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="EnumDefinition">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Values">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="Value">
<xsd:complexType>
<xsd:attributeGroup ref="aid"/>
<xsd:attribute name="value" type="xsd:unsignedByte" use="required"/>
<xsd:attribute name="valueName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="ValueUC">
<xsd:selector xpath="Value"/>
<xsd:field xpath="@value"/>
</xsd:key>
<xsd:key name="ValueNameUC">
<xsd:selector xpath="Value"/>
<xsd:field xpath="@valueName"/>
</xsd:key>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="enumName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="EnumNameUC">
<xsd:selector xpath="EnumDefinition"/>
<xsd:field xpath="@enumName"/>
</xsd:key>
</xsd:element>
<xsd:element maxOccurs="unbounded" name="EnumReference">
<xsd:complexType>
<xsd:attributeGroup ref="aid"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="PK">
<xsd:selector xpath="EnumDefinitions/EnumDefinition/Values/Value"/>
<xsd:field xpath="@aid"/>
</xsd:key>
<xsd:keyref name="FK" refer="PK">
<xsd:selector xpath="EnumReference"/>
<xsd:field xpath="@aid"/>
</xsd:keyref>
</xsd:element>
<xsd:attributeGroup name="aid">
<xsd:attribute name="aid" type="xsd:string" use="required"/>
</xsd:attributeGroup>
</xsd:schema>
看起来像这样:
这意味着:
如果你不能对结构做任何事情,那么唯一的替代方案是Schematron在XSD 1.0之上,或者转移到XSD 1.1处理器(此时不是那种传播,祝你在各个平台上找到好的,免费的处理器)