如何基于属性值通过XSD约束XML元素的内容类型
根据field元素name属性校验内容类型的XSD实现
需求
需编写XSD校验目标XML有效性,并根据field元素的name属性值约束内容类型:
name1:字符串类型(xs:string)name2:布尔类型(xs:boolean)name3:日期时间类型(原XML值为2023-10-09T093500Z,符合xs:dateTime格式)
原XSD错误原因
原XSD将<xs:alternative>放在了<xs:element>的complexType节点之后,违反了XSD 1.1的结构规则——Type Alternative必须定义在<xs:simpleContent>或<xs:complexType>的内部指定位置,不能直接作为<xs:element>的子元素。
正确XSD代码
<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="doc"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="field"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="name" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="name1"/> <xs:enumeration value="name2"/> <xs:enumeration value="name3"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="copyTo" type="xs:string" use="optional"/> </xs:extension> <!-- 根据name属性切换内容类型 --> <xs:alternative test="@name='name1'" type="xs:string"/> <xs:alternative test="@name='name2'" type="xs:boolean"/> <xs:alternative test="@name='name3'" type="xs:dateTime"/> <!-- 默认类型,匹配未指定的name值 --> <xs:alternative type="xs:string"/> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:schema>
关键说明
- 必须添加
version="1.1"声明,启用XSD 1.1的Type Alternative特性 - 将
<xs:alternative>放在<xs:simpleContent>内部,作为extension的同级节点,符合结构规则 - 针对
name3的内容,原XML值为带时间的格式,因此使用xs:dateTime而非xs:date,避免校验失败;若需求严格要求日期类型,需将XML中name3的值改为2023-10-09
验证效果
- 当
name2的值为true/false时,校验通过;若为whatever这类非布尔值,会抛出类型不匹配错误 name3的值符合yyyy-MM-ddTHHmmssZ格式则通过,否则报错name1接受任意字符串内容
内容的提问来源于stack exchange,提问作者Miguel Díaz Pestana
相关产品推荐
相关产品推荐

