Package xmlschema_acue ::
        Package validators ::
        Module attributes
      
  1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11  """ 
 12  This module contains classes for XML Schema attributes and attribute groups. 
 13  """ 
 14  from __future__ import unicode_literals 
 15  from decimal import Decimal 
 16  from elementpath.datatypes import AbstractDateTime, Duration 
 17   
 18  from xmlschema_acue.compat import MutableMapping, ordered_dict_class 
 19  from xmlschema_acue.exceptions import XMLSchemaAttributeError, XMLSchemaTypeError, XMLSchemaValueError 
 20  from xmlschema_acue.qnames import XSD_ANY_SIMPLE_TYPE, XSD_SIMPLE_TYPE, XSD_ATTRIBUTE_GROUP, XSD_COMPLEX_TYPE, \ 
 21      XSD_RESTRICTION, XSD_EXTENSION, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE, XSD_ATTRIBUTE, XSD_ANY_ATTRIBUTE 
 22  from xmlschema_acue.helpers import get_namespace, get_qname, get_xsd_form_attribute 
 23  from xmlschema_acue.namespaces import XSI_NAMESPACE 
 24   
 25  from xmlschema_acue.validators.exceptions import XMLSchemaValidationError 
 26  from xmlschema_acue.validators.xsdbase import XsdComponent, ValidationMixin 
 27  from xmlschema_acue.validators.simple_types import XsdSimpleType 
 28  from xmlschema_acue.validators.wildcards import XsdAnyAttribute 
 32      """ 
 33      Class for XSD 1.0 'attribute' declarations. 
 34   
 35      <attribute 
 36        default = string 
 37        fixed = string 
 38        form = (qualified | unqualified) 
 39        id = ID 
 40        name = NCName 
 41        ref = QName 
 42        type = QName 
 43        use = (optional | prohibited | required) : optional 
 44        {any attributes with non-schema namespace ...}> 
 45        Content: (annotation?, simpleType?) 
 46      </attribute> 
 47      """ 
 48      _admitted_tags = {XSD_ATTRIBUTE} 
 49      qualified = False 
 50   
 51 -    def __init__(self, elem, schema, parent, name=None, xsd_type=None): 
  58   
 60          if self.ref is None: 
 61              return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name) 
 62          else: 
 63              return '%s(ref=%r)' % (self.__class__.__name__, self.prefixed_name) 
  64   
 70   
 72          super(XsdAttribute, self)._parse() 
 73          elem = self.elem 
 74   
 75          try: 
 76              form = self.form 
 77          except ValueError as err: 
 78              self.parse_error(err) 
 79          else: 
 80              if form is None: 
 81                  self.qualified = self.schema.attribute_form_default == 'qualified' 
 82              elif self.parent is None: 
 83                  self.parse_error("attribute 'form' not allowed in a global attribute.") 
 84              else: 
 85                  self.qualified = form == 'qualified' 
 86   
 87          self.use = elem.get('use') 
 88          if self.use is None: 
 89              self.use = 'optional' 
 90          elif self.parent is None: 
 91              self.parse_error("attribute 'use' not allowed in a global attribute.") 
 92          elif self.use not in {'optional', 'prohibited', 'required'}: 
 93              self.parse_error("wrong value %r for 'use' attribute." % self.use) 
 94              self.use = 'optional' 
 95   
 96          name = elem.get('name') 
 97          if name is not None: 
 98              if 'ref' in elem.attrib: 
 99                  self.parse_error("both 'name' and 'ref' in attribute declaration") 
