xml - XSD 全局定义多个元素时需要某个 XML 根元素?
问题描述
我为一个项目制作了一个 XSD,这个 XSD 应该能够捕获与 XML 代码中缺少结构相关的错误,但事实并非如此。例如,当我尝试验证不正确的 XML 时,例如:
<Course number="1">
<Subject idSub="s8" type="core">
<Name>PII</Name>
<Student>
<Name>John White</Name>
<ID>12345601A</ID>
<Grade>9.27</Grade>
</Student>
</Subject>
</Course>
如果缺少父元素Degree
及其子元素Name
,Scope
验证器会通知我 XML 在它应该是错误的时候是有效的。
我已经尝试创建一个父类:
<xsd:element name="Degrees">
<xs:complexType>
<xs:sequence>
<xs:element ref="Degree" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xsd:element>
但似乎什么也没做。
这是一个有效 XML 的示例:
<Degree location="London">
<Name>Industrial Engineering</Name>
<Scope>technology</Scope>
<Course number="1">
<Subject idSub="ts1" type="core">
<Name>Thermodynamics</Name>
<Student>
<Name>Michael Williams</Name>
<ID>89345601A</ID>
<Grade>7.37</Grade>
</Student>
</Subject>
</Course>
</Degree>
这是我的完整 XSD 代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Degree">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element ref="Scope"/>
<xsd:element ref="Course" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="location" use="optional">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="London"/>
<xsd:enumeration value="Oxford"/>
<xsd:enumeration value="Cambridge"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="Scope">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="humanities"/>
<xsd:enumeration value="science"/>
<xsd:enumeration value="technology"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="Course">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Subject" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="number" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:pattern value="[1-4]{1}" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
<xsd:unique name="IDSubUnique">
<xsd:selector xpath="./Subject" />
<xsd:field xpath="@idSub" />
</xsd:unique>
</xsd:element>
<xsd:element name="Subject">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element ref="Student" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="type" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="core" />
<xsd:enumeration value="specialty" />
<xsd:enumeration value="optional" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="idSub" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="Student">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:choice>
<xsd:element ref="ID" minOccurs="0"/>
<xsd:element ref="Resident" minOccurs="0"/>
</xsd:choice>
<xsd:element ref="Grade"/>
<xsd:element ref="EAML" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="StudentAddress" use="optional">
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="ID">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0-9]{8}[A-Z]{1}"></xsd:pattern>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="Resident">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="[A-Z]{1}[0-9]{7}"></xsd:pattern>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="Grade">
<xsd:simpleType>
<xsd:restriction base="xsd:decimal">
<xsd:fractionDigits value="2"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="EAML" type="xsd:anyURI"/>
</xsd:schema>
解决方案
当一个元素Course
在 XSD 中全局定义时(就像在您采用的Salami Slice 设计中所做的那样),它可能会作为 XML 文档的根元素出现。禁止这种情况的方法包括重新设计 XSD 或使用依赖于实现的验证选项:
嵌套非本地元素声明(Russian Doll Design):
代替
<xsd:element name="Degree"> <xsd:complexType> <xsd:sequence> <xsd:element ref="Course" minOccurs="1" maxOccurs="unbounded"/> ...
和
<xsd:element name="Degree"> <xsd:complexType> <xsd:sequence> <xsd:element name="Course"> <xsd:complexType> <xsd:sequence> <xsd:element ref="Subject" maxOccurs="unbounded"/> ...
请注意, 的声明
Course
已从具有全局范围迁移到具有局部范围。嵌套非本地元素声明,但全局声明类型(威尼斯盲设计)。
依赖于实现相关的验证选项,例如 Saxon 的模式验证器
-top:Degree
参数给出的验证选项。
也可以看看
- 对于意大利腊肠切片vs俄罗斯娃娃vs威尼斯盲人设计:全球与本地:一组共同开发的模式设计指南
- XSD 要求 XML 文档中存在特定的根元素?
推荐阅读
- cordova - Ionic 无法构建或运行应用程序
- ignite - 点燃内存消耗 vs Redis
- bash - 如何在 shell 脚本中获取动态路径?
- c# - 使用 ajax 调用的 setInterval 不会触发成功回调,直到另一个表单完成提交
- javascript - 分组 div 元素
- java - 只能使用 JDBC Sql Server 连接到主数据库
- office-js - 如何使用office.js在excel中删除工作表中的工作表行
- entity-framework - 从 DTO 批量更新实体
- alibaba-cloud - 使用 OSS Utility 工具在阿里云 OSS 的特定区域创建存储桶?
- javascript - 如何为带有“document.write”的javascript函数编写单元测试用例