Fix name matching and targetNamespace for XSD 1.1 declarations

- Use the targetNamespace of reference
  - In case of a default namespace try also the match with the local name
This commit is contained in:
Davide Brunato 2019-10-30 18:05:41 +01:00
parent 2b1497860b
commit 4c624af6c9
4 changed files with 47 additions and 24 deletions

View File

@ -286,9 +286,12 @@ class Xsd11Attribute(XsdAttribute):
@property
def target_namespace(self):
if self._target_namespace is None:
if self._target_namespace is not None:
return self._target_namespace
elif self.ref is not None:
return self.ref.target_namespace
else:
return self.schema.target_namespace
return self._target_namespace
def _parse(self):
super(Xsd11Attribute, self)._parse()

View File

@ -715,26 +715,38 @@ class XsdElement(XsdComponent, ValidationMixin, ParticleMixin, ElementPathMixin)
def is_matching(self, name, default_namespace=None, group=None):
if default_namespace and name[0] != '{':
name = '{%s}%s' % (default_namespace, name)
if name in self.names:
return True
for xsd_element in self.iter_substitutes():
if name in xsd_element.names:
qname = '{%s}%s' % (default_namespace, name)
if name in self.names or qname in self.names:
return True
for xsd_element in self.iter_substitutes():
if name in xsd_element.names or qname in xsd_element.names:
return True
elif name in self.names:
return True
else:
for xsd_element in self.iter_substitutes():
if name in xsd_element.names:
return True
return False
def match(self, name, default_namespace=None, **kwargs):
if default_namespace and name[0] != '{':
name = '{%s}%s' % (default_namespace, name)
qname = '{%s}%s' % (default_namespace, name)
if name in self.names or qname in self.names:
return self
if name in self.names:
for xsd_element in self.iter_substitutes():
if name in xsd_element.names or qname in xsd_element.names:
return xsd_element
elif name in self.names:
return self
for xsd_element in self.iter_substitutes():
if name in xsd_element.names:
return xsd_element
else:
for xsd_element in self.iter_substitutes():
if name in xsd_element.names:
return xsd_element
def is_restriction(self, other, check_occurs=True):
if isinstance(other, XsdAnyElement):
@ -905,9 +917,12 @@ class Xsd11Element(XsdElement):
@property
def target_namespace(self):
if self._target_namespace is None:
if self._target_namespace is not None:
return self._target_namespace
elif self.ref is not None:
return self.ref.target_namespace
else:
return self.schema.target_namespace
return self._target_namespace
def iter_components(self, xsd_classes=None):
if xsd_classes is None:

View File

@ -140,7 +140,8 @@ class XsdWildcard(XsdComponent, ValidationMixin):
elif default_namespace is None:
return self.is_namespace_allowed('')
else:
return self.is_namespace_allowed(default_namespace)
return self.is_namespace_allowed('') or \
self.is_namespace_allowed(default_namespace)
def is_namespace_allowed(self, namespace):
if self.not_namespace:
@ -656,12 +657,15 @@ class Xsd11AnyElement(XsdAnyElement):
if name is None:
return False
elif not name or name[0] == '{':
namespace = get_namespace(name)
elif default_namespace is None:
namespace = ''
if not self.is_namespace_allowed(get_namespace(name)):
return False
elif default_namespace is not None:
if not self.is_namespace_allowed(''):
return False
else:
name = '{%s}%s' % (default_namespace, name)
namespace = default_namespace
if not self.is_namespace_allowed('') and not self.is_namespace_allowed(default_namespace):
return False
if group in self.precedences:
if occurs is None:
@ -676,7 +680,8 @@ class Xsd11AnyElement(XsdAnyElement):
if any(e.is_matching(name) for e in group.iter_elements()
if not isinstance(e, XsdAnyElement)):
return False
return name not in self.not_qname and self.is_namespace_allowed(namespace)
return name not in self.not_qname
def is_consistent(self, other):
if isinstance(other, XsdAnyElement) or self.process_contents == 'skip':

View File

@ -299,7 +299,7 @@ class XsdComponent(XsdValidator):
@property
def target_namespace(self):
"""Property that references to schema's targetNamespace."""
return self.schema.target_namespace
return self.schema.target_namespace if self.ref is None else self.ref.target_namespace
@property
def default_namespace(self):