100              elif name == 'xmlns': 
101                  self.parse_error("an attribute name must be different from 'xmlns'") 
102   
103              if self.parent is None or self.qualified: 
104                  if self.target_namespace == XSI_NAMESPACE and \ 
105                          name not in {'nil', 'type', 'schemaLocation', 'noNamespaceSchemaLocation'}: 
106                      self.parse_error("Cannot add attributes in %r namespace" % XSI_NAMESPACE) 
107                  self.name = get_qname(self.target_namespace, name) 
108              else: 
109                  self.name = name 
110          elif self.parent is None: 
111              self.parse_error("missing 'name' in global attribute declaration") 
112          else: 
113              try: 
114                  attribute_qname = self.schema.resolve_qname(elem.attrib['ref']) 
115              except KeyError: 
116                  self.parse_error("missing both 'name' and 'ref' in attribute declaration") 
117                  self.xsd_type = self.maps.lookup_type(XSD_ANY_SIMPLE_TYPE) 
118                  return 
119              except ValueError as err: 
120                  self.parse_error(err) 
121                  self.xsd_type = self.maps.lookup_type(XSD_ANY_SIMPLE_TYPE) 
122                  return 
123              else: 
124                  try: 
125                      xsd_attribute = self.maps.lookup_attribute(attribute_qname) 
126                  except LookupError: 
127                      self.parse_error("unknown attribute %r" % elem.attrib['ref']) 
128                      self.type = self.maps.lookup_type(XSD_ANY_SIMPLE_TYPE) 
129                  else: 
130                      self.type = xsd_attribute.type 
131                      self.qualified = xsd_attribute.qualified 
132                      if xsd_attribute.fixed is not None and 'fixed' in elem.attrib and \ 
133                              elem.get('fixed') != xsd_attribute.fixed: 
134                          self.parse_error("referenced attribute has a different fixed value %r" % xsd_attribute.fixed) 
135   
136                  self.name = attribute_qname 
137                  for attribute in ('form', 'type'): 
138                      if attribute in self.elem.attrib: 
139                          self.parse_error("attribute %r is not allowed when attribute reference is used." % attribute) 
140                  xsd_declaration = self._parse_component(elem, required=False) 
141   
142                  if xsd_declaration is not None and xsd_declaration.tag == XSD_SIMPLE_TYPE: 
143                      self.parse_error("not allowed type declaration for XSD attribute reference") 
144                  return 
145   
146          xsd_declaration = self._parse_component(elem, required=False) 
147          try: 
148              type_qname = self.schema.resolve_qname(elem.attrib['type']) 
149          except ValueError as err: 
150              self.parse_error(err, elem) 
151              xsd_type = self.maps.lookup_type(XSD_ANY_SIMPLE_TYPE) 
152          except KeyError: 
153              if xsd_declaration is not None: 
154                   
155                  xsd_type = self.schema.BUILDERS.simple_type_factory(xsd_declaration, self.schema, self) 
156              else: 
157                   
158                  xsd_type = self.maps.lookup_type(XSD_ANY_SIMPLE_TYPE) 
159          else: 
160              try: 
161                  xsd_type = self.maps.lookup_type(type_qname) 
162              except LookupError as err: 
163                  self.parse_error(err, elem) 
164                  xsd_type = self.maps.lookup_type(XSD_ANY_SIMPLE_TYPE) 
165   
166              if xsd_declaration is not None and xsd_declaration.tag == XSD_SIMPLE_TYPE: 
167                  self.parse_error("ambiguous type declaration for XSD attribute") 
168              elif xsd_declaration: 
169                  self.parse_error("not allowed element in XSD attribute declaration: %r" % xsd_declaration[0]) 
170   
171          try: 
172              self.type = xsd_type 
173          except TypeError as err: 
174              self.parse_error(err) 
175   
176           
177          if 'default' in elem.attrib: 
178              if 'fixed' in elem.attrib: 
179                  self.parse_error("'default' and 'fixed' attributes are mutually exclusive") 
180              if self.use != 'optional': 
181                  self.parse_error("the attribute 'use' must be 'optional' if the attribute 'default' is present") 
182              if not self.type.is_valid(elem.attrib['default']): 
183                  msg = "'default' value {!r} is not compatible with the type {!r}" 
184                  self.parse_error(msg.format(elem.attrib['default'], self.type)) 
185              elif self.type.is_key(): 
186                  self.parse_error("'xs:ID' or a type derived from 'xs:ID' cannot has a 'default'") 
187          elif 'fixed' in elem.attrib: 
188              if not self.type.is_valid(elem.attrib['fixed']): 
189                  msg = "'fixed' value {!r} is not compatible with the type {!r}" 
190                  self.parse_error(msg.format(elem.attrib['fixed'], self.type)) 
191              elif self.type.is_key(): 
192                  self.parse_error("'xs:ID' or a type derived from 'xs:ID' cannot has a 'default'") 
 193   
