Package xmlschema_acue :: Package validators :: Module elements

Source Code for Module xmlschema_acue.validators.elements

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright (c), 2016-2019, SISSA (International School for Advanced Studies). 
  4  # All rights reserved. 
  5  # This file is distributed under the terms of the MIT License. 
  6  # See the file 'LICENSE' in the root directory of the present 
  7  # distribution, or http://opensource.org/licenses/MIT. 
  8  # 
  9  # @author Davide Brunato <brunato@sissa.it> 
 10  # 
 11  """ 
 12  This module contains classes for XML Schema elements, complex types and model groups. 
 13  """ 
 14  from __future__ import unicode_literals 
 15  from decimal import Decimal 
 16  from elementpath import XPath2Parser, ElementPathSyntaxError, XPathContext 
 17  from elementpath.xpath_helpers import boolean_value 
 18  from elementpath.datatypes import AbstractDateTime, Duration 
 19   
 20  from xmlschema_acue.exceptions import XMLSchemaAttributeError 
 21  from xmlschema_acue.qnames import XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE, XSD_ATTRIBUTE_GROUP, \ 
 22      XSD_COMPLEX_TYPE, XSD_SIMPLE_TYPE, XSD_ALTERNATIVE, XSD_ELEMENT, XSD_ANY_TYPE, XSD_UNIQUE, \ 
 23      XSD_KEY, XSD_KEYREF, XSI_NIL, XSI_TYPE, XSD_ID 
 24  from xmlschema_acue.helpers import get_qname, get_xml_bool_attribute, get_xsd_derivation_attribute, \ 
 25      get_xsd_form_attribute, ParticleCounter 
 26  from xmlschema_acue.etree import etree_element 
 27  from xmlschema_acue.converters import ElementData, raw_xml_encode, XMLSchemaConverter 
 28  from xmlschema_acue.xpath import ElementPathMixin 
 29   
 30  from xmlschema_acue.validators.exceptions import XMLSchemaValidationError 
 31  from xmlschema_acue.validators.xsdbase import XsdComponent, XsdType, ValidationMixin, ParticleMixin 
 32  from xmlschema_acue.validators.identities import XsdUnique, XsdKey, XsdKeyref 
 33  from xmlschema_acue.validators.wildcards import XsdAnyElement 
 34   
 35   
 36  XSD_MODEL_GROUP_TAGS = {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE} 
 37  XSD_ATTRIBUTE_GROUP_ELEMENT = etree_element(XSD_ATTRIBUTE_GROUP) 
