Fixing W3C XSD 1.1 schema tests
- Add XSD 1.1 skip list in W3C test script - Regex: check unescaped double hyphens (--) - Check model extension allowed types
This commit is contained in:
parent
a6ef42d926
commit
6c47e49971
|
@ -22,10 +22,11 @@ from .converters import (
|
|||
from .documents import validate, to_dict, to_json, from_json
|
||||
|
||||
from .validators import (
|
||||
XMLSchemaValidatorError, XMLSchemaParseError, XMLSchemaNotBuiltError, XMLSchemaModelError,
|
||||
XMLSchemaModelDepthError, XMLSchemaValidationError, XMLSchemaDecodeError, XMLSchemaEncodeError,
|
||||
XMLSchemaChildrenValidationError, XMLSchemaIncludeWarning, XMLSchemaImportWarning, XsdGlobals,
|
||||
XMLSchemaBase, XMLSchema, XMLSchema10, XMLSchema11
|
||||
XMLSchemaValidatorError, XMLSchemaParseError, XMLSchemaNotBuiltError,
|
||||
XMLSchemaModelError, XMLSchemaModelDepthError, XMLSchemaValidationError,
|
||||
XMLSchemaDecodeError, XMLSchemaEncodeError, XMLSchemaChildrenValidationError,
|
||||
XMLSchemaIncludeWarning, XMLSchemaImportWarning, XMLSchemaTypeTableWarning,
|
||||
XsdGlobals, XMLSchemaBase, XMLSchema, XMLSchema10, XMLSchema11
|
||||
)
|
||||
|
||||
__version__ = '1.0.14'
|
||||
|
|
|
@ -20,6 +20,7 @@ from .compat import PY3, unicode_type, string_base_type, MutableSet
|
|||
from .exceptions import XMLSchemaValueError, XMLSchemaRegexError
|
||||
from .codepoints import UnicodeSubset, UNICODE_CATEGORIES, unicode_subset
|
||||
|
||||
_RE_HYPHENS = re.compile(r'(?<!\\)--')
|
||||
_RE_QUANTIFIER = re.compile(r'{\d+(,(\d+)?)?}')
|
||||
_RE_FORBIDDEN_ESCAPES = re.compile(
|
||||
r'(?<!\\)\\(U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|o{\d+}|\d+|A|Z|z|B|b|o)'
|
||||
|
@ -222,7 +223,14 @@ def parse_character_class(xml_regex, class_pos, xsd_version='1.0'):
|
|||
pos += 2
|
||||
elif xml_regex[pos] == ']' or xml_regex[pos:pos + 2] == '-[':
|
||||
if pos == group_pos:
|
||||
raise XMLSchemaRegexError("empty character class at position %d: %r" % (class_pos, xml_regex))
|
||||
raise XMLSchemaRegexError(
|
||||
"empty character class at position %d: %r" % (class_pos, xml_regex)
|
||||
)
|
||||
if _RE_HYPHENS.search(xml_regex[group_pos:pos]) and pos - group_pos > 2:
|
||||
raise XMLSchemaRegexError(
|
||||
"invalid character range '--' at position %d: %r" % (class_pos, xml_regex)
|
||||
)
|
||||
|
||||
char_group = XsdRegexCharGroup(xsd_version, xml_regex[group_pos:pos])
|
||||
if negative:
|
||||
char_group.complement()
|
||||
|
@ -236,7 +244,9 @@ def parse_character_class(xml_regex, class_pos, xsd_version='1.0'):
|
|||
subtracted_group, pos = parse_character_class(xml_regex, pos)
|
||||
pos += 1
|
||||
if xml_regex[pos] != ']':
|
||||
raise XMLSchemaRegexError("unterminated character group at position %d: %r" % (class_pos, xml_regex))
|
||||
raise XMLSchemaRegexError(
|
||||
"unterminated character group at position %d: %r" % (class_pos, xml_regex)
|
||||
)
|
||||
char_group -= subtracted_group
|
||||
|
||||
return char_group, pos
|
||||
|
|
|
@ -66,20 +66,20 @@ SKIPPED_TESTS = {
|
|||
'../saxonData/Assert/assert011.xsd', # TODO: XPath 2 doc() function in elementpath
|
||||
|
||||
# Invalid that may be valid
|
||||
'../msData/additional/adhocAddC002.xsd', # 4642: Lack of the processor on XML namespace knowledge
|
||||
'../msData/additional/test65026.xsd', # 4712: Lack of the processor on XML namespace knowledge
|
||||
'../msData/annotations/annotF001.xsd', # 4989: Annotation contains xml:lang="" ?? (but xml.xsd allows '')
|
||||
'../msData/datatypes/Facets/base64Binary/base64Binary_enumeration003.xsd', # 7277: check base64 invalid values
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_a001.xsd', # 7292: XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_a003.xsd', # 7294: XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_b004.xsd', # 7310: XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_b006.xsd', # 7312: XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/element/elemZ026.xsd', # 8541: This is good because the head element is abstract
|
||||
'../msData/element/elemZ031.xsd', # 8557: Valid in Python that has arbitrary large integers
|
||||
'../msData/group/groupH021.xsd', # 8679: TODO: wrong in XSD 1.0, good in XSD 1.1
|
||||
'../msData/identityConstraint/idC019.xsd', # 8936: TODO: is it an error?
|
||||
'../msData/identityConstraint/idI148.xsd', # 9291: FIXME attribute::* in a selector (restrict XPath parser)
|
||||
'../msData/modelGroups/mgE006.xsd', # 9712: Is valid (is mg007.xsd invalid for the same reason)
|
||||
'../msData/additional/adhocAddC002.xsd', # Lack of the processor on XML namespace knowledge
|
||||
'../msData/additional/test65026.xsd', # Lack of the processor on XML namespace knowledge
|
||||
'../msData/annotations/annotF001.xsd', # Annotation contains xml:lang="" ?? (but xml.xsd allows '')
|
||||
'../msData/datatypes/Facets/base64Binary/base64Binary_enumeration003.xsd', # check base64 invalid values
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_a001.xsd', # XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_a003.xsd', # XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_b004.xsd', # XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/datatypes/Facets/anyURI/anyURI_b006.xsd', # XSD 1.0 limited URI (see RFC 2396 + RFC 2732)
|
||||
'../msData/element/elemZ026.xsd', # This is good because the head element is abstract
|
||||
'../msData/element/elemZ031.xsd', # Valid in Python that has arbitrary large integers
|
||||
'../msData/group/groupH021.xsd', # TODO: wrong in XSD 1.0, good in XSD 1.1
|
||||
'../msData/identityConstraint/idC019.xsd', # TODO: is it an error?
|
||||
'../msData/identityConstraint/idI148.xsd', # FIXME attribute::* in a selector (restrict XPath parser)
|
||||
'../msData/modelGroups/mgE006.xsd', # Is valid (is mg007.xsd invalid for the same reason)
|
||||
|
||||
# Invalid that maybe valid because depends by implementation choices
|
||||
'../msData/schema/schG6_a.xsd', # Schema is valid because the ns import is done once, validation fails.
|
||||
|
@ -96,6 +96,13 @@ SKIPPED_TESTS = {
|
|||
|
||||
}
|
||||
|
||||
XSD11_SKIPPED_TESTS = {
|
||||
# Invalid that may be valid
|
||||
'../saxonData/Override/over026.bad.xsd', # Same as over003.xsd, that is signed as valid.
|
||||
'../msData/regex/reK86.xsd', # \P{Is} is valid in regex for XSD 1.1
|
||||
'../msData/regex/reK87.xsd', # \P{Is} is valid in regex for XSD 1.1
|
||||
}
|
||||
|
||||
|
||||
def extract_additional_arguments():
|
||||
"""
|
||||
|
@ -154,19 +161,19 @@ def create_w3c_test_group_case(filename, group_elem, group_num, xsd_version='1.0
|
|||
tag = '{%s}instanceDocument' % TEST_SUITE_NAMESPACE
|
||||
|
||||
try:
|
||||
source_path = elem.find(tag).get('{%s}href' % XLINK_NAMESPACE)
|
||||
source_href = elem.find(tag).get('{%s}href' % XLINK_NAMESPACE)
|
||||
except AttributeError:
|
||||
return
|
||||
else:
|
||||
if not schema_test and source_path.endswith('.testSet'):
|
||||
if not schema_test and source_href.endswith('.testSet'):
|
||||
return
|
||||
if source_path in SKIPPED_TESTS:
|
||||
if source_href in SKIPPED_TESTS:
|
||||
if args.numbers:
|
||||
print("Skip test number %d ..." % testgroup_num)
|
||||
return
|
||||
|
||||
# Normalize and check file path
|
||||
source_path = os.path.normpath(os.path.join(os.path.dirname(filename), source_path))
|
||||
source_path = os.path.normpath(os.path.join(os.path.dirname(filename), source_href))
|
||||
if not os.path.isfile(source_path):
|
||||
print("ERROR: file %r not found!" % source_path)
|
||||
return
|
||||
|
@ -176,6 +183,8 @@ def create_w3c_test_group_case(filename, group_elem, group_num, xsd_version='1.0
|
|||
for version in xsd_version.split():
|
||||
if version not in args.version:
|
||||
continue
|
||||
elif version == '1.1' and source_href in XSD11_SKIPPED_TESTS:
|
||||
continue
|
||||
|
||||
for e in elem.findall('{%s}expected' % TEST_SUITE_NAMESPACE):
|
||||
if 'version' not in e.attrib:
|
||||
|
@ -207,10 +216,6 @@ def create_w3c_test_group_case(filename, group_elem, group_num, xsd_version='1.0
|
|||
if args.numbers and testgroup_num not in args.numbers:
|
||||
return
|
||||
|
||||
# if testgroup_num not in (4759, 8201, 10874, 10881, 10976, 10981, 14377,
|
||||
# 14420, 14425, 14426, 14457, 14656, 14740, 14945, 15009, 15011):
|
||||
# return
|
||||
|
||||
name = group_elem.attrib['name']
|
||||
group_tests = []
|
||||
|
||||
|
|
|
@ -220,6 +220,35 @@ class TestXsdComplexType(XsdValidatorTestCase):
|
|||
base, '<xs:choice maxOccurs="2"><xs:element name="A"/><xs:element name="C"/></xs:choice>',
|
||||
)
|
||||
|
||||
base = """
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xs:complexType name="b">
|
||||
<xs:choice>
|
||||
<xs:element name="a" minOccurs="0" maxOccurs="5"/>
|
||||
<xs:element name="b" minOccurs="0" maxOccurs="5"/>
|
||||
<xs:element name="c" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="http://one.com/" processContents="skip" minOccurs="2" maxOccurs="2"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="e">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="b">
|
||||
<xs:all>
|
||||
<xs:element name="e" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="f" minOccurs="0" maxOccurs="4"/>
|
||||
<xs:any notNamespace="http://two.com/" processContents="skip" minOccurs="2" maxOccurs="2"/>
|
||||
</xs:all>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="doc" type="e"/>
|
||||
|
||||
|
||||
</xs:schema>"""
|
||||
|
||||
def test_occurs_restriction(self):
|
||||
base = """
|
||||
<xs:sequence minOccurs="3" maxOccurs="10">
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
"""
|
||||
XML Schema validators subpackage.
|
||||
"""
|
||||
from .exceptions import XMLSchemaValidatorError, XMLSchemaParseError, XMLSchemaModelError, \
|
||||
XMLSchemaModelDepthError, XMLSchemaValidationError, XMLSchemaDecodeError, XMLSchemaEncodeError, \
|
||||
XMLSchemaNotBuiltError, XMLSchemaChildrenValidationError, XMLSchemaIncludeWarning, XMLSchemaImportWarning
|
||||
from .exceptions import XMLSchemaValidatorError, XMLSchemaParseError, \
|
||||
XMLSchemaModelError, XMLSchemaModelDepthError, XMLSchemaValidationError, \
|
||||
XMLSchemaDecodeError, XMLSchemaEncodeError, XMLSchemaNotBuiltError, \
|
||||
XMLSchemaChildrenValidationError, XMLSchemaIncludeWarning, \
|
||||
XMLSchemaImportWarning, XMLSchemaTypeTableWarning
|
||||
|
||||
from .xsdbase import XsdValidator, XsdComponent, XsdAnnotation, XsdType, ValidationMixin, ParticleMixin
|
||||
|
||||
|
|
|
@ -273,6 +273,8 @@ class Xsd11Attribute(XsdAttribute):
|
|||
|
||||
def _parse(self):
|
||||
super(Xsd11Attribute, self)._parse()
|
||||
if self.use == 'prohibited' and 'fixed' in self.elem.attrib:
|
||||
self.parse_error("attribute 'fixed' with use=prohibited is not allowed in XSD 1.1")
|
||||
if self._parse_boolean_attribute('inheritable'):
|
||||
self.inheritable = True
|
||||
self._parse_target_namespace()
|
||||
|
|
|
@ -272,6 +272,17 @@ class XsdComplexType(XsdType, ValidationMixin):
|
|||
elif complex_content and base_type.is_simple():
|
||||
self.parse_error("a complexType ancestor required: %r" % base_type, elem)
|
||||
return self.maps.types[XSD_ANY_TYPE]
|
||||
|
||||
if base_type.final and elem.tag.rsplit('}', 1)[-1] in base_type.final:
|
||||
msg = "derivation by %r blocked by attribute 'final' in base type"
|
||||
self.parse_error(msg % elem.tag.rsplit('}', 1)[-1])
|
||||
if base_type.base_type is self.any_simple_type and self.xsd_version > '1.0':
|
||||
self.parse_error(
|
||||
"the simple content of %r is not a valid simple type in XSD 1.1 "
|
||||
"(derivation from xs:anySimpleType but missing variety, see http:"
|
||||
"//www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition_details)" % base_type
|
||||
)
|
||||
|
||||
return base_type
|
||||
|
||||
def _parse_simple_content_restriction(self, elem, base_type):
|
||||
|
@ -402,25 +413,36 @@ class XsdComplexType(XsdType, ValidationMixin):
|
|||
content_type = self.schema.BUILDERS.group_class(sequence_elem, self.schema, self)
|
||||
|
||||
if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
|
||||
# Illegal derivation from a simple content. Applies to both XSD 1.0 and XSD 1.1.
|
||||
# For the detailed rule refer to XSD 1.1 documentation:
|
||||
# https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#sec-cos-ct-extends
|
||||
if base_type.is_simple() or base_type.has_simple_content():
|
||||
# Illegal derivation from a simple content. Always forbidden in XSD 1.1
|
||||
# for XSD 1.0 applies only with not empty base and not empty extension.
|
||||
if base_type.is_simple() or base_type.has_simple_content() and self.xsd_version == '1.0':
|
||||
self.parse_error("base %r is simple or has a simple content." % base_type, elem)
|
||||
base_type = self.maps.types[XSD_ANY_TYPE]
|
||||
|
||||
group = self.schema.BUILDERS.group_class(group_elem, self.schema, self)
|
||||
if group.model == 'all' and self.xsd_version == '1.0':
|
||||
self.parse_error("Cannot extend a complex content with an all model")
|
||||
self.parse_error("cannot extend a complex content with xs:all")
|
||||
if base_type.content_type.model == 'all':
|
||||
if group.model == 'sequence':
|
||||
self.parse_error(
|
||||
"xs:sequence cannot extend xs:all even if the xs:all is a singleton"
|
||||
)
|
||||
elif group.model == 'all' and base_type.content_type.min_occurs != group.min_occurs:
|
||||
self.parse_error("when xs:all extends xs:all the minOccurs must be the same")
|
||||
elif base_type.content_type.model == 'sequence':
|
||||
if group.model == 'all':
|
||||
self.parse_error("xs:all cannot extend xs:sequence")
|
||||
|
||||
content_type.append(base_type.content_type)
|
||||
content_type.append(group)
|
||||
sequence_elem.append(base_type.content_type.elem)
|
||||
sequence_elem.append(group.elem)
|
||||
|
||||
if base_type.content_type.model == 'all' and base_type.content_type and group \
|
||||
and self.xsd_version == '1.0':
|
||||
self.parse_error("XSD 1.0 does not allow extension of a not empty 'ALL' model group.", elem)
|
||||
if base_type.content_type.model == 'all' and base_type.content_type and group:
|
||||
if self.xsd_version == '1.0':
|
||||
self.parse_error("XSD 1.0 does not allow extension of a not empty 'all' model group")
|
||||
elif group.model != 'all':
|
||||
self.parse_error("cannot extend a not empty 'all' model group with a different model")
|
||||
|
||||
if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE:
|
||||
self.parse_error("base has a different content type (mixed=%r) and the "
|
||||
|
@ -701,6 +723,15 @@ class Xsd11ComplexType(XsdComplexType):
|
|||
(k, v) for k, v in self.schema.default_attributes.items() if k not in self.attributes
|
||||
)
|
||||
|
||||
def _parse_complex_content_extension(self, elem, base_type):
|
||||
# Complex content extension with simple base is forbidden XSD 1.1.
|
||||
# For the detailed rule refer to XSD 1.1 documentation:
|
||||
# https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#sec-cos-ct-extends
|
||||
if base_type.is_simple() or base_type.has_simple_content():
|
||||
self.parse_error("base %r is simple or has a simple content." % base_type, elem)
|
||||
base_type = self.maps.types[XSD_ANY_TYPE]
|
||||
super(Xsd11ComplexType, self)._parse_complex_content_extension(elem, base_type)
|
||||
|
||||
def _parse_content_tail(self, elem, **kwargs):
|
||||
self.attributes = self.schema.BUILDERS.attribute_group_class(elem, self.schema, self, **kwargs)
|
||||
self.assertions = []
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
This module contains classes for XML Schema elements, complex types and model groups.
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
import warnings
|
||||
from decimal import Decimal
|
||||
from elementpath import XPath2Parser, ElementPathError, XPathContext
|
||||
from elementpath.datatypes import AbstractDateTime, Duration
|
||||
|
@ -27,7 +28,7 @@ from ..etree import etree_element
|
|||
from ..converters import ElementData, raw_xml_encode, XMLSchemaConverter
|
||||
from ..xpath import XMLSchemaProxy, ElementPathMixin
|
||||
|
||||
from .exceptions import XMLSchemaValidationError
|
||||
from .exceptions import XMLSchemaValidationError, XMLSchemaTypeTableWarning
|
||||
from .xsdbase import XsdComponent, XsdType, ValidationMixin, ParticleMixin
|
||||
from .identities import XsdKeyref
|
||||
from .wildcards import XsdAnyElement
|
||||
|
@ -753,13 +754,7 @@ class XsdElement(XsdComponent, ValidationMixin, ParticleMixin, ElementPathMixin)
|
|||
|
||||
:returns: `True` if there is no inconsistency between the particles, `False` otherwise,
|
||||
"""
|
||||
if isinstance(other, XsdAnyElement):
|
||||
xsd_element = other.matched_element(self.name, self.default_namespace)
|
||||
return xsd_element is None or self.is_consistent(xsd_element)
|
||||
elif self.name != other.name:
|
||||
return True
|
||||
else:
|
||||
return self.type is other.type
|
||||
return self.name != other.name or self.type is other.type
|
||||
|
||||
|
||||
class Xsd11Element(XsdElement):
|
||||
|
@ -806,9 +801,13 @@ class Xsd11Element(XsdElement):
|
|||
self.alternatives = self.ref.alternatives
|
||||
else:
|
||||
alternatives = []
|
||||
has_test = True
|
||||
for child in filter(lambda x: x.tag != XSD_ANNOTATION, self.elem[index:]):
|
||||
if child.tag == XSD_ALTERNATIVE:
|
||||
alternatives.append(XsdAlternative(child, self.schema, self))
|
||||
if not has_test:
|
||||
self.parse_error("test attribute missing on non-final alternative")
|
||||
has_test = 'test' in child.attrib
|
||||
index += 1
|
||||
else:
|
||||
break
|
||||
|
@ -850,33 +849,40 @@ class Xsd11Element(XsdElement):
|
|||
if isinstance(other, XsdElement):
|
||||
if self.name == other.name:
|
||||
return True
|
||||
elif other.substitution_group == self.name or other.name == self.substitution_group:
|
||||
elif any(self.name == x.name for x in other.iter_substitutes()):
|
||||
return True
|
||||
|
||||
for e in self.iter_substitutes():
|
||||
if other.name == e.name or any(x is e for x in other.iter_substitutes()):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_consistent(self, other):
|
||||
def is_consistent(self, other, strict=True):
|
||||
if isinstance(other, XsdAnyElement):
|
||||
if other.process_contents == 'skip':
|
||||
return True
|
||||
xsd_element = other.matched_element(self.name, self.default_namespace)
|
||||
return xsd_element is None or self.is_consistent(xsd_element)
|
||||
return xsd_element is None or self.is_consistent(xsd_element, False)
|
||||
|
||||
if self.name == other.name:
|
||||
xsd_element = self
|
||||
e = self
|
||||
else:
|
||||
for e in self.iter_substitutes():
|
||||
if e.name == other.name:
|
||||
xsd_element = e
|
||||
break
|
||||
else:
|
||||
return True
|
||||
|
||||
if xsd_element.type is not other.type or len(xsd_element.alternatives) != len(other.alternatives):
|
||||
if len(e.alternatives) != len(other.alternatives):
|
||||
return False
|
||||
elif not all(any(a == x for x in other.alternatives) for a in xsd_element.alternatives):
|
||||
elif e.type is not other.type and strict:
|
||||
return False
|
||||
else:
|
||||
return all(any(a == x for x in xsd_element.alternatives) for a in other.alternatives)
|
||||
elif e.type is not other.type or \
|
||||
not all(any(a == x for x in other.alternatives) for a in e.alternatives) or \
|
||||
not all(any(a == x for x in e.alternatives) for a in other.alternatives):
|
||||
msg = "Maybe a not equivalent type table between elements %r and %r." % (self, other)
|
||||
warnings.warn(msg, XMLSchemaTypeTableWarning, stacklevel=3)
|
||||
return True
|
||||
|
||||
|
||||
class XsdAlternative(XsdComponent):
|
||||
|
|
|
@ -349,3 +349,7 @@ class XMLSchemaIncludeWarning(XMLSchemaWarning):
|
|||
|
||||
class XMLSchemaImportWarning(XMLSchemaWarning):
|
||||
"""A schema namespace import fails."""
|
||||
|
||||
|
||||
class XMLSchemaTypeTableWarning(XMLSchemaWarning):
|
||||
"""Not equivalent type table found in model."""
|
||||
|
|
|
@ -474,7 +474,9 @@ class XsdGlobals(XsdValidator):
|
|||
else:
|
||||
constraint.selector = ref.selector
|
||||
constraint.fields = ref.fields
|
||||
if isinstance(constraint, XsdKeyref):
|
||||
if not isinstance(ref, constraint.__class__):
|
||||
constraint.parse_error("attribute 'ref' points to a different kind constraint")
|
||||
elif isinstance(constraint, XsdKeyref):
|
||||
constraint.refer = ref.refer
|
||||
constraint.ref = ref
|
||||
|
||||
|
|
|
@ -786,7 +786,6 @@ class Xsd11Group(XsdGroup):
|
|||
return self[0].is_restriction(other[0], check_occurs)
|
||||
|
||||
if self.model == 'choice' and len(self) > 1:
|
||||
print(self, other)
|
||||
if False:
|
||||
for item in self:
|
||||
if item is other or item.is_restriction(other):
|
||||
|
@ -815,57 +814,12 @@ class Xsd11Group(XsdGroup):
|
|||
item_iterator = iter(self.iter_model())
|
||||
item = next(item_iterator, None)
|
||||
|
||||
# print("SELF: ", list(self.iter_model()))
|
||||
# print("OTHER: ", list(other.iter_model()))
|
||||
# breakpoint()
|
||||
|
||||
for other_item in other.iter_model():
|
||||
if item is not None and item.is_restriction(other_item, check_occurs):
|
||||
item = next(item_iterator, None)
|
||||
elif not other_item.is_emptiable():
|
||||
print("SELF: ", list(self.iter_model()))
|
||||
print("OTHER: ", list(other.iter_model()))
|
||||
# breakpoint()
|
||||
return False
|
||||
return True
|
||||
|
||||
def _is_sequence_restriction(self, other):
|
||||
if not self.has_occurs_restriction(other):
|
||||
return False
|
||||
|
||||
check_occurs = other.max_occurs != 0
|
||||
|
||||
item_iterator = iter(self.iter_model())
|
||||
item = next(item_iterator, None)
|
||||
|
||||
print("SELF: ", list(self.iter_model()))
|
||||
print("OTHER: ", list(other.iter_model()))
|
||||
print("Self:", self.effective_min_occurs, self.effective_max_occurs)
|
||||
print("Other:", other.effective_min_occurs, other.effective_max_occurs)
|
||||
|
||||
for other_item in other.iter_model():
|
||||
min_occurs = 0
|
||||
max_occurs = Occurrence(other_item.effective_max_occurs)
|
||||
|
||||
while item is not None:
|
||||
if other_item is item:
|
||||
if max_occurs < item.effective_max_occurs:
|
||||
return False
|
||||
min_occurs += item.effective_min_occurs
|
||||
max_occurs.sub(item.effective_max_occurs)
|
||||
item = next(item_iterator, None)
|
||||
elif max_occurs >= item.effective_max_occurs and \
|
||||
item.is_restriction(other_item, check_occurs):
|
||||
min_occurs += item.effective_min_occurs
|
||||
max_occurs.sub(item.effective_max_occurs)
|
||||
item = next(item_iterator, None)
|
||||
else:
|
||||
break
|
||||
|
||||
if min_occurs < other_item.effective_min_occurs:
|
||||
breakpoint()
|
||||
return False
|
||||
return True
|
||||
return item is None
|
||||
|
||||
def is_all_restriction(self, other):
|
||||
if not self.has_occurs_restriction(other):
|
||||
|
|
|
@ -666,10 +666,17 @@ class XsdList(XsdSimpleType):
|
|||
except KeyError:
|
||||
self.parse_error("unknown itemType %r" % elem.attrib['itemType'], elem)
|
||||
base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE]
|
||||
else:
|
||||
if isinstance(base_type, tuple):
|
||||
self.parse_error("circular definition found for type {!r}".format(item_qname))
|
||||
base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE]
|
||||
|
||||
if base_type.final == '#all' or 'list' in base_type.final:
|
||||
self.parse_error("'final' value of the itemType %r forbids derivation by list" % base_type)
|
||||
|
||||
if base_type is self.any_atomic_type:
|
||||
self.parse_error("Cannot use xs:anyAtomicType as base type of a user-defined type")
|
||||
|
||||
try:
|
||||
self.base_type = base_type
|
||||
except XMLSchemaValueError as err:
|
||||
|
@ -835,11 +842,13 @@ class XsdUnion(XsdSimpleType):
|
|||
|
||||
member_types.append(mt)
|
||||
|
||||
if member_types:
|
||||
self.member_types = member_types
|
||||
else:
|
||||
if not member_types:
|
||||
self.parse_error("missing xs:union type declarations", elem)
|
||||
self.member_types = [self.maps.types[XSD_ANY_ATOMIC_TYPE]]
|
||||
elif any(mt is self.any_atomic_type for mt in member_types):
|
||||
self.parse_error("Cannot use xs:anyAtomicType as base type of a user-defined type")
|
||||
else:
|
||||
self.member_types = member_types
|
||||
|
||||
@property
|
||||
def admitted_facets(self):
|
||||
|
@ -1107,6 +1116,8 @@ class XsdAtomicRestriction(XsdAtomic):
|
|||
self.parse_error("missing base type in restriction:", self)
|
||||
elif base_type.final == '#all' or 'restriction' in base_type.final:
|
||||
self.parse_error("'final' value of the baseType %r forbids derivation by restriction" % base_type)
|
||||
if base_type is self.any_atomic_type:
|
||||
self.parse_error("Cannot use xs:anyAtomicType as base type of a user-defined type")
|
||||
|
||||
self.base_type = base_type
|
||||
self.facets = facets
|
||||
|
|
|
@ -118,8 +118,8 @@ class XsdWildcard(XsdComponent, ValidationMixin):
|
|||
self.parse_error("wrong QName format in 'notQName' attribute: %s" % str(err))
|
||||
return
|
||||
|
||||
if self.not_namespace and all(
|
||||
get_namespace(x) in self.not_namespace for x in names if not x.startswith('##')):
|
||||
if self.not_namespace and any(not x.startswith('##') for x in names) and \
|
||||
all(get_namespace(x) in self.not_namespace for x in names if not x.startswith('##')):
|
||||
self.parse_error("the namespace of each QName in notQName is allowed by notNamespace")
|
||||
|
||||
self.not_qname = names
|
||||
|
@ -411,10 +411,7 @@ class XsdAnyElement(XsdWildcard, ParticleMixin, ElementPathMixin):
|
|||
return any(ns in self.namespace for ns in other.namespace)
|
||||
|
||||
def is_consistent(self, other):
|
||||
if isinstance(other, XsdAnyElement):
|
||||
return True
|
||||
xsd_element = self.matched_element(other.name, other.default_namespace)
|
||||
return xsd_element is None or other.is_consistent(xsd_element)
|
||||
return True
|
||||
|
||||
|
||||
class XsdAnyAttribute(XsdWildcard):
|
||||
|
@ -520,7 +517,7 @@ class Xsd11AnyElement(XsdAnyElement):
|
|||
if isinstance(other, XsdAnyElement) or self.process_contents == 'skip':
|
||||
return True
|
||||
xsd_element = self.matched_element(other.name, other.default_namespace)
|
||||
return xsd_element is None or other.is_consistent(xsd_element)
|
||||
return xsd_element is None or other.is_consistent(xsd_element, False)
|
||||
|
||||
|
||||
class Xsd11AnyAttribute(XsdAnyAttribute):
|
||||
|
|
Loading…
Reference in New Issue