194      @property 
197   
198      @property 
204   
205       
206      @property 
208          return self.elem.get('ref') 
 209   
210      @property 
212          return self.elem.get('default') 
 213   
214      @property 
216          return self.elem.get('fixed') 
 217   
218      @property 
221   
223          return self.use == 'optional' 
 224   
226          if xsd_classes is None or isinstance(self, xsd_classes): 
227              yield self 
228          if self.ref is None and self.type.parent is not None: 
229              for obj in self.type.iter_components(xsd_classes): 
230                  yield obj 
 231   
232 -    def iter_decode(self, text, validation='lax', **kwargs): 
 233          if not text and kwargs.get('use_defaults', True) and self.default is not None: 
234              text = self.default 
235          if self.fixed is not None and text != self.fixed and validation != 'skip': 
236              yield self.validation_error(validation, "value differs from fixed value", text, **kwargs) 
237   
238          for result in self.type.iter_decode(text, validation, **kwargs): 
239              if isinstance(result, XMLSchemaValidationError): 
240                  yield result 
241              elif isinstance(result, Decimal): 
242                  try: 
243                      yield kwargs['decimal_type'](result) 
244                  except (KeyError, TypeError): 
245                      yield result 
246                  break 
247              elif isinstance(result, (AbstractDateTime, Duration)): 
248                  try: 
249                      yield result if kwargs['datetime_types'] is True else text 
250                  except KeyError: 
251                      yield text 
252              else: 
253                  yield result 
254                  break 
 255   
256 -    def iter_encode(self, obj, validation='lax', **kwargs): 
  261   
264      """ 
265      Class for XSD 1.1 'attribute' declarations. 
266   
267      <attribute 
268        default = string 
269        fixed = string 
270        form = (qualified | unqualified) 
271        id = ID 
272        name = NCName 
273        ref = QName 
274        targetNamespace = anyURI 
275        type = QName 
276        use = (optional | prohibited | required) : optional 
277        inheritable = boolean 
278        {any attributes with non-schema namespace . . .}> 
279        Content: (annotation?, simpleType?) 
280      </attribute> 
281      """ 
282      @property 
284          return self.elem.get('inheritable') in ('0', 'true') 
 285   
286      @property 
289   
291          super(Xsd11Attribute, self)._parse() 
292          if not self.elem.get('inheritable') not in {'0', '1', 'false', 'true'}: 
293              self.parse_error("an XML boolean value is required for attribute 'inheritable'") 
294          self._parse_target_namespace() 
  295   
298      """ 
299      Class for XSD 'attributeGroup' definitions. 
300       
301      <attributeGroup 
302        id = ID 
303        name = NCName 
304        ref = QName 
305        {any attributes with non-schema namespace . . .}> 
306        Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?)) 
307      </attributeGroup> 
308      """ 
309      redefine = None 
310      _admitted_tags = { 
311          XSD_ATTRIBUTE_GROUP, XSD_COMPLEX_TYPE, XSD_RESTRICTION, XSD_EXTENSION, 
312          XSD_SEQUENCE, XSD_ALL, XSD_CHOICE, XSD_ATTRIBUTE, XSD_ANY_ATTRIBUTE 
313      } 
314   
315 -    def __init__(self, elem, schema, parent, name=None, derivation=None, base_attributes=None): 
 320   
322          if self.ref is not None: 
323              return '%s(ref=%r)' % (self.__class__.__name__, self.prefixed_name) 
324          elif self.name is not None: 
325              return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name) 
326          elif self: 
327              names = [a if a.name is None else a.prefixed_name for a in self.values()] 
328              return '%s(%r)' % (self.__class__.__name__, names) 
329          else: 
330              return '%s()' % self.__class__.__name__ 
 331   
