我正在尝试用PyXB解析自定义XML文件格式。因此,我首先编写了以下XML模式:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="outertag" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="innertag0"
minOccurs="0"
maxOccurs="unbounded"/>
<xs:element name="innertag1"
minOccurs="0"
maxOccurs="unbounded"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
我使用以下pyxbgen命令生成Python模块的源py_schema_module.py:
pyxbgen -m py_schema_module -u schema.xsd
然后,我编写了以下脚本来解析我称之为example.XML:的XML文件
#!/usr/bin/env python2.7
import py_schema_module
if __name__ == "__main__":
with open("example.xml", "r") as f:
py_schema_module.CreateFromDocument(f.read())
我使用该脚本来确定example.xml语法的合法性。例如,以下example.xml文件根据模式具有合法语法:
<outertag>
<innertag0></innertag0>
<innertag1></innertag1>
</outertag>
这也是:
<outertag>
<innertag1></innertag1>
<innertag0></innertag0>
</outertag>
但是,以下语法是非法的:
<outertag>
<innertag1></innertag1>
<innertag0></innertag0>
<innertag1></innertag1>
</outertag>
这就是:
<outertag>
<innertag0></innertag0>
<innertag1></innertag1>
<innertag0></innertag0>
</outertag>
我能够写innetag0,然后再写innetag1。我还可以写innetag1,然后再写innetag0。我也可以任意重复innetag0和innetag1的实例(为了简洁起见,未显示实例(。但是,我不能在innertag0和innertag1之间切换。
假设我希望格式支持此功能。我应该如何更改我的XML模式文件?
无论innertag(0|1(元素的顺序如何,以下XML架构(XSD(1.0都应该涵盖您的用例。minOccurs
和maxOccurs
的默认值均为1。
有用的链接:XML模式,为什么xs:group不能是xs:all的子级?
XML
<outertag>
<innertag1></innertag1>
<innertag0></innertag0>
</outertag>
XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="outertag">
<xs:complexType>
<xs:all>
<xs:element name="innertag0" type="xs:string"/>
<xs:element name="innertag1" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
您的模式处理器似乎没有根据规范进行非常仔细的检查。
如果我尝试使用Saxon将您的模式处理为XSD1.0模式,它会告诉我有四个错误:
Error at xs:element on line 3 column 59 of test.xsd:
Attribute @minOccurs is not allowed on element <xs:element>
Error at xs:element on line 3 column 59 of test.xsd:
Attribute @maxOccurs is not allowed on element <xs:element>
Error at xs:all on line 5 column 15 of test.xsd:
Within <xs:all>, an <xs:element> must have @maxOccurs equal to 0 or 1
Error at xs:all on line 5 column 15 of test.xsd:
Within <xs:all>, an <xs:element> must have @maxOccurs equal to 0 or 1
Schema processing failed: 4 errors were found while processing the schema
前两个表示在全局元素声明中不允许使用minOccurs
和maxOccurs
。
第二个是说xs:all
中的maxOccurs
必须是1——当内容模型是xs:all
时,XSD 1.0不允许元素重复。您的处理器告诉您这是XML实例中的错误,但实际上这是您的模式中的错误。
XSD 1.1允许在xs:all
中多次出现。如果我通过删除@minOccurs
和@maxOccurs
来更正全局元素声明,那么该模式现在在XSD 1.1下是有效的,并且允许您遇到问题的交错实例示例。