Skip to content

Commit

Permalink
Add a test with a resolution for issue #341
Browse files Browse the repository at this point in the history
  • Loading branch information
brunato committed Mar 28, 2023
1 parent 7a842ce commit c9548da
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 2 deletions.
46 changes: 46 additions & 0 deletions tests/test_cases/issues/issue_341/issue_341-ext.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="windows-1251"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="TEST">
<xs:complexType>
<xs:sequence>
<xs:element name="TEST_EL" maxOccurs="1000">
<xs:complexType>
<xs:sequence>
<xs:element name="TEST_EL_2">
<xs:complexType>
<xs:sequence>
<xs:element name="exists_in_xml" type="test_type"/>
<xs:element name="not_exists_in_xml" type="test_type" minOccurs="0"/>
<xs:choice>
<xs:element name="choice_elem1" minOccurs="0"/>
<xs:element name="choice_elem2" minOccurs="0"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Date" type="xs:date" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="test_type">
<xs:attribute name="test_attr">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="60"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="test_attr_2">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="60"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>
8 changes: 8 additions & 0 deletions tests/test_cases/issues/issue_341/issue_341.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<TEST>
<TEST_EL Date="2022-10-03">
<TEST_EL_2>
<exists_in_xml test_attr="test_value_attr" />
</TEST_EL_2>
</TEST_EL>
</TEST>
42 changes: 42 additions & 0 deletions tests/test_cases/issues/issue_341/issue_341.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="windows-1251"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="TEST">
<xs:complexType>
<xs:sequence>
<xs:element name="TEST_EL" maxOccurs="1000">
<xs:complexType>
<xs:sequence>
<xs:element name="TEST_EL_2">
<xs:complexType>
<xs:sequence>
<xs:element name="exists_in_xml" type="test_type"/>
<xs:element name="not_exists_in_xml" type="test_type" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Date" type="xs:date" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="test_type">
<xs:attribute name="test_attr">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="60"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="test_attr_2">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="60"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>
92 changes: 90 additions & 2 deletions tests/validation/test_decoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

from xmlschema.names import XSD_STRING, XSI_NIL
from xmlschema.converters import UnorderedConverter
from xmlschema.validators import XMLSchema11
from xmlschema.validators import XMLSchema11, ModelVisitor
from xmlschema.testing import XsdValidatorTestCase, etree_elements_assert_equal

VEHICLES_DICT = {
Expand Down Expand Up @@ -375,7 +375,9 @@ def test_to_dict_from_etree(self):
xml_dict = self.vh_schema.to_dict(vh_xml_tree, namespaces=self.vh_namespaces)
self.assertEqual(xml_dict, VEHICLES_DICT)

xml_dict = xmlschema.to_dict(vh_xml_tree, self.vh_schema.url, namespaces=self.vh_namespaces)
xml_dict = xmlschema.to_dict(
vh_xml_tree, self.vh_schema.url, namespaces=self.vh_namespaces
)
self.assertEqual(xml_dict, VEHICLES_DICT)

xml_dict = self.col_schema.to_dict(col_xml_tree)
Expand Down Expand Up @@ -1375,6 +1377,92 @@ def test_mixed_content_decode__issue_334(self):
body_text = result['Demonstrative_Examples']['Demonstrative_Example'][0]['Body_Text']
self.assertListEqual(body_text, expected)

def test_fill_missing_elements__issue_341(self):
xsd_file = self.casepath('issues/issue_341/issue_341.xsd')
xml_file = self.casepath('issues/issue_341/issue_341.xml')
schema = self.schema_class(xsd_file)

expected = {'TEST_EL': [
{'@Date': '2022-10-03',
'TEST_EL_2': {
'exists_in_xml': {
'@test_attr': 'test_value_attr', '@test_attr_2': None
}
}}
]}
xml_dict = schema.decode(xml_file, fill_missing=True)
self.assertDictEqual(xml_dict, expected)

def fill_missing_content(element_data: ElementData, _xsd_element, xsd_type):
group = xsd_type.model_group
if group is None:
return element_data # an element with simple content

filled_content = []
model = ModelVisitor(group)
xsd_element = None
for name, value, xsd_element in element_data.content:
if isinstance(name, int) or xsd_element is None:
filled_content.append((name, value, xsd_element))
continue

while model.element is not None:
if model.element is xsd_element:
filled_content.append((name, value, xsd_element))
for _err in model.advance(True):
pass
break

if model.element.max_occurs != 0:
filled_content.append((model.element.name, None, model.element))
for _err in model.advance(False):
pass
else:
filled_content.append((name, value, xsd_element))

while model.element is not None:
if model.element is not xsd_element and model.element.max_occurs != 0:
filled_content.append((model.element.name, None, model.element))
for _err in model.advance(False):
pass

return ElementData(
element_data.tag,
element_data.text,
filled_content,
element_data.attributes
)

expected = {'TEST_EL': [
{'@Date': '2022-10-03',
'TEST_EL_2': {
'exists_in_xml': {
'@test_attr': 'test_value_attr', '@test_attr_2': None
},
'not_exists_in_xml': None
}}
]}
xml_dict = schema.decode(xml_file, element_hook=fill_missing_content, fill_missing=True)
self.assertDictEqual(xml_dict, expected)

# Resolving more complex schemas requires more checks in hook function
xsd_file = self.casepath('issues/issue_341/issue_341-ext.xsd')
schema = self.schema_class(xsd_file)

expected = {'TEST_EL': [
{'@Date': '2022-10-03',
'TEST_EL_2': {
'exists_in_xml': {
'@test_attr': 'test_value_attr', '@test_attr_2': None
},
'not_exists_in_xml': None,
'choice_elem1': None,
'choice_elem2': None, # this is wrong (at most one element for a choice)
}}
]}
xml_dict = schema.decode(xml_file, element_hook=fill_missing_content, fill_missing=True)
self.assertDictEqual(xml_dict, expected)


class TestDecoding11(TestDecoding):
schema_class = XMLSchema11
Expand Down

0 comments on commit c9548da

Please sign in to comment.