Schema中有3种一致性约束:key约束、keyref约束和unique约束,这3种约束对命名空间的支持有点小问题,假设有以下Schema:
<!--key.xsd--> <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.xml.org/schema" targetNamespace="http://www.xml.org/schema"> <xs:complexType name="item_type"> <xs:complexContent> <xs:restriction base="xs:anyType"> <xs:sequence> <xs:element name="id" type="xs:int"/> <xs:element name="name" type="xs:token"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:element name="item" type="item_type"/> <xs:element name="test"> <xs:complexType> <xs:complexContent> <xs:restriction base="xs:anyType"> <xs:sequence> <xs:element ref="item" maxOccurs="unbounded"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:key name="idKey"> <xs:selector xpath="item"/> <!--①--> <xs:field xpath="id"/> <!--②--> </xs:key> </xs:element> </xs:schema>
上面的Schema是在<test.../>元素(根元素)以内定义了惟一约束,定义test/item之下的<id.../>元素的值必须遵照惟一约束。对于以下XML文档:
<!--key.xml--> <?xml version="1.0" encoding="UTF-8"?> <test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.xml.org/schema" xsi:schemaLocation="http://www.xml.org/schema key.xsd"> <item> <id>1</id> <name>dell</name> </item> <item> <id>1</id> <name>sony</name> </item> </test>
上面的XML文档中两个<item.../>元素里的<id.../>子元素的值彻底相同,这显然不符合惟一约束的要求,但这份XML文档依然是有效的。这是为何呢?发生这个问题是由于一致性约束对命名空间的支持有点小问题,上面的key.xsd定义一致性约束时在①、②号代码处直接使用了item、id两个元素,而没有任何前缀。本质上它们依然处于http://www.xml.org/schema命名...,只是因为指定了xmlns="http://www.xml.org/schema",所以在key.xsd中使用时无须添加限定短名做为前缀。但一致性约束不这么处理,它的处理规律是:只要该元素没有添加任何限定短名,它就认为该元素不处在任何命名空间下。也就是说,它约束的并非http://www.xml.org/schema命名...,而是对不在任何命名空间下的id进行约束,所以上面的key.xml文档天然也就有效了。编程
为了解决这个问题,当须要在Schema中对指定命名空间下的元素添加一致性约束时,必须为其添加限定短名做为前缀。能够把key.xsd该为以下形式:spa
<!--updated_key.xsd--> <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:sos="http://www.xml.org/schema" targetNamespace="http://www.xml.org/schema"> <xs:complexType name="item_type"> <xs:complexContent> <xs:restriction base="xs:anyType"> <xs:sequence> <xs:element name="id" type="xs:int"/> <xs:element name="name" type="xs:token"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:element name="item" type="sos:item_type"/> <xs:element name="test"> <xs:complexType> <xs:complexContent> <xs:restriction base="xs:anyType"> <xs:sequence> <xs:element ref="sos:item" maxOccurs="unbounded"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:key name="idKey"> <xs:selector xpath="sos:item"/> <!--①--> <xs:field xpath="sos:id"/> <!--②--> </xs:key> </xs:element> </xs:schema>
上面的updated_key.xsd中为item、id元素定义约束时指定了sos前缀,因而一致性约束就会根据该前缀找到对应的命名空间,完成对 http://www.xml.org/schema命名...。若是上面的key.xml改成使用updated_key.xsd这份Schema做为语义约束,那它就违反了惟一约束,天然也就是无效文档了。总结:
当须要在Schema中对指定命名空间下的元素(或属性)添加像key、keyref或unique约束时,必须为其添加限定短名做为前缀,不然一致性约束会认为只是对无命名空间的元素(或属性)添加约束。rest