332       
334          return self._attribute_group[key] 
 335   
352   
354          del self._attribute_group[key] 
 355   
357          if None in self._attribute_group: 
358               
359              return iter(sorted(self._attribute_group, key=lambda x: (x is None, x))) 
360          else: 
361              return iter(self._attribute_group) 
 362   
364          return len(self._attribute_group) 
 365   
366       
368          super(XsdAttributeGroup, self).__setattr__(name, value) 
369          if name == '_attribute_group': 
370              assert isinstance(value, dict), 'A dictionary object is required.' 
371              for k, v in value.items(): 
372                  if k is None: 
373                      assert isinstance(value, XsdAnyAttribute), 'An XsdAnyAttribute instance is required.' 
374                  else: 
375                      assert isinstance(value, XsdAttribute), 'An XsdAttribute instance is required.' 
 376   
378          super(XsdAttributeGroup, self)._parse() 
379          elem = self.elem 
380          any_attribute = False 
381          attribute_group_refs = [] 
382   
383          if elem.tag == XSD_ATTRIBUTE_GROUP: 
384              if self.parent is not None: 
385                  return   
386              try: 
387                  self.name = get_qname(self.target_namespace, self.elem.attrib['name']) 
388              except KeyError: 
389                  self.parse_error("an attribute group declaration requires a 'name' attribute.") 
390                  return 
391   
392          attributes = ordered_dict_class() 
393          for child in self._iterparse_components(elem): 
394              if any_attribute: 
395                  if child.tag == XSD_ANY_ATTRIBUTE: 
396                      self.parse_error("more anyAttribute declarations in the same attribute group") 
397                  else: 
398                      self.parse_error("another declaration after anyAttribute") 
399   
400              elif child.tag == XSD_ANY_ATTRIBUTE: 
401                  any_attribute = True 
402                  attributes.update([(None, XsdAnyAttribute(child, self.schema, self))]) 
403   
404              elif child.tag == XSD_ATTRIBUTE: 
405                  attribute = self.schema.BUILDERS.attribute_class(child, self.schema, self) 
406                  if attribute.name in attributes: 
407                      self.parse_error("multiple declaration for attribute {!r}".format(attribute.name)) 
408                  else: 
409                      attributes[attribute.name] = attribute 
410   
411              elif child.tag == XSD_ATTRIBUTE_GROUP: 
412                  try: 
413                      ref = child.attrib['ref'] 
414                      attribute_group_qname = self.schema.resolve_qname(ref) 
415                  except ValueError as err: 
416                      self.parse_error(err, elem) 
417                  except KeyError: 
418                      self.parse_error("the attribute 'ref' is required in a local attributeGroup", elem) 
419                  else: 
420                      if attribute_group_qname in attribute_group_refs: 
421                          self.parse_error("duplicated attributeGroup %r" % ref) 
422                      elif self.redefine is not None: 
423                          if attribute_group_qname == self.name: 
424                              if attribute_group_refs: 
425                                  self.parse_error("in a redefinition the reference to itself must be the first") 
426                              attribute_group_refs.append(attribute_group_qname) 
427                              attributes.update(self._attribute_group.items()) 
428                              continue 
429                          elif not attribute_group_refs: 
430                               
431                              if not any(e.tag == XSD_ATTRIBUTE_GROUP and ref == e.get('ref') 
432                                         for e in self.redefine.elem): 
433                                  self.parse_error("attributeGroup ref=%r is not in the redefined group" % ref) 
434                      elif attribute_group_qname == self.name and self.schema.XSD_VERSION == '1.0': 
435                          self.parse_error("Circular attribute groups not allowed in XSD 1.0") 
436                      attribute_group_refs.append(attribute_group_qname) 
437   
438                      try: 
439                          base_attributes = self.maps.lookup_attribute_group(attribute_group_qname) 
440                      except LookupError: 
441                          self.parse_error("unknown attribute group %r" % child.attrib['ref'], elem) 
442                      else: 
443                          if isinstance(base_attributes, tuple): 
444                              self.parse_error("Circular reference found between attribute groups " 
445                                               "{!r} and {!r}".format(self.name, attribute_group_qname)) 
446   
447                          for name, attr in base_attributes.items(): 
448                              if name is not None and name in attributes: 
449                                  self.parse_error("multiple declaration for attribute {!r}".format(name)) 
450                              else: 
451                                  attributes[name] = attr 
452   
453              elif self.name is not None: 
454                  self.parse_error("(attribute | attributeGroup) expected, found %r." % child) 
455   
456           
457          if self.base_attributes is not None: 
458              wildcard = self.base_attributes.get(None) 
459              for name, attr in attributes.items(): 
460                  if name not in self.base_attributes: 
461                      if self.derivation != 'restriction': 
462                          continue 
463                      elif wildcard is None or not wildcard.is_matching(name, self.default_namespace): 
464                          self.parse_error("Unexpected attribute %r in restriction" % name) 
465                      continue 
466   
467                  base_attr = self.base_attributes[name] 
468   
469                  if name is None: 
470                      if self.derivation == 'extension': 
471                          try: 
472                              attr.extend_namespace(base_attr) 
473                          except ValueError as err: 
474                              self.parse_error(err) 
475                      elif not attr.is_restriction(base_attr): 
476                          self.parse_error("Attribute wildcard is not a restriction of the base wildcard") 
477                      continue 
478                  if self.derivation == 'restriction' and attr.type.name != XSD_ANY_SIMPLE_TYPE and \ 
479                          not attr.type.is_derived(base_attr.type, 'restriction'): 
480                      self.parse_error("Attribute type is not a restriction of the base attribute type") 
481                  if base_attr.use != 'optional' and attr.use == 'optional' or \ 
482                          base_attr.use == 'required' and attr.use != 'required': 
483                      self.parse_error("Attribute %r: unmatched attribute use in restriction" % name) 
484                  if base_attr.fixed is not None and \ 
485                          attr.type.normalize(attr.fixed) != base_attr.type.normalize(base_attr.fixed): 
486                      self.parse_error("Attribute %r: derived attribute has a different fixed value" % name) 
487   
488              self._attribute_group.update(self.base_attributes.items()) 
489          elif self.redefine is not None and not attribute_group_refs: 
490              for name, attr in self._attribute_group.items(): 
491                  if name is None: 
492                      continue 
493                  elif name not in attributes: 
494                      if attr.use == 'required': 
495                          self.parse_error("Missing required attribute %r in redefinition restriction" % name) 
496                      continue 
497                  if attr.use != 'optional' and attributes[name].use != attr.use: 
498                      self.parse_error("Attribute %r: unmatched attribute use in redefinition" % name) 
499                  if attr.fixed is not None and attributes[name].fixed is None: 
500                      self.parse_error("Attribute %r: redefinition remove fixed constraint" % name) 
501   
502              pos = 0 
503              keys = list(self._attribute_group.keys()) 
504              for name in attributes: 
505                  try: 
506                      next_pos = keys.index(name) 
507                  except ValueError: 
508                      self.parse_error("Redefinition restriction contains additional attribute %r" % name) 
509                  else: 
510                      if next_pos < pos: 
511                          self.parse_error("Wrong attribute order in redefinition restriction") 
512                          break 
513                      pos = next_pos 
514              self.clear() 
515   
516          self._attribute_group.update(attributes) 
517   
518          if self.schema.XSD_VERSION == '1.0': 
519              has_key = False 
520              for attr in self._attribute_group.values(): 
521                  if attr.name is not None and attr.type.is_key(): 
522                      if has_key: 
523                          self.parse_error("multiple key attributes in a group not allowed in XSD 1.0") 
524                      has_key = True 
525   
526          elif self.parent is None and self.schema.default_attributes == self.name: 
527              self.schema.default_attributes = self 
 528   
