XSD:允许来自不同命名空间的元素在序列中的任何位置
Posted
技术标签:
【中文标题】XSD:允许来自不同命名空间的元素在序列中的任何位置【英文标题】:XSD: Allow elements from different namespace anywhere in a sequence 【发布时间】:2014-08-07 08:58:34 【问题描述】:我一直在尝试以下方法。 我想为 XML 创建一个 XSD,其中某些元素只允许出现一次并且需要有效,并且来自其他命名空间的元素可以在任何地方使用,并且没有必须验证的模式。
应该允许的XML:
<ns:bookstore>
<ns:books>
<ns:book1 />
<other:magazine1 />
<ns:book2 />
<ns:book3 />
<otherns:newspaper1 />
<ns:book4 />
</ns:books>
</ns:bookstore>
book1,2,3 和 4 在 XML 中只能出现一次并且需要验证,其他命名空间中的元素然后 ns: 应该被允许而不经过验证。为此,我在 XSD 中使用了带有 processContents lax 的 xs:any:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ns">
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence >
<xs:element name ="book1" type="xs:string" maxOccurs="1"/>
<xs:element name ="book2" type="xs:string" maxOccurs="1"/>
<xs:element name ="book3" type="xs:string" maxOccurs="1"/>
<xs:element name ="book4" type="xs:string" maxOccurs="1"/>
<xs:any processContents="lax" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
在这个解决方案中,其他命名空间中的元素只能出现在序列之后,而不能出现在强制元素之间。理想的解决方案(但我知道它在 XSD 中是不允许的)是在 xs:all 中更改我的 xs:sequence(但 xs:all 中不允许 xs:any)
我知道有这样的问题,但没有一个答案对我来说很清楚。 有人可以为我提供解决此问题的方法吗?
我还尝试了以下方法:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ns">
<xs:element name="bookstore">
<xs:complexType>
<xs:choice maxOccurs="unbounded" >
<xs:element name ="book1" type="xs:string" maxOccurs="1"/>
<xs:element name ="book2" type="xs:string" maxOccurs="1"/>
<xs:element name ="book3" type="xs:string" maxOccurs="1"/>
<xs:element name ="book4" type="xs:string" maxOccurs="1"/>
<xs:any processContents="lax" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:complexType>
</xs:element>
因为选择的出现次数是无限的,所以选择中的任何元素都可以在任何位置出现任意多次。但是这里 book1、2、3 和 4 可以出现多次,在我的用例中是不允许的。
有人有其他想法可以帮助我吗?提前致谢!!
P.S.:我的书的类型其实是complexTypes,而且都互不相同,这只是XML的简化版。
编辑:
这在我的 XSD 中也是不允许的:
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence >
<xs:element name ="book1" type="xs:string" maxOccurs="1"/>
<xs:any processContents="lax" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name ="book2" type="xs:string" maxOccurs="1"/>
<xs:any processContents="lax" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name ="book3" type="xs:string" maxOccurs="1"/>
<xs:element name ="book4" type="xs:string" maxOccurs="1"/>
<xs:any processContents="lax" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
【问题讨论】:
【参考方案1】:在 XSD 1.1 中,您可以通过定义一个开放内容模型来非常轻松地做到这一点:
<xs:complexType ...>
<xs:openContent mode="interleave">
<xs:any namespace=.../>
</xs:openContent>
... regular content model ...
</xs:complexType>
在 1.0 中没有简单的方法;您只需在每个可能的位置放置一个可选通配符。
【讨论】:
"您只需在每个可能的位置放置一个可选通配符。"你能举个例子吗?一个序列中是否允许有更多 xs:any? 我的意思是sequence (x *? y *? z *?)
where *?是 xs:any 通配符,minOccurs=0,x、y、z 是元素声明。
这不违反唯一粒子属性吗?我记得试过这个。
在 XSD 1.0 中,您必须确保通配符不允许用于命名元素的命名空间,因此没有歧义。
您提供的架构对我来说似乎有效。我已经用 Saxon、Xerces 和 libxml 检查了它。我还检查了它是否允许在指定位置使用其他命名空间元素。您使用的是什么模式处理器,您遇到了什么错误?另外,xs:schema 元素中 targetNamespace 和 elementFormDefault 的值是多少?以上是关于XSD:允许来自不同命名空间的元素在序列中的任何位置的主要内容,如果未能解决你的问题,请参考以下文章
XML XSD 错误:org.xml.sax.SAXParseException:s4s-elt-schema-ns:元素“配置”的命名空间必须来自模式命名空间