I am learning how to use an XML Schema document to generate an XML file which complies with said schema.
I have learned about PyXB to generate Python bindings for data structures defined by an XML Schema.
This SO post presents an "end-to-end" example of how to go about generating an XML file which complies with a given XML Schema. In order to provide information, the post helps digest information in these two links:
- http://pyxb.sourceforge.net/userref_pyxbgen.html#pyxbgen
- http://pyxb.sourceforge.net/userref_usebind.html
Both of these links present a decent explanation of how to use the bindings to generate the required XML file.
Here's the XSD file used:
<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>
Here's the command I use to generate the Python bindings:
pyxbgen -u po1.xsd -m po1
This command generates a po1.py
file which can then be used to generate an XML document as follows (content of 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'))
Executing this code yields the following well-formed XML file (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>
Actual questions:
- How can I automate the validation of the generated XML file against the used XSD Schema?
- Why (using this validator) does the
generated XML file (
demo2.xml
) fail to be validated against the XML Schema? Specifically, I get the following error: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'.
- What modifications should I consider adding to
demo2.py
to produce XML files that do pass the validation against the Schema?