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:允许来自不同命名空间的元素在序列中的任何位置的主要内容,如果未能解决你的问题,请参考以下文章

使用不同版本名称空间序列化/反序列化 XSD 的方法?

使用 xslt 引用具有不同命名空间的元素

XML XSD 错误:org.xml.sax.SAXParseException:s4s-elt-schema-ns:元素“配置”的命名空间必须来自模式命名空间

在 .NET 中序列化对象时忽略所有 xsi 和 xsd 命名空间?

xsd2code 元素命名空间前缀问题

在不修改 C# XSD 类的情况下向 XML 序列化添加前缀和命名空间