我正在学习如何使用XML架构文档来生成符合所述架构的XML文件。
我已经了解了PyXB来为XML模式定义的数据结构生成Python绑定。
This SO post给出了一个“端到端”示例,说明如何生成符合给定XML模式的XML文件。为了提供信息,the post帮助在以下两个链接中摘要信息:
这两个链接都很好地解释了如何使用绑定来生成所需的XML文件。
这是使用的XSD文件:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
<xsd:element name="comment" type="xsd:string"/>
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>
<xsd:complexType name="Items">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="USPrice" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="partNum" type="SKU" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
这是我用来生成Python绑定的命令:
pyxbgen -u po1.xsd -m po1
此命令生成一个po1.py
文件,该文件随后可用于生成XML文档,如下所示(demo2.py
的内容):
from __future__ import print_function
import po1 as address
addr = address.USAddress()
addr.name = 'Robert Smith'
addr.street = '8 Oak Avenue'
addr.city = 'Anytown'
addr.state = 'AK'
addr.zip = 12341
with open('demo2.xml', 'w') as f:
f.write(addr.toxml("utf-8", element_name='USAddress').decode('utf-8'))
执行此代码将产生以下格式良好的XML文件(demo2.xml
):
<?xml version="1.0" encoding="utf-8"?>
<USAddress>
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Anytown</city>
<state>AK</state>
<zip>12341.0</zip>
</USAddress>
实际问题:
demo2.xml
)无法针对
XML模式?具体来说,我收到以下错误:Not valid.
Error - Line 1, 50: org.xml.sax.SAXParseException; lineNumber: 1;
columnNumber: 50; cvc-elt.1.a: Cannot find the declaration of
element 'USAddress'.
demo2.py
生成确实通过验证的XML文件
模式?答案 0 :(得分:0)
经过更多阅读后,我意识到使用Python绑定不能保证所生成的XML文档符合该模式。
答案2和3的一部分:
在这种情况下,验证失败,因为Python代码实际上是针对给定的架构构造了一个无效的XML文档。考虑一对简单得多的XSD-XML文件:
简单的XSD:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="a" type="AType"/>
<xsd:complexType name="AType">
<xsd:sequence>
<xsd:element name="b" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
使用为架构生成的绑定的简单Python代码:
from __future__ import print_function
import po2
hey = po2.AType()
hey.b = "Eduardo"
with open('demo4.xml', 'w') as f:
f.write(hey.toxml("utf-8", element_name='a').decode('utf-8'))
执行Python代码时,会生成以下XML:
<?xml version="1.0" encoding="utf-8"?>
<a><b>Eduardo</b></a>
在原始情况下(USAddress
),原始架构为DOM提供了一个根类型,而不是USAddress
类型。但是,Python代码忽略了这一点,直接使用这种类型的实例来生成XML文件。生成的XML确实格式正确,但是不符合架构。在这里描述的简单得多的情况下,不仅XML有效,而且使用Python绑定还可以生成符合XSD模式的XML文件。
答案1:
您可以使用提供的here说明,针对给定的XSD模式自动验证生成的文件。
from lxml import etree
from StringIO import StringIO
# Check https://lxml.de/validation.html
f = StringIO('''\
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="a" type="AType"/>
<xsd:complexType name="AType">
<xsd:sequence>
<xsd:element name="b" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
''')
xmlschema_doc = etree.parse(f)
xmlschema = etree.XMLSchema(xmlschema_doc)
valid = StringIO('''\
<?xml version="1.0" encoding="utf-8"?>
<a><b>Eduardo</b></a>
''')
doc = etree.parse(valid)
print('Is XML is valid?', xmlschema.validate(doc))