Caf*_*eek 32 xml xsd xml-validation
也许是我,但似乎你有一个XSD
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element name="GivenName" />
<xs:element name="SurName" />
</xs:sequence>
<xs:attribute name="ID" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)
它定义了此文档的架构
<?xml version="1.0" encoding="utf-8" ?>
<User ID="1">
<GivenName></GivenName>
<SurName></SurName>
</User>
Run Code Online (Sandbox Code Playgroud)
它将无法验证您是否添加了另一个元素,例如EmailAddress,并混淆了订单
<?xml version="1.0" encoding="utf-8" ?>
<User ID="1">
<SurName></SurName>
<EmailAddress></EmailAddress>
<GivenName></GivenName>
</User>
Run Code Online (Sandbox Code Playgroud)
我不想将EmailAddress添加到文档中并将其标记为可选.
我只想要一个XSD来验证文档必须满足的最低要求.
有没有办法做到这一点?
marc_s在下面指出你可以使用xs:any内部xs:sequence允许更多元素,遗憾的是,你必须维护元素的顺序.
或者,我可以使用xs:all哪个不强制执行元素的顺序,但是,唉,不允许我放在xs:any它内部.
Abe*_*bel 55
你的问题有一个解决方案,但它不会很漂亮.原因如下:
你已经触及了W3C XML Schema的灵魂.您所要求的 - 变量顺序和变量未知元素 - 违反了XSD最难但最基本的原则,非歧义规则,或者更正式地说,唯一粒子归因约束:
必须形成内容模型,使得在验证期间[...]可以唯一地确定序列中的每个项目而不检查该项目的内容或属性,并且没有关于序列的其余部分中的项目的任何信息.
在普通英语中:当验证XML并且XSD处理器遇到<SurName>它时,它必须能够验证它,而无需先检查它是否后跟<GivenName>,即没有向前看.在您的方案中,这是不可能的.存在此规则以允许通过有限状态机实现,这应该使实现相当简单和快速.
这是争论最多的问题之一,是SGML和DTD(内容模型必须是确定性的)和XML 的遗产,默认情况下,它定义元素的顺序很重要(因此,尝试相反,制定顺序)不重要,很难).
正如Marc_s已经建议的那样,Relax_NG是一种允许非确定性内容模型的替代方案.但是如果你坚持使用W3C XML Schema,你会怎么做?
你已经注意到这xs:all是非常严格的.原因很简单:同样的非确定性规则适用,这就是为什么xs:any,min/maxOccurs大于一,不允许序列.
此外,您可能尝试过各种各样的组合choice,sequence和any.遇到这种无效情况时Microsoft XSD处理器抛出的错误是:
错误:元素" http://example.com/Chad:SurName "的多个定义会导致内容模型变得模糊不清.必须形成内容模型,使得在元素信息项序列的验证期间,可以在不检查元素信息项序列的内容或属性的情况下,直接地,间接地或隐含地包含在其中依次用于尝试验证序列中的每个项目的粒子.该项目,并且没有关于序列其余部分中的项目的任何信息.
在O'Reilly的XML Schema中(是的,这本书有它的缺陷),这是非常好的解释.幸运的是,本书的部分内容可在线获取.我强烈建议您阅读第7.4.1.3节关于独特粒子归因规则的内容,他们的解释和示例比我能得到的更清晰.
在大多数情况下,可以从不确定的设计转变为确定性设计.这通常看起来不太漂亮,但如果您必须坚持使用W3C XML Schema和/或绝对必须允许对XML使用非严格规则,那么它就是一个解决方案.你的情况的噩梦就是你要强制执行一件事(2个预定义的元素),同时又想让它变得非常松散(顺序无关紧要,任何事情都可以介于之前和之后).如果我不试图给你很好的建议,但只是直接带你到解决方案,它将如下所示:
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="0" processContents="lax" namespace="##other" />
<xs:choice>
<xs:sequence>
<xs:element name="GivenName" />
<xs:any minOccurs="0" processContents="lax" namespace="##other" />
<xs:element name="SurName" />
</xs:sequence>
<xs:sequence>
<xs:element name="SurName" />
<xs:any minOccurs="0" processContents="lax" namespace="##other" />
<xs:element name="GivenName" />
</xs:sequence>
</xs:choice>
<xs:any minOccurs="0" processContents="lax" namespace="##any" />
</xs:sequence>
<xs:attribute name="ID" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
Run Code Online (Sandbox Code Playgroud)
上面的代码实际上是有效的.但有几点需要注意.首先是xs:any与##other它的命名空间.你不能使用##any,除了最后一个,因为这将允许GivenName使用相似的元素,这意味着定义User变得模糊不清.
第二个警告是,如果你想使用超过两个或三个这个技巧,你将不得不写下所有组合.维护噩梦.这就是为什么我想出以下内容:
改变你的定义.这样做的好处是让读者或用户更清楚.它还具有易于维护的优点.这里有一整套解决方案在XFront上进行了解释,你可能已经从Oleg的帖子中看到了一个不那么易读的链接.这是一个很好的阅读,但大多数都没有考虑到你在变量内容容器中至少需要两个元素.
针对您的情况的当前最佳实践方法(比您可能想象的更频繁地发生)是在必需和非必需字段之间拆分数据.您可以添加元素<Required>,或者相反,添加元素<ExtendedInfo>(或将其称为Properties或OptionalData).这看起来如下:
<xs:element name="User2">
<xs:complexType>
<xs:sequence>
<xs:element name="GivenName" />
<xs:element name="SurName" />
<xs:element name="ExtendedInfo" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##any" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Run Code Online (Sandbox Code Playgroud)
目前这似乎不太理想,但让它增长一点.拥有一组有序的固定元素并不是什么大问题.你不是唯一会抱怨W3C XML Schema明显不足的人,但正如我之前所说,如果你必须使用它,你将不得不忍受它的局限性,或接受开发的负担围绕这些限制,以更高的拥有成本.
我确定你已经知道了,但默认情况下属性的顺序是不确定的.如果您的所有内容都是简单类型,您也可以选择更充分地使用属性.
无论采用何种方法,您都将失去对数据的大量可验证性.允许内容提供商添加内容类型通常更好,但仅限于可以验证的内容类型.这可以通过从切换lax到strict处理以及使类型本身更严格来完成.但是过于严格也不好,正确的平衡将取决于你判断你所反对的用例的能力,并权衡某些实施策略的权衡.
在阅读了marc_s的答案和你在评论中的讨论之后,我决定添加一点.
在我看来,你的问题乍得没有完美的解决方案.如何在XSD中实现可扩展内容模型有一些方法,但我所知的所有实现都有一些限制.因为您没有写过计划使用可扩展XSD的环境,所以我只能推荐一些链接,这些链接可能会帮助您选择在您的环境中实现的方式:
| 归档时间: |
|
| 查看次数: |
10374 次 |
| 最近记录: |