XSD唯一约束,带有多个成员的字段

时间:2013-09-25 14:54:23

标签: xml xsd

我有这样的结构:

<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}'评估为具有多个成员的节点集。

有可能这样做吗?

1 个答案:

答案 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>

看起来像这样:

enter image description here

这意味着:

  • 您的交叉引用就PK / FK约束而言
  • 通过UC后缀限制确保您的诚信。

如果你不能对结构做任何事情,那么唯一的替代方案是Schematron在XSD 1.0之上,或者转移到XSD 1.1处理器(此时不是那种传播,祝你在各个平台上找到好的,免费的处理器)