38 39 40 -class XsdElement(XsdComponent, ValidationMixin, ParticleMixin, ElementPathMixin):
41 """ 42 Class for XSD 1.0 'element' declarations. 43 44 <element 45 abstract = boolean : false 46 block = (#all | List of (extension | restriction | substitution)) 47 default = string 48 final = (#all | List of (extension | restriction)) 49 fixed = string 50 form = (qualified | unqualified) 51 id = ID 52 maxOccurs = (nonNegativeInteger | unbounded) : 1 53 minOccurs = nonNegativeInteger : 1 54 name = NCName 55 nillable = boolean : false 56 ref = QName 57 substitutionGroup = QName 58 type = QName 59 {any attributes with non-schema namespace . . .}> 60 Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*)) 61 </element> 62 """ 63 _admitted_tags = {XSD_ELEMENT} 64 qualified = False 65 _ref = None 66 _abstract = False 67 _block = None 68 _final = None 69 _substitution_group = None 70
71 - def __init__(self, elem, schema, parent, name=None):
72 super(XsdElement, self).__init__(elem, schema, parent, name) 73 self.names = (self.qualified_name,) if self.qualified else (self.qualified_name, self.local_name) 74 if not hasattr(self, 'type'): 75 raise XMLSchemaAttributeError("undefined 'type' attribute for %r." % self) 76 if not hasattr(self, 'qualified'): 77 raise XMLSchemaAttributeError("undefined 'qualified' attribute for %r." % self)
78
79 - def __repr__(self):
80 if self.ref is None: 81 return '%s(name=%r, occurs=%r)' % (self.__class__.__name__, self.prefixed_name, self.occurs) 82 else: 83 return '%s(ref=%r, occurs=%r)' % (self.__class__.__name__, self.prefixed_name, self.occurs)
84
85 - def __setattr__(self, name, value):
86 if name == "type": 87 assert value is None or isinstance(value, XsdType), "Wrong value %r for attribute 'type'." % value 88 if hasattr(value, 'attributes'): 89 self.attributes = value.attributes 90 else: 91 self.attributes = self.schema.BUILDERS.attribute_group_class( 92 XSD_ATTRIBUTE_GROUP_ELEMENT, self.schema, self 93 ) 94 super(XsdElement, self).__setattr__(name, value)
95
96 - def __iter__(self):
97 if not self.type.has_simple_content(): 98 for e in self.type.content_type.iter_subelements(): 99 yield e
100
101 - def _parse(self):
102 XsdComponent._parse(self) 103 self._parse_attributes() 104 index = self._parse_type() 105 self._parse_identity_constraints(index) 106 if self.parent is None: 107 self._parse_substitution_group()
108
109 - def _parse_attributes(self):
110 elem = self.elem 111 attrib = elem.attrib 112 self._parse_particle(elem) 113 114 try: 115 self.qualified = (self.form or self.schema.element_form_default) == 'qualified' 116 except ValueError as err: 117 self.parse_error(err) 118 119 name = elem.get('name') 120 if name is not None: 121 if self.parent is None or self.qualified: 122 self.name = get_qname(self.target_namespace, attrib['name']) 123 else: 124 self.name = attrib['name'] 125 elif self.parent is None: 126 self.parse_error("missing 'name' in a global element declaration") 127 self.name = elem.get('ref', 'nameless_%s' % str(id(self))) 128 elif 'ref' not in attrib: 129 self.parse_error("missing both 'name' and 'ref' attributes") 130 self.name = elem.get('nameless_%s' % str(id(self))) 131 else: 132 try: 133 element_name = self.schema.resolve_qname(attrib['ref']) 134 except ValueError as err: 135 self.parse_error(err) 136 self.type = self.maps.types[XSD_ANY_TYPE] 137 self.name = elem.get('nameless_%s' % str(id(self))) 138 else: 139 if not element_name: 140 self.parse_error("empty 'ref' attribute") 141 self.type = self.maps.types[XSD_ANY_TYPE] 142 self.name = elem.get('nameless_%s' % str(id(self))) 143 else: 144 try: 145 xsd_element = self.maps.lookup_element(element_name) 146 except KeyError: 147 self.parse_error('unknown element %r' % element_name) 148 self.name = element_name 149 self.type = self.maps.types[XSD_ANY_TYPE] 150 else: 151 self._ref = xsd_element 152 self.name = xsd_element.name 153 self.type = xsd_element.type 154 self.qualified = xsd_element.qualified 155 156 for attr_name in ('name', 'type', 'nillable', 'default', 'fixed', 'form', 157 'block', 'abstract', 'final', 'substitutionGroup'): 158 if attr_name in attrib: 159 self.parse_error("attribute %r is not allowed when element reference is used." % attr_name) 160 return 161 162 if 'default' in attrib and 'fixed' in attrib: 163 self.parse_error("'default' and 'fixed' attributes are mutually exclusive.") 164 165 if 'abstract' in elem.attrib: 166 try: 167 self._abstract = get_xml_bool_attribute(elem, 'abstract') 168 except ValueError as err: 169 self.parse_error(err, elem) 170 else: 171 if self.parent is not None: 172 self.parse_error("local scope elements cannot have abstract attribute") 173 174 if 'block' in elem.attrib: 175 try: 176 self._block = get_xsd_derivation_attribute( 177 elem, 'block', ('extension', 'restriction', 'substitution') 178 ) 179 except ValueError as err: 180 self.parse_error(err, elem) 181 182 if self.parent is None: 183 self._parse_properties('nillable') 184 185 if 'final' in elem.attrib: 186 try: 187 self._final = get_xsd_derivation_attribute(elem, 'final', ('extension', 'restriction')) 188 except ValueError as err: 189 self.parse_error(err, elem) 190 191 for attr_name in ('ref', 'form', 'minOccurs', 'maxOccurs'): 192 if attr_name in attrib: 193 self.parse_error("attribute %r not allowed in a global element declaration" % attr_name) 194 else: 195 self._parse_properties('form', 'nillable') 196 197 for attr_name in ('final', 'substitutionGroup'): 198 if attr_name in attrib: 199 self.parse_error("attribute %r not allowed in a local element declaration" % attr_name)
200
201 - def _parse_type(self):
202 attrib = self.elem.attrib 203 if self.ref: 204 if self._parse_component(self.elem, required=False, strict=False) is not None: 205 self.parse_error("element reference declaration can't has children.") 206 elif 'type' in attrib: 207 try: 208 self.type = self.maps.lookup_type(self.schema.resolve_qname(attrib['type'])) 209 except KeyError: 210 self.parse_error('unknown type %r' % attrib['type']) 211 self.type = self.maps.types[XSD_ANY_TYPE] 212 except ValueError as err: 213 self.parse_error(err) 214 self.type = self.maps.types[XSD_ANY_TYPE] 215 finally: 216 child = self._parse_component(self.elem, required=False, strict=False) 217 if child is not None and child.tag in (XSD_COMPLEX_TYPE, XSD_SIMPLE_TYPE): 218 msg = "the attribute 'type' and the <%s> local declaration are mutually exclusive" 219 self.parse_error(msg % child.tag.split('}')[-1]) 220 else: 221 child = self._parse_component(self.elem, required=False, strict=False) 222 if child is not None: 223 if child.tag == XSD_COMPLEX_TYPE: 224 self.type = self.schema.BUILDERS.complex_type_class(child, self.schema, self) 225 elif child.tag == XSD_SIMPLE_TYPE: 226 self.type = self.schema.BUILDERS.simple_type_factory(child, self.schema, self) 227 else: 228 self.type = self.maps.lookup_type(XSD_ANY_TYPE) 229 return 0 230 231 # Check value constraints 232 if 'default' in attrib and not self.type.is_valid(attrib['default']): 233 msg = "'default' value %r is not compatible with the type of the element" 234 self.parse_error(msg % attrib['default']) 235 elif 'fixed' in attrib and not self.type.is_valid(attrib['fixed']): 236 msg = "'fixed' value %r is not compatible with the type of the element" 237 self.parse_error(msg % attrib['fixed']) 238 239 return 1 240 else: 241 self.type = self.maps.lookup_type(XSD_ANY_TYPE) 242 return 0 243 244 # Check value constraints 245 if 'default' in attrib: 246 if not self.type.is_valid(attrib['default']): 247 msg = "'default' value {!r} is not compatible with the type {!r}" 248 self.parse_error(msg.format(attrib['default'], self.type)) 249 elif self.schema.XSD_VERSION == '1.0' and ( 250 self.type.name == XSD_ID or self.type.is_derived(self.schema.meta_schema.types['ID'])): 251 self.parse_error("'xs:ID' or a type derived from 'xs:ID' cannot has a 'default'") 252 elif 'fixed' in attrib: 253 if not self.type.is_valid(attrib['fixed']): 254 msg = "'fixed' value {!r} is not compatible with the type {!r}" 255 self.parse_error(msg.format(attrib['fixed'], self.type)) 256 elif self.schema.XSD_VERSION == '1.0' and ( 257 self.type.name == XSD_ID or self.type.is_derived(self.schema.meta_schema.types['ID'])): 258 self.parse_error("'xs:ID' or a type derived from 'xs:ID' cannot has a 'default'") 259 260 return 0
261
262 - def _parse_identity_constraints(self, index=0):
263 self.constraints = {} 264 for child in self._iterparse_components(self.elem, start=index): 265 if child.tag == XSD_UNIQUE: 266 constraint = XsdUnique(child, self.schema, self) 267 elif child.tag == XSD_KEY: 268 constraint = XsdKey(child, self.schema, self) 269 elif child.tag == XSD_KEYREF: 270 constraint = XsdKeyref(child, self.schema, self) 271 else: 272 continue # Error already caught by validation against the meta-schema 273 274 try: 275 if child != self.maps.constraints[constraint.name]: 276 self.parse_error("duplicated identity constraint %r:" % constraint.name, child) 277 except KeyError: 278 self.maps.constraints[constraint.name] = constraint 279 finally: 280 self.constraints[constraint.name] = constraint
281
283 substitution_group = self.elem.get('substitutionGroup') 284 if substitution_group is None: 285 return 286 287 try: 288 substitution_group_qname = self.schema.resolve_qname(substitution_group) 289 except ValueError as err: 290 self.parse_error(err) 291 return 292 else: 293 if substitution_group_qname[0] != '{': 294 substitution_group_qname = get_qname(self.target_namespace, substitution_group_qname) 295 296 try: 297 head_element = self.maps.lookup_element(substitution_group_qname) 298 except KeyError: 299 self.parse_error("unknown substitutionGroup %r" % substitution_group) 300 return 301 else: 302 if isinstance(head_element, tuple): 303 self.parse_error("circularity found for substitutionGroup %r" % substitution_group) 304 return 305 elif 'substitution' in head_element.block: 306 return 307 308 final = head_element.final 309 if self.type == head_element.type or self.type.name == XSD_ANY_TYPE: 310 pass 311 elif not self.type.is_derived(head_element.type): 312 msg = "%r type is not of the same or a derivation of the head element %r type." 313 self.parse_error(msg % (self, head_element)) 314 elif final == '#all' or 'extension' in final and 'restriction' in final: 315 msg = "head element %r can't be substituted by an element that has a derivation of its type" 316 self.parse_error(msg % head_element) 317 elif 'extension' in final and self.type.is_derived(head_element.type, 'extension'): 318 msg = "head element %r can't be substituted by an element that has an extension of its type" 319 self.parse_error(msg % head_element) 320 elif 'restriction' in final and self.type.is_derived(head_element.type, 'restriction'): 321 msg = "head element %r can't be substituted by an element that has a restriction of its type" 322 self.parse_error(msg % head_element) 323 324 if self.type.name == XSD_ANY_TYPE and 'type' not in self.elem.attrib: 325 self.type = self.maps.elements[substitution_group_qname].type 326 327 try: 328 self.maps.substitution_groups[substitution_group_qname].add(self) 329 except KeyError: 330 self.maps.substitution_groups[substitution_group_qname] = {self} 331 finally: 332 self._substitution_group = substitution_group_qname
333 334 @property
335 - def built(self):
336 return self.type.parent is None or self.type.built
337 338 @property
339 - def validation_attempted(self):
340 if self.built: 341 return 'full' 342 else: 343 return self.type.validation_attempted
344 345 # XSD declaration attributes 346 @property
347 - def ref(self):
348 return self.elem.get('ref')
349 350 # Global element's exclusive properties 351 @property
352 - def abstract(self):
353 return self._abstract if self._ref is None else self._ref.abstract
354 355 @property
356 - def final(self):
357 return self._final or self.schema.final_default if self._ref is None else self._ref.final
358 359 @property
360 - def block(self):
361 return self._block or self.schema.block_default if self._ref is None else self._ref.block
362 363 @property
364 - def substitution_group(self):
365 return self._substitution_group if self._ref is None else self._ref.substitution_group
366 367 @property
368 - def default(self):
369 return self.elem.get('default') if self._ref is None else self._ref.default
370 371 @property
372 - def fixed(self):
373 return self.elem.get('fixed') if self._ref is None else self._ref.fixed
374 375 @property
376 - def form(self):
377 return get_xsd_form_attribute(self.elem, 'form') if self._ref is None else self._ref.form
378 379 @property
380 - def nillable(self):
381 if self._ref is not None: 382 return self._ref.nillable 383 return get_xml_bool_attribute(self.elem, 'nillable', default=False)
384
385 - def get_attribute(self, name):
386 if name[0] != '{': 387 return self.type.attributes[get_qname(self.type.target_namespace, name)] 388 return self.type.attributes[name]
389
390 - def get_type(self, elem):
391 return self.type
392
393 - def get_path(self, ancestor=None, reverse=False):
394 """ 395 Returns the XPath expression of the element. The path is relative to the schema instance 396 in which the element is contained or is relative to a specific ancestor passed as argument. 397 In the latter case returns `None` if the argument is not an ancestor. 398 399 :param ancestor: optional XSD component of the same schema, that may be an ancestor of the element. 400 :param reverse: if set to `True` returns the reverse path, from the element to ancestor. 401 """ 402 path = [] 403 xsd_component = self 404 while xsd_component is not None: 405 if xsd_component is ancestor: 406 return '/'.join(reversed(path)) or '.' 407 elif hasattr(xsd_component, 'tag'): 408 path.append('..' if reverse else xsd_component.name) 409 xsd_component = xsd_component.parent 410 else: 411 if ancestor is None: 412 return '/'.join(reversed(path)) or '.'
413
414 - def iter_components(self, xsd_classes=None):
415 if xsd_classes is None: 416 yield self 417 for obj in self.constraints.values(): 418 yield obj 419 else: 420 if isinstance(self, xsd_classes): 421 yield self 422 for obj in self.constraints.values(): 423 if isinstance(obj, xsd_classes): 424 yield obj 425 426 if self.ref is None and self.type.parent is not None: 427 for obj in self.type.iter_components(xsd_classes): 428 yield obj
429
430 - def iter_substitutes(self):
431 for xsd_element in self.maps.substitution_groups.get(self.name, ()): 432 yield xsd_element 433 for e in xsd_element.iter_substitutes(): 434 yield e
435
436 - def iter_decode(self, elem, validation='lax', converter=None, **kwargs):
437 """ 438 Creates an iterator for decoding an Element instance. 439 440 :param elem: the Element that has to be decoded. 441 :param validation: the validation mode, can be 'lax', 'strict' or 'skip. 442 :param converter: an :class:`XMLSchemaConverter` subclass or instance. 443 :param kwargs: keyword arguments for the decoding process. 444 :return: yields a decoded object, eventually preceded by a sequence of \ 445 validation or decoding errors. 446 """ 447 if not isinstance(converter, XMLSchemaConverter): 448 converter = self.schema.get_converter(converter, **kwargs) 449 level = kwargs.pop('level', 0) 450 use_defaults = kwargs.get('use_defaults', False) 451 value = content = attributes = None 452 453 # Get the instance type: xsi:type or the schema's declaration 454 if XSI_TYPE not in elem.attrib: 455 xsd_type = self.get_type(elem) 456 else: 457 xsi_type = elem.attrib[XSI_TYPE] 458 try: 459 xsd_type = self.maps.lookup_type(converter.unmap_qname(xsi_type)) 460 except KeyError: 461 yield self.validation_error(validation, "unknown type %r" % xsi_type, elem, **kwargs) 462 xsd_type = self.get_type(elem) 463 464 # Decode attributes 465 attribute_group = getattr(xsd_type, 'attributes', self.attributes) 466 for result in attribute_group.iter_decode(elem.attrib, validation, **kwargs): 467 if isinstance(result, XMLSchemaValidationError): 468 yield self.validation_error(validation, result, elem, **kwargs) 469 else: 470 attributes = result 471 472 # Checks the xsi:nil attribute of the instance 473 if validation != 'skip' and XSI_NIL in elem.attrib: 474 if not self.nillable: 475 yield self.validation_error(validation, "element is not nillable.", elem, **kwargs) 476 try: 477 if get_xml_bool_attribute(elem, XSI_NIL): 478 if elem.text is not None: 479 reason = "xsi:nil='true' but the element is not empty." 480 yield self.validation_error(validation, reason, elem, **kwargs) 481 else: 482 element_data = ElementData(elem.tag, None, None, attributes) 483 yield converter.element_decode(element_data, self, level) 484 return 485 except TypeError: 486 reason = "xsi:nil attribute must has a boolean value." 487 yield self.validation_error(validation, reason, elem, **kwargs) 488 489 if xsd_type.is_simple(): 490 if len(elem) and validation != 'skip': 491 reason = "a simpleType element can't has child elements." 492 yield self.validation_error(validation, reason, elem, **kwargs) 493 494 text = elem.text 495 if self.fixed is not None: 496 if text is None: 497 text = self.fixed 498 elif text != self.fixed: 499 reason = "must has the fixed value %r." % self.fixed 500 yield self.validation_error(validation, reason, elem, **kwargs) 501 elif not text and use_defaults and self.default is not None: 502 text = self.default 503 504 if text is None: 505 for result in xsd_type.iter_decode('', validation, **kwargs): 506 if isinstance(result, XMLSchemaValidationError): 507 yield self.validation_error(validation, result, elem, **kwargs) 508 else: 509 for result in xsd_type.iter_decode(text, validation, **kwargs): 510 if isinstance(result, XMLSchemaValidationError): 511 yield self.validation_error(validation, result, elem, **kwargs) 512 else: 513 value = result 514 515 elif xsd_type.has_simple_content(): 516 if len(elem) and validation != 'skip': 517 reason = "a simple content element can't has child elements." 518 yield self.validation_error(validation, reason, elem, **kwargs) 519 520 if elem.text is not None: 521 text = elem.text or self.default if use_defaults else elem.text 522 for result in xsd_type.content_type.iter_decode(text, validation, **kwargs): 523 if isinstance(result, XMLSchemaValidationError): 524 yield self.validation_error(validation, result, elem, **kwargs) 525 else: 526 value = result 527 else: 528 for result in xsd_type.content_type.iter_decode(elem, validation, converter, level=level + 1, **kwargs): 529 if isinstance(result, XMLSchemaValidationError): 530 yield self.validation_error(validation, result, elem, **kwargs) 531 else: 532 content = result 533 534 if isinstance(value, Decimal): 535 try: 536 value = kwargs['decimal_type'](value) 537 except (KeyError, TypeError): 538 pass 539 elif isinstance(value, (AbstractDateTime, Duration)): 540 try: 541 if kwargs['datetime_types'] is not True: 542 value = elem.text 543 except KeyError: 544 value = elem.text 545 546 element_data = ElementData(elem.tag, value, content, attributes) 547 yield converter.element_decode(element_data, self, level) 548 if content is not None: 549 del content 550 551 if validation != 'skip': 552 for constraint in self.constraints.values(): 553 for error in constraint(elem): 554 yield self.validation_error(validation, error, elem, **kwargs)
555
556 - def iter_encode(self, obj, validation='lax', converter=None, **kwargs):
557 """ 558 Creates an iterator for encoding data to an Element. 559 560 :param obj: the data that has to be encoded. 561 :param validation: the validation mode: can be 'lax', 'strict' or 'skip'. 562 :param converter: an :class:`XMLSchemaConverter` subclass or instance. 563 :param kwargs: keyword arguments for the encoding process. 564 :return: yields an Element, eventually preceded by a sequence of \ 565 validation or encoding errors. 566 """ 567 if not isinstance(converter, XMLSchemaConverter): 568 converter = self.schema.get_converter(converter, **kwargs) 569 level = kwargs.pop('level', 0) 570 element_data = converter.element_encode(obj, self, level) 571 572 errors = [] 573 tag = element_data.tag 574 text = None 575 children = element_data.content 576 attributes = () 577 578 if element_data.attributes and XSI_TYPE in element_data.attributes: 579 xsi_type = element_data.attributes[XSI_TYPE] 580 try: 581 xsd_type = self.maps.lookup_type(converter.unmap_qname(xsi_type)) 582 except KeyError: 583 errors.append("unknown type %r" % xsi_type) 584 xsd_type = self.get_type(element_data) 585 else: 586 xsd_type = self.get_type(element_data) 587 588 attribute_group = getattr(xsd_type, 'attributes', self.attributes) 589 for result in attribute_group.iter_encode(element_data.attributes, validation, **kwargs): 590 if isinstance(result, XMLSchemaValidationError): 591 errors.append(result) 592 else: 593 attributes = result 594 595 if validation != 'skip' and XSI_NIL in element_data.attributes: 596 if not self.nillable: 597 errors.append("element is not nillable.") 598 xsi_nil = element_data.attributes[XSI_NIL] 599 if xsi_nil.strip() not in ('0', '1', 'true', 'false'): 600 errors.append("xsi:nil attribute must has a boolean value.") 601 if element_data.text is not None: 602 errors.append("xsi:nil='true' but the element is not empty.") 603 else: 604 elem = converter.etree_element(element_data.tag, attrib=attributes, level=level) 605 for e in errors: 606 yield self.validation_error(validation, e, elem, **kwargs) 607 yield elem 608 return 609 610 if xsd_type.is_simple(): 611 if element_data.content: 612 errors.append("a simpleType element can't has child elements.") 613 614 if element_data.text is None: 615 pass 616 else: 617 for result in xsd_type.iter_encode(element_data.text, validation, **kwargs): 618 if isinstance(result, XMLSchemaValidationError): 619 errors.append(result) 620 else: 621 text = result 622 623 elif xsd_type.has_simple_content(): 624 if element_data.text is not None: 625 for result in xsd_type.content_type.iter_encode(element_data.text, validation, **kwargs): 626 if isinstance(result, XMLSchemaValidationError): 627 errors.append(result) 628 else: 629 text = result 630 else: 631 for result in xsd_type.content_type.iter_encode( 632 element_data, validation, converter, level=level+1, **kwargs): 633 if isinstance(result, XMLSchemaValidationError): 634 errors.append(result) 635 elif result: 636 text, children = result 637 638 elem = converter.etree_element(tag, text, children, attributes, level) 639 640 if validation != 'skip' and errors: 641 for e in errors: 642 yield self.validation_error(validation, e, elem, **kwargs) 643 yield elem 644 del element_data
645
646 - def is_restriction(self, other, check_occurs=True):
647 if isinstance(other, XsdAnyElement): 648 if self.min_occurs == self.max_occurs == 0: 649 return True 650 if check_occurs and not self.has_occurs_restriction(other): 651 return False 652 return other.is_matching(self.name, self.default_namespace) 653 elif isinstance(other, XsdElement): 654 if self.name != other.name: 655 substitution_group = self.substitution_group 656 657 if other.name == self.substitution_group and other.min_occurs != other.max_occurs \ 658 and self.max_occurs != 0 and not other.abstract: 659 # Base is the head element, it's not abstract and has non deterministic occurs: this 660 # is less restrictive than W3C test group (elemZ026), marked as invalid despite it's 661 # based on an abstract declaration. 662 return False 663 elif self.substitution_group is None: 664 return False 665 elif not any(e.name == self.name for e in self.maps.substitution_groups[substitution_group]): 666 return False 667 668 if check_occurs and not self.has_occurs_restriction(other): 669 return False 670 elif self.type is not other.type and self.type.elem is not other.type.elem and \ 671 not self.type.is_derived(other.type, 'restriction') and not other.type.abstract: 672 return False 673 elif self.fixed != other.fixed and self.type.normalize(self.fixed) != other.type.normalize(other.fixed): 674 return False 675 elif other.nillable is False and self.nillable: 676 return False 677 elif any(value not in self.block for value in other.block.split()): 678 return False 679 elif not all(k in other.constraints for k in self.constraints): 680 return False 681 else: 682 return True 683 elif other.model == 'choice': 684 if other.is_empty() and self.max_occurs != 0: 685 return False 686 687 check_group_items_occurs = self.schema.XSD_VERSION == '1.0' 688 counter = ParticleCounter() 689 for e in other.iter_model(): 690 if not isinstance(e, (XsdElement, XsdAnyElement)): 691 return False 692 elif not self.is_restriction(e, check_group_items_occurs): 693 continue 694 counter += e 695 counter *= other 696 if self.has_occurs_restriction(counter): 697 return True 698 counter.reset() 699 return False 700 else: 701 match_restriction = False 702 for e in other.iter_model(): 703 if match_restriction: 704 if not e.is_emptiable(): 705 return False 706 elif self.is_restriction(e): 707 match_restriction = True 708 elif not e.is_emptiable(): 709 return False 710 return True
711
712 - def overlap(self, other):
713 if isinstance(other, XsdElement): 714 if self.name == other.name: 715 return True 716 elif other.substitution_group == self.name or other.name == self.substitution_group: 717 return True 718 elif isinstance(other, XsdAnyElement): 719 if other.is_matching(self.name, self.default_namespace): 720 return True 721 for e in self.maps.substitution_groups.get(self.name, ()): 722 if other.is_matching(e.name, self.default_namespace): 723 return True 724 return False
725
726 727 -class Xsd11Element(XsdElement):
728 """ 729 Class for XSD 1.1 'element' declarations. 730 731 <element 732 abstract = boolean : false 733 block = (#all | List of (extension | restriction | substitution)) 734 default = string 735 final = (#all | List of (extension | restriction)) 736 fixed = string 737 form = (qualified | unqualified) 738 id = ID 739 maxOccurs = (nonNegativeInteger | unbounded) : 1 740 minOccurs = nonNegativeInteger : 1 741 name = NCName 742 nillable = boolean : false 743 ref = QName 744 substitutionGroup = List of QName 745 targetNamespace = anyURI 746 type = QName 747 {any attributes with non-schema namespace . . .}> 748 Content: (annotation?, ((simpleType | complexType)?, alternative*, (unique | key | keyref)*)) 749 </element> 750 """
751 - def _parse(self):
752 XsdComponent._parse(self) 753 self._parse_attributes() 754 index = self._parse_type() 755 index = self._parse_alternatives(index) 756 self._parse_identity_constraints(index) 757 if self.parent is None: 758 self._parse_substitution_group() 759 self._parse_target_namespace()
760
761 - def _parse_alternatives(self, index=0):
762 if self._ref is not None: 763 self.alternatives = self._ref.alternatives 764 else: 765 self.alternatives = [] 766 for child in self._iterparse_components(self.elem, start=index): 767 if child.tag == XSD_ALTERNATIVE: 768 self.alternatives.append(XsdAlternative(child, self.schema, self)) 769 index += 1 770 else: 771 break 772 return index
773 774 @property
775 - def target_namespace(self):
776 try: 777 return self.elem.attrib['targetNamespace'] 778 except KeyError: 779 return self.schema.target_namespace
780
781 - def get_type(self, elem):
782 if not self.alternatives: 783 return self.type 784 785 if isinstance(elem, ElementData): 786 if elem.attributes: 787 attrib = {k: raw_xml_encode(v) for k, v in elem.attributes.items()} 788 elem = etree_element(elem.tag, attrib=attrib) 789 else: 790 elem = etree_element(elem.tag) 791 792 for alt in self.alternatives: 793 if alt.type is not None and boolean_value(list(alt.token.select(context=XPathContext(root=elem)))): 794 return alt.type 795 return self.type
796
797 - def overlap(self, other):
798 if isinstance(other, XsdElement): 799 if self.name == other.name: 800 return True 801 elif other.substitution_group == self.name or other.name == self.substitution_group: 802 return True 803 return False
804
805 806 -class XsdAlternative(XsdComponent):
807 """ 808 <alternative 809 id = ID 810 test = an XPath expression 811 type = QName 812 xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local)) 813 {any attributes with non-schema namespace . . .}> 814 Content: (annotation?, (simpleType | complexType)?) 815 </alternative> 816 """ 817 _admitted_tags = {XSD_ALTERNATIVE} 818 type = None 819
820 - def __repr__(self):
821 return '%s(type=%r, test=%r)' % (self.__class__.__name__, self.elem.get('type'), self.elem.get('test'))
822
823 - def _parse(self):
824 XsdComponent._parse(self) 825 attrib = self.elem.attrib 826 try: 827 self.path = attrib['test'] 828 except KeyError as err: 829 self.path = 'true()' 830 self.parse_error(err) 831 832 if 'xpathDefaultNamespace' in attrib: 833 self.xpath_default_namespace = self._parse_xpath_default_namespace(self.elem) 834 else: 835 self.xpath_default_namespace = self.schema.xpath_default_namespace 836 parser = XPath2Parser(self.namespaces, strict=False, default_namespace=self.xpath_default_namespace) 837 838 try: 839 self.token = parser.parse(self.path) 840 except ElementPathSyntaxError as err: 841 self.parse_error(err) 842 self.token = parser.parse('true()') 843 self.path = 'true()' 844 845 try: 846 type_qname = self.schema.resolve_qname(attrib['type']) 847 except KeyError: 848 self.parse_error("missing 'type' attribute") 849 except ValueError as err: 850 self.parse_error(err) 851 else: 852 try: 853 self.type = self.maps.lookup_type(type_qname) 854 except KeyError: 855 self.parse_error("unknown type %r" % attrib['type']) 856 else: 857 if not self.type.is_derived(self.parent.type): 858 self.parse_error("type %r ir not derived from %r" % (attrib['type'], self.parent.type))
859 860 @property
861 - def built(self):
862 raise NotImplementedError
863