When the objectify element is printed on the console, the leading zero is lost, but it is preserved in the .text
:
>>> from lxml import objectify
>>>
>>> xml = "<a><b>01</b></a>"
>>> a = objectify.fromstring(xml)
>>> print(a.b)
1
>>> print(a.b.text)
01
From what I understand, objectify
automatically makes the b
element an IntElement
class instance. But, it also does that even if I try to explicitly set the type with an XSD schema:
from io import StringIO
from lxml import etree, objectify
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>
''')
schema = etree.XMLSchema(file=f)
parser = objectify.makeparser(schema=schema)
xml = "<a><b>01</b></a>"
a = objectify.fromstring(xml, parser)
print(a.b)
print(type(a.b))
print(a.b.text)
Prints:
1
<class 'lxml.objectify.IntElement'>
01
How can I force objectify
to recognize this b
element as a string element?
Based on the documentation and the behavior observed, it seems that XSD Schema
is only used for validation, but isn't involved in the process of determining property data type whatsoever.
For example, when an element is declared to be of type integer
in the XSD, but then the actual element in the XML has value of x01
, element invalid exception is correctly raised :
f = StringIO(u'''
<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:integer" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
''')
schema = etree.XMLSchema(file=f)
parser = objectify.makeparser(schema=schema)
xml = '''<a><b>x01</b></a>'''
a = objectify.fromstring(xml, parser)
# the following exception raised:
# lxml.etree.XMLSyntaxError: Element 'b': 'x01' is not a valid value of....
# ...the atomic type 'xs:integer'.
Despite objectify
documentation on how data types are matched mentioned about XML Schema xsi:type (no. 4 in the linked section), the example code there suggests that it means by adding xsi:type
attribute directly in the actual XML element, not via a separate XSD file, for example :
xml = '''
<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<b xsi:type="string">01</b>
</a>
'''
a = objectify.fromstring(xml)
print(a.b) # 01
print(type(a.b)) # <type 'lxml.objectify.StringElement'>
print(a.b.text) # 01