需要澄清关于 xml 模式“all”标签(这是一个 libxml2 错误吗?)

zzz*_*eek 3 xml xsd

从 libxml2 2.6 升级到 2.7 时,我的某些行为发生了变化。我在他们的网站上找到了关于此更改的错误报告,其https://bugzilla.gnome.org/show_bug.cgi?id=571271

有趣的是,他们报告说“我猜我们误解了这个选项的预期行为(尽管我仍然不是 100% 确定)”——他们不确定他们是否正确阅读了规范,但他们提交了修复程序。

我认为以前的行为是正确的,所以我想看看这里是否有人对这两个方向有了解。

基本上,是否<xs:all>elem1, elem2, ..<xs:all>意味着“必须存在 elem1、elem2 .. 中的所有或不存在”,或“可能存在 elem1、elem2 中的任何一个 ..”?尽管看起来像前者,但有两个消息来源并没有说明这一点:

http://www.w3.org/TR/xmlschema-0/#re​​f18 - “组中的所有元素可能出现一次,也可能根本不出现,它们可能以任何顺序出现。”

http://www.w3schools.com/Schema/el_all.asp - “上面的例子表明“名字”和“姓氏”元素可以以任何顺序出现,每个元素可以出现零次或一次!”

下面的脚本使用 lxml,在使用 libxml2 2.6 时报告成功,但第二个模式验证在 2.7 上失败。有人可以确认 2.7 在这里做的是对还是错?

from lxml import etree
from StringIO import StringIO

schema = """
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element type="parent-type" name="parent"/>
 <xs:complexType name="parent-type">
   <xs:all maxOccurs="1" minOccurs="0">
     <xs:element type="xs:int" name="int-attr"/>
     <xs:element type="xs:string" name="str-attr"/>
   </xs:all>
 </xs:complexType>
</xs:schema>
"""

xmlschema = etree.XMLSchema(etree.parse(StringIO(schema)))

# passes
doc1 = """
<parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.example.com/xml/schemas">
 <str-attr>some value</str-attr>
 <int-attr>12</int-attr>
</parent>
"""

# fails.  it wants both "int-attr" and "str-attr" to be present.
# didn't think this was how "xs:all" worked ?
doc2 = """
<parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.example.com/xml/schemas">
 <int-attr>12</int-attr>
</parent>
"""

for i, doc in enumerate((doc1, doc2, )):
   doc = etree.parse(StringIO(doc))
   try:
       xmlschema.assertValid(doc)
       print "document %d is valid." % i
   except Exception, e:
       print "document %d is not valid." % i
       print e
Run Code Online (Sandbox Code Playgroud)

输出:

document 0 is valid.
document 1 is not valid.
Element 'parent': Missing child element(s). Expected is ( str-attr )., line 2
Run Code Online (Sandbox Code Playgroud)

jas*_*sso 5

用户 Jörn Horstmann 实际上已经正确回答了您的问题,但格式可能会使答案看起来有点不清楚。我希望这些例子能帮助那些感到困惑的人。

元素的作用minOccursmaxOccurs意义<xs:all>

请记住这一点,<xs:all><xs:element>minOccurs和设置默认值“1” maxOccurs。所以

<xs:all>
  <xs:element type="xs:int" name="int-attr"/>
  <xs:element type="xs:string" name="str-attr"/>
</xs:all>
Run Code Online (Sandbox Code Playgroud)

实际上是一样的

<xs:all minOccurs="1" maxOccurs="1">
  <xs:element type="xs:int" name="int-attr" minOccurs="1" maxOccurs="1"/>
  <xs:element type="xs:string" name="str-attr" minOccurs="1" maxOccurs="1"/>
</xs:all>
Run Code Online (Sandbox Code Playgroud)

这意味着整个<xs:all>组以及其中定义的两个元素都是强制性的 - 订单是自由的。因此 XML 文档

<parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://www.example.com/xml/schemas">
  <int-attr>12</int-attr>
</parent>
Run Code Online (Sandbox Code Playgroud)

将无效。使用属性minOccurs="0"on<xs:all>意味着整个组是可选的,在这种情况下它也允许一个空<parent/>元素。我看到这就是规范的真正含义“组中的所有元素可能出现一次或根本不出现”。我的母语不是英语,但我也想说 w3schools 页面上的第二个例子是不正确的。它应该读作“两个元素都可以出现零次或一次”而不是“每个元素都可以出现零次或一次”。

maxOccurs的属性<xs:all>固定为值“1”

如何定义每个子标签具有零个或一个的标签

所以这就是您在评论中提出的问题以及您首先尝试验证的内容。<xs:all>组内的可选元素是通过minOccurs="0"在这些元素上添加属性来实现的。下面的例子

<xs:all minOccurs="1" maxOccurs="1">
  <xs:element type="xs:int" name="int-attr" minOccurs="0" maxOccurs="1"/>
  <xs:element type="xs:string" name="str-attr" minOccurs="0" maxOccurs="1"/>
</xs:all>
Run Code Online (Sandbox Code Playgroud)

此模式将验证 XML 文档

<parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://www.example.com/xml/schemas">
  <int-attr>12</int-attr>
</parent>
Run Code Online (Sandbox Code Playgroud)

由于这两个元素都是可选的(因为它们有minOccurs="0"),这个定义也允许一个空<parent/>元素。尽管对元素的基数限制以某种方式“覆盖”了<xs:all>规范中设置的基数限制也说:“内容模型中的元素不能出现多次,即 minOccurs 和 maxOccurs 的允许值是 0 和 1”。所以你不能有一个以随机顺序多次具有相同元素的组,或者至少你不能<xs:all>用来创建这样的类型。