如何为嵌套元素设置XSD唯一约束?附XML示例
没问题,我来帮你搞定这个嵌套XML的XSD唯一约束配置。先看你的XML结构,核心是两层需要唯一校验的场景:全局范围内所有<chain>的chainName属性唯一,以及每个<chain>内部的<handler>的handlerName属性唯一对吧?下面分情况给你详细说明配置方式:
1. 全局所有
<chain>的chainName唯一 要实现这个,我们可以在根元素<catalog>下定义xs:unique约束,指定选择所有<chain>节点,并校验它们的chainName属性值不重复。
示例代码片段:
<xs:element name="catalog"> <xs:complexType> <xs:sequence> <xs:element name="chainList"> <xs:complexType> <xs:sequence> <xs:element name="chain" maxOccurs="unbounded"> <!-- 这里定义chain的结构 --> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <!-- 全局chainName唯一约束 --> <xs:unique name="uniqueChainName"> <xs:selector xpath="chainList/chain"/> <xs:field xpath="@chainName"/> </xs:unique> </xs:element>
2. 每个
<chain>内部的<handler>的handlerName唯一 这个场景是局部唯一,约束范围限定在单个<chain>内部,确保同一个chain下的handler不会有重复的handlerName。我们需要把xs:unique定义在<chain>元素内部:
示例代码片段:
<xs:element name="chain" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="handlerList"> <xs:complexType> <xs:sequence> <xs:element name="handler" maxOccurs="unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="handlerName" type="xs:string" use="required"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="chainName" type="xs:string" use="required"/> </xs:complexType> <!-- 当前chain内部handlerName唯一约束 --> <xs:unique name="uniqueHandlerNameInChain"> <xs:selector xpath="handlerList/handler"/> <xs:field xpath="@handlerName"/> </xs:unique> </xs:element>
完整XSD示例
把上面两部分整合起来,对应你的XML结构的完整XSD如下:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="catalog"> <xs:complexType> <xs:sequence> <xs:element name="chainList"> <xs:complexType> <xs:sequence> <xs:element name="chain" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="handlerList"> <xs:complexType> <xs:sequence> <xs:element name="handler" maxOccurs="unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="handlerName" type="xs:string" use="required"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="chainName" type="xs:string" use="required"/> </xs:complexType> <!-- 单个chain内handlerName唯一约束 --> <xs:unique name="uniqueHandlerNameInChain"> <xs:selector xpath="handlerList/handler"/> <xs:field xpath="@handlerName"/> </xs:unique> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <!-- 全局chainName唯一约束 --> <xs:unique name="uniqueChainName"> <xs:selector xpath="chainList/chain"/> <xs:field xpath="@chainName"/> </xs:unique> </xs:element> </xs:schema>
简单解释下关键部分:
xs:selector:指定要检查唯一性的节点集合,xpath路径是相对于定义约束的元素的。xs:field:指定要校验唯一的属性或元素内容,这里就是对应的@chainName和@handlerName属性。
这样配置之后,你的XML如果出现以下两种情况都会在校验时报错:
- 两个不同的
<chain>使用了相同的chainName值; - 同一个
<chain>下的两个<handler>使用了相同的handlerName值。
内容的提问来源于stack exchange,提问作者Lorelorelore
相关产品推荐
相关产品推荐

