XML XSD中为不同id枚举值配置专属内容限制的问题
问题描述
我从以下XML生成了XSD文件:
<Edits> <Item id="AlignmentLargerThanSize">0.0</Item> <Item id="Machine">PI-8200</Item> <Item id="PackagePCBNames">Deepest level</Item> <Item id="ManualExactOutlineStroke">10.0</Item> <Item id="AlignmentPoint1Y">0.0</Item> <Item id="PolarityComboBox">Positive</Item> <Item id="AlignmentLessThanSize">10.0</Item> </Edits>
生成的XSD如下:
<xs:element name="Item"> <xs:complexType> <xs:simpleContent> <xs:extension base="ST_Item"> <xs:attribute name="id" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="AlignmentLargerThanSize"/> <xs:enumeration value="Machine"/> <xs:enumeration value="PackagePCBNames"/> <xs:enumeration value="ManualExactOutlineStroke"/> <xs:enumeration value="AlignmentPoint1Y"/> <xs:enumeration value="PolarityComboBox"/> <xs:enumeration value="AlignmentLessThanSize"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:simpleType name="ST_Item"> <xs:restriction base="xs:string"> <xs:enumeration value=""/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType>
但这个生成结果不符合需求,我需要为每个id枚举值配置专属的内容限制,示例如下:
<xs:simpleType name="Item1" id="AlignmentLessThanSize"> <xs:restriction base="xs:decimal"> <xs:minInclusive value="0"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="Item2" id="AlignmentLargerThanSize"> <xs:restriction base="xs:decimal"> <xs:minExclusive value="0"/> </xs:restriction> </xs:simpleType>
请问如何实现这种为不同id枚举值绑定专属内容限制的XSD配置?
解决方案
要实现基于id属性值约束元素内容的需求,得靠XSD 1.1的特性——XSD 1.0不支持这种条件化的类型绑定。下面提供两种可行的实现方式:
方式一:条件类型赋值(清晰易维护)
给每个id对应的Item定义专属简单类型,通过条件匹配自动绑定对应的内容约束:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1"> <!-- 为每个id定义专属内容约束类型 --> <xs:simpleType name="AlignmentLessThanSizeType"> <xs:restriction base="xs:decimal"> <xs:minInclusive value="0"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="AlignmentLargerThanSizeType"> <xs:restriction base="xs:decimal"> <xs:minExclusive value="0"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="MachineType"> <xs:restriction base="xs:string"> <xs:enumeration value="PI-8200"/> <xs:enumeration value="PI-8300"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="PackagePCBNamesType"> <xs:restriction base="xs:string"> <xs:minLength value="1"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="AlignmentPoint1YType"> <xs:restriction base="xs:decimal"> <xs:minInclusive value="-100"/> <xs:maxInclusive value="100"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="PolarityComboBoxType"> <xs:restriction base="xs:string"> <xs:enumeration value="Positive"/> <xs:enumeration value="Negative"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="ManualExactOutlineStrokeType"> <xs:restriction base="xs:decimal"> <xs:minInclusive value="1"/> <xs:maxInclusive value="20"/> </xs:restriction> </xs:simpleType> <!-- 定义Item元素,根据id匹配对应类型 --> <xs:element name="Item"> <xs:alternative test="@id = 'AlignmentLessThanSize'" type="AlignmentLessThanSizeType"/> <xs:alternative test="@id = 'AlignmentLargerThanSize'" type="AlignmentLargerThanSizeType"/> <xs:alternative test="@id = 'Machine'" type="MachineType"/> <xs:alternative test="@id = 'PackagePCBNames'" type="PackagePCBNamesType"/> <xs:alternative test="@id = 'AlignmentPoint1Y'" type="AlignmentPoint1YType"/> <xs:alternative test="@id = 'PolarityComboBox'" type="PolarityComboBoxType"/> <xs:alternative test="@id = 'ManualExactOutlineStroke'" type="ManualExactOutlineStrokeType"/> <!-- 默认匹配错误,确保id必须在枚举范围内 --> <xs:alternative type="xs:error"/> </xs:element> <!-- 定义外层Edits容器 --> <xs:element name="Edits"> <xs:complexType> <xs:sequence> <xs:element ref="Item" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
方式二:断言(紧凑灵活)
如果不想单独定义类型,也可以在Item的复杂类型中通过xs:assert直接添加条件校验:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1"> <xs:element name="Edits"> <xs:complexType> <xs:sequence> <xs:element ref="Item" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Item"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="id" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="AlignmentLargerThanSize"/> <xs:enumeration value="Machine"/> <xs:enumeration value="PackagePCBNames"/> <xs:enumeration value="ManualExactOutlineStroke"/> <xs:enumeration value="AlignmentPoint1Y"/> <xs:enumeration value="PolarityComboBox"/> <xs:enumeration value="AlignmentLessThanSize"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:extension> </xs:simpleContent> <!-- 断言:根据id校验内容合法性 --> <xs:assert test=" (@id = 'AlignmentLessThanSize' and . castable as xs:decimal and xs:decimal(.) >= 0) or (@id = 'AlignmentLargerThanSize' and . castable as xs:decimal and xs:decimal(.) > 0) or (@id = 'Machine' and . castable as xs:string and (. = 'PI-8200' or . = 'PI-8300')) or (@id = 'PackagePCBNames' and . castable as xs:string and string-length(.) > 0) or (@id = 'AlignmentPoint1Y' and . castable as xs:decimal and xs:decimal(.) >= -100 and xs:decimal(.) <= 100) or (@id = 'PolarityComboBox' and . castable as xs:string and (. = 'Positive' or . = 'Negative')) or (@id = 'ManualExactOutlineStroke' and . castable as xs:decimal and xs:decimal(.) >=1 and xs:decimal(.) <=20) "/> </xs:complexType> </xs:element> </xs:schema>
注意事项
- 两种方式都需要支持XSD 1.1的解析器(比如Saxon 9.5+、Xerces 2.12+),XSD 1.0解析器无法识别这些特性。
- 条件类型赋值方式更清晰,类型可复用;断言方式更紧凑,适合简单约束场景。
内容的提问来源于stack exchange,提问作者witny
相关产品推荐
相关产品推荐