529      @property 
531          return all([attr.built for attr in self.values()]) 
 532   
533      @property 
535          if self.built: 
536              return 'full' 
537          elif any([attr.validation_attempted == 'partial' for attr in self.values()]): 
538              return 'partial' 
539          else: 
540              return 'none' 
 541   
542      @property 
544          return self.elem.get('ref') 
 545   
547          for k, v in self._attribute_group.items(): 
548              if k is not None and v.use == 'required': 
549                  yield k 
 550   
552          if xsd_classes is None or isinstance(self, xsd_classes): 
553              yield self 
554          if self.ref is None: 
555              for attr in self.values(): 
556                  if attr.parent is not None: 
557                      for obj in attr.iter_components(xsd_classes): 
558                          yield obj 
 559   
560 -    def iter_decode(self, attrs, validation='lax', **kwargs): 
 561          if not attrs and not self: 
562              return 
563   
564          result_list = [] 
565          required_attributes = {a for a in self.iter_required()} 
566          for name, value in attrs.items(): 
567              try: 
568                  xsd_attribute = self[name] 
569              except KeyError: 
570                  if get_namespace(name) == XSI_NAMESPACE: 
571                      try: 
572                          xsd_attribute = self.maps.lookup_attribute(name) 
573                      except LookupError: 
574                          if validation != 'skip': 
575                              reason = "%r is not an attribute of the XSI namespace." % name 
576                              yield self.validation_error(validation, reason, attrs, **kwargs) 
577                          continue 
578                  else: 
579                      try: 
580                          xsd_attribute = self[None]   
581                          value = (name, value) 
582                      except KeyError: 
583                          if validation != 'skip': 
584                              reason = "%r attribute not allowed for element." % name 
585                              yield self.validation_error(validation, reason, attrs, **kwargs) 
586                          continue 
587              else: 
588                  required_attributes.discard(name) 
589   
590              for result in xsd_attribute.iter_decode(value, validation, **kwargs): 
591                  if isinstance(result, XMLSchemaValidationError): 
592                      yield result 
593                  else: 
594                      result_list.append((name, result)) 
595                      break 
596   
597          if required_attributes and validation != 'skip': 
598              reason = "missing required attributes: %r" % required_attributes 
599              yield self.validation_error(validation, reason, attrs, **kwargs) 
600   
601          yield result_list 
 602   
