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:
Davide Brunato 2019-08-23 08:48:02 +02:00
parent a6ef42d926
commit 6c47e49971
13 changed files with 168 additions and 114 deletions

View File

@ -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'

View File

@ -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

View File

@ -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 = []

View File

@ -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">

View File

@ -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

View File

@ -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()

View File

@ -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 = []

View File

@ -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):

View File

@ -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."""

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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):