Refine 'all' models visiting

- Restart at every match with not exhausted items
  - Do not check occurs on stop_item()
  - Do not reset element counter when repeat
This commit is contained in:
Davide Brunato 2019-10-31 07:29:09 +01:00
parent 4c624af6c9
commit b95d890f51
2 changed files with 30 additions and 10 deletions

View File

@ -630,6 +630,27 @@ class TestModelValidation11(TestModelValidation):
self.assertIsNone(schema.validate(xml_data))
def test_all_model_with_extended_occurs(self):
schema = self.schema_class(
"""<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="a" minOccurs="0" maxOccurs="5"/>
<xs:element name="b" maxOccurs="5"/>
<xs:element name="c" minOccurs="2" maxOccurs="5"/>
<xs:element name="d" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
""")
xml_data = '<root><a/><b/><d/><c/><a/><c/></root>'
self.assertIsNone(schema.validate(xml_data))
class TestModelBasedSorting(XsdValidatorTestCase):

View File

@ -440,7 +440,10 @@ class ModelVisitor(MutableSequence):
item_occurs = occurs[item]
model = self.group.model
if item_occurs:
if model == 'all':
return False
elif item_occurs:
self.match = True
if model == 'choice':
occurs[item] = 0
@ -470,7 +473,7 @@ class ModelVisitor(MutableSequence):
occurs[element] += 1
self.match = True
if self.group.model == 'all':
pass
self.items = (e for e in self.group if not e.is_over(occurs[e]))
elif not element.is_over(occurs[element]):
return
@ -487,8 +490,6 @@ class ModelVisitor(MutableSequence):
if obj is None:
if not self.match:
if self.group.model == 'all':
for e in self.group:
occurs[e] = occurs[(e,)]
if all(e.min_occurs <= occurs[e] for e in self.group):
occurs[self.group] = 1
group, expected = self.group, self.expected
@ -497,16 +498,14 @@ class ModelVisitor(MutableSequence):
elif self.group.model != 'all':
self.items, self.match = iter(self.group), False
elif any(not e.is_over(occurs[e]) for e in self.group):
for e in self.group:
occurs[(e,)] += occurs[e]
self.items, self.match = (e for e in self.group if not e.is_over(occurs[e])), False
else:
for e in self.group:
occurs[(e,)] += occurs[e]
occurs[self.group] = 1
elif not isinstance(obj, ModelGroup): # XsdElement or XsdAnyElement
self.element, occurs[obj] = obj, 0
self.element = obj
if self.group.model != 'all':
occurs[obj] = 0
return
else:
@ -515,7 +514,7 @@ class ModelVisitor(MutableSequence):
occurs[obj] = 0
if obj.model == 'all':
for e in obj:
occurs[(e,)] = 0
occurs[e] = 0
except IndexError:
# Model visit ended