603 -    def iter_encode(self, attrs, validation='lax', **kwargs): 
 604          result_list = [] 
605          required_attributes = {a for a in self.iter_required()} 
606          try: 
607              attrs = attrs.items() 
608          except AttributeError: 
609              pass 
610   
611          for name, value in attrs: 
612              try: 
613                  xsd_attribute = self[name] 
614              except KeyError: 
615                  namespace = get_namespace(name) or self.target_namespace 
616                  if namespace == XSI_NAMESPACE: 
617                      try: 
618                          xsd_attribute = self.maps.lookup_attribute(name) 
619                      except LookupError: 
620                          if validation != 'skip': 
621                              reason = "%r is not an attribute of the XSI namespace." % name 
622                              yield self.validation_error(validation, reason, attrs, **kwargs) 
623                          continue 
624                  else: 
625                      try: 
626                          xsd_attribute = self[None]   
627                          value = (name, value) 
628                      except KeyError: 
629                          if validation != 'skip': 
630                              reason = "%r attribute not allowed for element." % name 
631                              yield self.validation_error(validation, reason, attrs, **kwargs) 
632                          continue 
633              else: 
634                  required_attributes.discard(name) 
635   
636              for result in xsd_attribute.iter_encode(value, validation, **kwargs): 
637                  if isinstance(result, XMLSchemaValidationError): 
638                      yield result 
639                  else: 
640                      result_list.append((name, result)) 
641                      break 
642   
643          if required_attributes and validation != 'skip': 
644              reason = "missing required attributes %r" % required_attributes 
645              yield self.validation_error(validation, reason, attrs, **kwargs) 
646          yield result_list 
  647