提问人:Miguel Díaz Pestana 提问时间:11/8/2023 更新时间:11/10/2023 访问量:41
如何使用 XSD 基于属性值约束 XML 元素内容类型
How to constrain XML element content type based on an attribute value using XSD
问:
我有以下xml文件:
<doc id="JOURNAL/otai/04.03/product/root">
<field name="name1">8043501d8766ee1199370022482955e0</field>
<field name="name2">false</field>
<field name="name3">2023-10-09T093500Z</field>
</doc>
我需要创建一个 XSD 文件,用于检查 xml 文件的有效性,以及根据 name 属性的值检查每个字段元素的内容类型。
例如:
- 8043501d8766ee1199370022482955e0 的内容类型为 string。
- false 的内容为 boolean 类型。
- 2023-10-09T093500Z 的内容类型为 date。
如果字段节点内容类型与这些类型不匹配,则 XSD 应引发错误,例如,任何应引发错误,因为“whatever”不能强制转换为布尔值,依此类推。
在验证输入 xml 时,XSD 应该如何执行这些检查?
谢谢!
我尝试了很多方法,但没有一个奏效。我正在玩 Type Alternative Schema Component,但我无法让它工作。
这是我尝试过的:
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Technologies Online Tools 1.0 (https://www.liquid-technologies.com) -->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<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>
</xs:simpleContent>
</xs:complexType>
<xs:alternative test="@name='name2'">
<xs:element name="field" type="xs:boolean"/>
</xs:alternative>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
如果我尝试验证 xml,则会出现以下错误:
s4s-elt-must-match.1:'field' 的内容必须匹配 (annotation?, (simpleType | complexType)?, (unique | key | keyref)*))。从以下位置开始发现一个问题:替代。
我希望 XSD 根据 name 属性的值验证 field 元素的内容。
例如,将 name2 作为 name 属性值的字段元素只有在字段元素内容可以解析为布尔值时才有效。
答:
1赞
Yitzhak Khabinsky
11/9/2023
#1
请尝试以下使用条件类型分配 (CTA) 的 XSD 1.1。
XML格式
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="doc">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="field"/>
</xs:sequence>
<xs:attribute name="id" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="field" type="xs:anySimpleType">
<xs:alternative test="@name eq 'name1'" type="StringType"/>
<xs:alternative test="@name eq 'name2'" type="BooleanType"/>
<xs:alternative test="@name eq 'name3'" type="DateTimeType"/>
<xs:alternative type="xs:error"/>
</xs:element>
<xs:complexType name="StringType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attributeGroup ref="GrpAttributes"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="BooleanType">
<xs:simpleContent>
<xs:extension base="xs:boolean">
<xs:attributeGroup ref="GrpAttributes"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DateTimeType">
<xs:simpleContent>
<xs:extension base="xs:dateTime">
<xs:attributeGroup ref="GrpAttributes"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:attributeGroup name="GrpAttributes">
<xs:attribute name="name" type="NameAttrType" use="required"/>
<xs:attribute name="copyTo" type="xs:string"/>
</xs:attributeGroup>
<xs:simpleType name="NameAttrType">
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="100"/>
<xs:enumeration value="name1"/>
<xs:enumeration value="name2"/>
<xs:enumeration value="name3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
评论
0赞
Miguel Díaz Pestana
11/10/2023
它有效。非常感谢。只有一个问题...学习 XSD 1.1 和此类验证的最佳在线资源是什么?再次感谢你!
0赞
Miguel Díaz Pestana
11/10/2023
你好。我忘了再提一件事:“field”元素可以有一个名为“copyTo”的可选属性,类型为“xs:string”。XSD 将如何更改以适应这种情况?谢谢!
0赞
Yitzhak Khabinsky
11/10/2023
我更新了答案并使用了.一探究竟。attributeGroup
1赞
Michael Kay
11/9/2023
#2
在我看来,从错误消息来看,好像您使用的是 XSD 1.0 处理器而不是 XSD 1.1 处理器。
当你解决这个问题时,你将需要改变你的元素。它应该是这样的xs:alternative
<xs:alternative test="@name='name2'">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:boolean">
此外,字段元素的主要(控制)类型需要包含所有可能性(也许),并且所有特定情况都需要是一般情况的子类型。xs:anyType
评论
0赞
Miguel Díaz Pestana
11/10/2023
好的,我会尝试的。非常感谢!
评论