1# -*- coding: utf-8 -*-
2# Copyright 2009-2013, Peter A. Bigot
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain a
6# copy of the License at:
7#
8#            http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""This module contains support classes from which schema-specific bindings
17inherit, and that describe the content models of those schema."""
18
19import logging
20import collections
21import xml.dom
22import pyxb
23from pyxb.utils import domutils, utility, six
24import pyxb.namespace
25from pyxb.namespace.builtin import XMLSchema_instance as XSI
26import decimal
27
28_log = logging.getLogger(__name__)
29
30class _TypeBinding_mixin (utility.Locatable_mixin):
31    # Private member holding the validation configuration that applies to the
32    # class or instance.  Can't really make it private with __ prefix because
33    # that would screw up parent classes.  You end users---stay away from
34    # this.
35    _validationConfig_ = pyxb.GlobalValidationConfig
36
37    @classmethod
38    def _SetValidationConfig (cls, validation_config):
39        """Set the validation configuration for this class."""
40        cls._validationConfig_ = validation_config
41
42    @classmethod
43    def _GetValidationConfig (cls):
44        """The L{pyxb.ValidationConfig} instance that applies to this class.
45
46        By default this will reference L{pyxb.GlobalValidationConfig}."""
47        return cls._validationConfig_
48
49    def _setValidationConfig (self, validation_config):
50        """Set the validation configuration for this instance."""
51        self._validationConfig_ = validation_config
52
53    def __getValidationConfig (self):
54        """The L{pyxb.ValidationConfig} instance that applies to this instance.
55
56        By default this will reference the class value from
57        L{_GetValidationConfig}, which defaults to
58        L{pyxb.GlobalValidationConfig}."""
59        return self._validationConfig_
60
61    # This is how you should be accessing this value.
62    _validationConfig = property(__getValidationConfig)
63
64    @classmethod
65    def _PerformValidation (cls):
66        """Determine whether the content model should be validated for this class.
67
68        In the absence of context, this returns C{True} iff both binding and
69        document validation are in force.
70
71        @deprecated: use L{_GetValidationConfig} and check specific requirements."""
72        # Bypass the property since this is a class method
73        vo = cls._validationConfig_
74        return vo.forBinding and vo.forDocument
75
76    def _performValidation (self):
77        """Determine whether the content model should be validated for this
78        instance.
79
80        In the absence of context, this returns C{True} iff both binding and
81        document validation are in force.
82
83        @deprecated: use L{_validationConfig} and check specific requirements."""
84        vo = self._validationConfig
85        return vo.forBinding and vo.forDocument
86
87    _ExpandedName = None
88    """The expanded name of the component."""
89
90    _XSDLocation = None
91    """Where the definition can be found in the originating schema."""
92
93    _ReservedSymbols = set([ 'validateBinding', 'toDOM', 'toxml', 'Factory', 'property' ])
94
95    if pyxb._CorruptionDetectionEnabled:
96        def __setattr__ (self, name, value):
97            if name in self._ReservedSymbols:
98                raise pyxb.ReservedNameError(self, name)
99            return super(_TypeBinding_mixin, self).__setattr__(name, value)
100
101    _PyXBFactoryKeywords = ( '_dom_node', '_fallback_namespace', '_from_xml',
102                             '_apply_whitespace_facet', '_validate_constraints',
103                             '_require_value', '_nil', '_element', '_apply_attributes',
104                             '_convert_string_values', '_location' )
105    """Keywords that are interpreted by __new__ or __init__ in one or more
106    classes in the PyXB type hierarchy.  All these keywords must be removed
107    before invoking base Python __init__ or __new__."""
108
109    # While simple type definitions cannot be abstract, they can appear in
110    # many places where complex types can, so we want it to be legal to test
111    # for abstractness without checking whether the object is a complex type.
112    _Abstract = False
113
114    def _namespaceContext (self):
115        """Return a L{namespace context <pyxb.binding.NamespaceContext>}
116        associated with the binding instance.
117
118        This will return C{None} unless something has provided a context to
119        the instance.  Context is provided when instances are generated by the
120        DOM and SAX-based translators."""
121        return self.__namespaceContext
122    def _setNamespaceContext (self, namespace_context):
123        """Associate a L{namespace context <pyxb.binding.NamespaceContext>}
124        with the binding instance."""
125        self.__namespaceContext = namespace_context
126        return self
127    __namespaceContext = None
128
129    def _setElement (self, elt):
130        """Associate an element binding with the instance.
131
132        Since the value of a binding instance reflects only its content, an
133        associated element is necessary to generate an XML document or DOM
134        tree.
135
136        @param elt: the L{pyxb.binding.basis.element} instance associated with
137        the value.  This may be C{None} when disassociating a value from a
138        specific element."""
139        import pyxb.binding.content
140        assert (elt is None) or isinstance(elt, element)
141        self.__element = elt
142        return self
143    def _element (self):
144        """Return a L{pyxb.binding.basis.element} associated with the binding
145        instance.
146
147        This will return C{None} unless an element has been associated.
148        Constructing a binding instance using the element instance will add
149        this association.
150        """
151        return self.__element
152    __element = None
153
154    __xsiNil = None
155    def _isNil (self):
156        """Indicate whether this instance is U{nil
157        <http://www.w3.org/TR/xmlschema-1/#xsi_nil>}.
158
159        The value is set by the DOM and SAX parsers when building an instance
160        from a DOM element with U{xsi:nil
161        <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set to C{true}.
162
163        @return: C{None} if the element used to create the instance is not
164        U{nillable<http://www.w3.org/TR/xmlschema-1/#nillable>}.
165        If it is nillable, returns C{True} or C{False} depending on
166        whether the instance itself is U{nil<http://www.w3.org/TR/xmlschema-1/#xsi_nil>}.
167        """
168        return self.__xsiNil
169    def _setIsNil (self, nil=True):
170        """Set the xsi:nil property of the instance.
171
172        @param nil: C{True} if the value of xsi:nil should be C{true},
173        C{False} if the value of xsi:nil should be C{false}.
174
175        @raise pyxb.NoNillableSupportError: the instance is not associated
176        with an element that is L{nillable
177        <pyxb.binding.basis.element.nillable>}.
178        """
179        if self.__xsiNil is None:
180            raise pyxb.NoNillableSupportError(self)
181        self.__xsiNil = not not nil
182        if self.__xsiNil:
183            # The element must be empty, so also remove all element content.
184            # Attribute values are left unchanged.
185            self._resetContent(reset_elements=True)
186
187    def _resetContent (self, reset_elements=False):
188        """Reset the content of an element value.
189
190        This is not a public method.
191
192        For simple types, this does nothing. For complex types, this clears the
193        L{content<complexTypeDefinition.content>} array, removing all
194        non-element content from the instance.  It optionally also removes all
195        element content.
196
197        @param reset_elements: If C{False} (default) only the content array is
198        cleared, which has the effect of removing any preference for element
199        order when generating a document.  If C{True}, the element content
200        stored within the binding is also cleared, leaving it with no content
201        at all.
202
203        @note: This is not the same thing as L{complexTypeDefinition.reset},
204        which unconditionally resets attributes and element and non-element
205        content.
206        """
207        pass
208
209    __constructedWithValue = False
210    def __checkNilCtor (self, args):
211        self.__constructedWithValue = (0 < len(args))
212        if self.__xsiNil:
213            if self.__constructedWithValue:
214                raise pyxb.ContentInNilInstanceError(self, args[0])
215        else:
216            # Types that descend from string will, when constructed from an
217            # element with empty content, appear to have no constructor value,
218            # while in fact an empty string should have been passed.
219            if issubclass(type(self), six.string_types):
220                self.__constructedWithValue = True
221    def _constructedWithValue (self):
222        return self.__constructedWithValue
223
224    # Flag used to control whether we print a warning when creating a complex
225    # type instance that does not have an associated element.  Not sure yet
226    # whether that'll be common practice or common error.
227    __WarnedUnassociatedElement = False
228
229    def __init__ (self, *args, **kw):
230        # Strip keyword not used above this level.
231        element = kw.pop('_element', None)
232        is_nil = kw.pop('_nil', False)
233        super(_TypeBinding_mixin, self).__init__(*args, **kw)
234        if (element is None) or element.nillable():
235            self.__xsiNil = is_nil
236        if element is not None:
237            self._setElement(element)
238        self.__checkNilCtor(args)
239
240    @classmethod
241    def _PreFactory_vx (cls, args, kw):
242        """Method invoked upon entry to the Factory method.
243
244        This method is entitled to modify the keywords array.  It can also
245        return a state value which is passed to _postFactory_vx."""
246        return None
247
248    def _postFactory_vx (cls, state):
249        """Method invoked prior to leaving the Factory method.
250
251        This is an instance method, and is given the state that was returned
252        by _PreFactory_vx."""
253        return None
254
255    @classmethod
256    def Factory (cls, *args, **kw):
257        """Provide a common mechanism to create new instances of this type.
258
259        The class constructor won't do, because you can't create
260        instances of union types.
261
262        This method may be overridden in subclasses (like STD_union).  Pre-
263        and post-creation actions can be customized on a per-class instance by
264        overriding the L{_PreFactory_vx} and L{_postFactory_vx} methods.
265
266        @keyword _dom_node: If provided, the value must be a DOM node, the
267        content of which will be used to set the value of the instance.
268
269        @keyword _location: An optional instance of
270        L{pyxb.utils.utility.Location} showing the origin the binding.  If
271        C{None}, a value from C{_dom_node} is used if available.
272
273        @keyword _from_xml: If C{True}, the input must be either a DOM node or
274        a unicode string comprising a lexical representation of a value.  This
275        is a further control on C{_apply_whitespace_facet} and arises from
276        cases where the lexical and value representations cannot be
277        distinguished by type.  The default value is C{True} iff C{_dom_node}
278        is not C{None}.
279
280        @keyword _apply_whitespace_facet: If C{True} and this is a
281        simpleTypeDefinition with a whiteSpace facet, the first argument will
282        be normalized in accordance with that facet prior to invoking the
283        parent constructor.  The value is always C{True} if text content is
284        extracted from a C{_dom_node}, and otherwise defaults to the defaulted
285        value of C{_from_xml}.
286
287        @keyword _validate_constraints: If C{True}, any constructed value is
288        checked against constraints applied to the union as well as the member
289        type.
290
291        @keyword _require_value: If C{False} (default), it is permitted to
292        create a value without an initial value.  If C{True} and no initial
293        value was provided, causes L{pyxb.SimpleContentAbsentError} to be raised.
294        Only applies to simpleTypeDefinition instances; this is used when
295        creating values from DOM nodes.
296        """
297        # Invoke _PreFactory_vx for the superseding class, which is where
298        # customizations will be found.
299        dom_node = kw.get('_dom_node')
300        location = kw.get('_location')
301        if (location is None) and isinstance(dom_node, utility.Locatable_mixin):
302            location = dom_node._location()
303        kw.setdefault('_from_xml', dom_node is not None)
304        used_cls = cls._SupersedingClass()
305        state = used_cls._PreFactory_vx(args, kw)
306        rv = cls._DynamicCreate(*args, **kw)
307        rv._postFactory_vx(state)
308        if (rv._location is None) and (location is not None):
309            rv._setLocation(location)
310        return rv
311
312    def _substitutesFor (self, element):
313        if (element is None) or (self._element() is None):
314            return False
315        return self._element().substitutesFor(element)
316
317    @classmethod
318    def _IsUrType (cls):
319        """Return C{True} iff this is the ur-type.
320
321        The only ur-type is {http://www.w3.org/2001/XMLSchema}anyType.  The
322        implementation of this method is overridden for
323        L{pyxb.binding.datatypes.anyType}."""
324        return False
325
326    @classmethod
327    def _RequireXSIType (cls, value_type):
328        if cls._IsUrType():
329            # Require xsi:type if value refines xs:anyType
330            return value_type != cls
331        if cls._Abstract:
332            # You can't instantiate an abstract class, so if the element
333            # declaration expects one we're gonna need to be told what type
334            # this really is.
335            return value_type != cls._SupersedingClass()
336        # For unions delegate to whether the selected member type requires
337        # the attribute.  Most times they won't.
338        if issubclass(cls, STD_union):
339            for mt in cls._MemberTypes:
340                if issubclass(value_type, mt):
341                    return mt._RequireXSIType(value_type)
342            raise pyxb.LogicError('Union %s instance type %s not sublass of member type?' % (cls, value_type))
343        # Otherwise we need the qualifier if the value type extends or
344        # restricts the type schema expects.
345        return value_type != cls._SupersedingClass()
346
347    @classmethod
348    def _CompatibleValue (cls, value, **kw):
349        """Return a variant of the value that is compatible with this type.
350
351        Compatibility is defined relative to the type definition associated
352        with the element.  The value C{None} is always compatible.  If
353        C{value} has a Python type (e.g., C{int}) that is a superclass of the
354        required L{_TypeBinding_mixin} class (e.g., C{xs:byte}), C{value} is
355        used as a constructor parameter to return a new instance of the
356        required type.  Note that constraining facets are applied here if
357        necessary (e.g., although a Python C{int} with value C{500} is
358        type-compatible with C{xs:byte}, it is outside the value space, and
359        compatibility will fail).
360
361        @keyword _convert_string_values: If C{True} (default) and the incoming value is
362        a string, an attempt will be made to form a compatible value by using
363        the string as a constructor argument to the this class.  This flag is
364        set to C{False} when testing automaton transitions.
365
366        @raise pyxb.SimpleTypeValueError: if the value is not both
367        type-consistent and value-consistent with the element's type.
368        """
369        convert_string_values = kw.get('_convert_string_values', True)
370        # None is always None
371        if value is None:
372            return None
373        # Already an instance?
374        if isinstance(value, cls):
375            # @todo: Consider whether we should change the associated _element
376            # of this value.  (**Consider** it, don't just do it.)
377            return value
378        value_type = type(value)
379        # All string-based PyXB binding types use unicode, not str
380        if six.PY2 and str == value_type:
381            value_type = six.text_type
382
383        # See if we got passed a Python value which needs to be "downcasted"
384        # to the _TypeBinding_mixin version.
385        if issubclass(cls, value_type):
386            return cls(value)
387
388        # See if we have a numeric type that needs to be cast across the
389        # numeric hierarchy.  int to long is the *only* conversion we accept.
390        if isinstance(value, int) and issubclass(cls, six.long_type):
391            return cls(value)
392
393        # Same, but for boolean, which Python won't let us subclass
394        if isinstance(value, bool) and issubclass(cls, pyxb.binding.datatypes.boolean):
395            return cls(value)
396
397        # See if we have convert_string_values on, and have a string type that
398        # somebody understands.
399        if convert_string_values and value_type == six.text_type:
400            return cls(value)
401
402        # Maybe this is a union?
403        if issubclass(cls, STD_union):
404            for mt in cls._MemberTypes:
405                try:
406                    return mt._CompatibleValue(value, **kw)
407                except:
408                    pass
409
410        # Any type is compatible with the corresponding ur-type
411        if (pyxb.binding.datatypes.anySimpleType == cls) and issubclass(value_type, simpleTypeDefinition):
412            return value
413        if pyxb.binding.datatypes.anyType == cls:
414            if not isinstance(value, _TypeBinding_mixin):
415                _log.info('Created %s instance from value of type %s', cls._ExpandedName, type(value))
416                value = cls(value)
417            return value
418
419        # Is this the wrapper class that indicates we should create a binding
420        # from arguments?
421        if isinstance(value, pyxb.BIND):
422            return value.createInstance(cls.Factory, **kw)
423
424        # Does the class have simple content which we can convert?
425        if cls._IsSimpleTypeContent():
426            # NB: byte(34.2) will create a value, but it may not be one we
427            # want to accept, so only do this if the output is equal to the
428            # input.
429            rv = cls.Factory(value)
430            if isinstance(rv, simpleTypeDefinition) and (rv == value):
431                return rv
432            # Python decimal instances do not compare equal to float values;
433            # test whether the string representation is equal instead.
434            if isinstance(rv, decimal.Decimal) and (str(rv) == str(value)):
435                return rv
436            if isinstance(rv, complexTypeDefinition) and (rv.value() == value):
437                return rv
438
439        # There may be other things that can be converted to the desired type,
440        # but we can't tell that from the type hierarchy.  Too many of those
441        # things result in an undesirable loss of information: for example,
442        # when an all model supports both numeric and string transitions, the
443        # candidate is a number, and the string transition is tested first.
444        raise pyxb.SimpleTypeValueError(cls, value)
445
446    @classmethod
447    def _IsSimpleTypeContent (cls):
448        """Return True iff the content of this binding object is a simple type.
449
450        This is true only for descendents of simpleTypeDefinition and instances
451        of complexTypeDefinition that have simple type content."""
452        raise pyxb.LogicError('Failed to override _TypeBinding_mixin._IsSimpleTypeContent')
453
454    # If the type supports wildcard attributes, this describes their
455    # constraints.  (If it doesn't, this should remain None.)  Supporting
456    # classes should override this value.
457    _AttributeWildcard = None
458
459    _AttributeMap = { }
460    """Map from expanded names to AttributeUse instances.  Non-empty only in
461    L{complexTypeDefinition} subclasses."""
462
463    @classmethod
464    def __AttributesFromDOM (cls, node):
465        attribute_settings = { }
466        for ai in range(0, node.attributes.length):
467            attr = node.attributes.item(ai)
468            # NB: Specifically do not consider attr's NamespaceContext, since
469            # attributes do not accept a default namespace.
470            attr_en = pyxb.namespace.ExpandedName(attr)
471
472            # Ignore xmlns and xsi attributes; we've already handled those
473            if attr_en.namespace() in ( pyxb.namespace.XMLNamespaces, XSI ):
474                continue
475
476            attribute_settings[attr_en] = attr.value
477        return attribute_settings
478
479    def _setAttributesFromKeywordsAndDOM (self, kw, dom_node):
480        """Invoke self._setAttribute based on node attributes and keywords.
481
482        Though attributes can only legally appear in complexTypeDefinition
483        instances, delayed conditional validation requires caching them in
484        simpleTypeDefinition.
485
486        @param kw: keywords passed to the constructor.  This map is mutated by
487        the call: keywords corresponding to recognized attributes are removed.
488
489        @param dom_node: an xml.dom Node instance, possibly C{None}
490        """
491
492        # Extract keywords that match field names
493        attribute_settings = { }
494        if dom_node is not None:
495            attribute_settings.update(self.__AttributesFromDOM(dom_node))
496        for fu in six.itervalues(self._AttributeMap):
497            iv = kw.pop(fu.id(), None)
498            if iv is not None:
499                attribute_settings[fu.name()] = iv
500        for (attr_en, value_lex) in six.iteritems(attribute_settings):
501            self._setAttribute(attr_en, value_lex)
502
503    def toDOM (self, bds=None, parent=None, element_name=None):
504        """Convert this instance to a DOM node.
505
506        The name of the top-level element is either the name of the L{element}
507        instance associated with this instance, or the XML name of the type of
508        this instance.
509
510        @param bds: Support for customizing the generated document
511        @type bds: L{pyxb.utils.domutils.BindingDOMSupport}
512        @param parent: If C{None}, a standalone document is created;
513        otherwise, the created element is a child of the given element.
514        @type parent: C{xml.dom.Element} or C{None}
515        @rtype: C{xml.dom.Document}
516        """
517
518        if bds is None:
519            bds = domutils.BindingDOMSupport()
520        need_xsi_type = bds.requireXSIType()
521        if isinstance(element_name, six.string_types):
522            element_name = pyxb.namespace.ExpandedName(bds.defaultNamespace(), element_name)
523        if (element_name is None) and (self._element() is not None):
524            element_binding = self._element()
525            element_name = element_binding.name()
526            need_xsi_type = need_xsi_type or element_binding.typeDefinition()._RequireXSIType(type(self))
527        if element_name is None:
528            raise pyxb.UnboundElementError(self)
529        element = bds.createChildElement(element_name, parent)
530        if need_xsi_type:
531            bds.addAttribute(element, XSI.type, self._ExpandedName)
532        self._toDOM_csc(bds, element)
533        bds.finalize()
534        return bds.document()
535
536    def toxml (self, encoding=None, bds=None, root_only=False, element_name=None):
537        """Shorthand to get the object as an XML document.
538
539        If you want to set the default namespace, pass in a pre-configured
540        C{bds}.
541
542        @param encoding: The encoding to be used.  See
543        @C{xml.dom.Node.toxml()} for a description of why you should always
544        pass @C{'utf-8'} here.  Because this method follows the contract of
545        the corresponding C{xml.dom.Node} method, it does not automatically
546        get the default PyXB output encoding.
547
548        @param bds: Optional L{pyxb.utils.domutils.BindingDOMSupport} instance
549        to use for creation. If not provided (default), a new generic one is
550        created.
551
552        @param root_only: Set to C{True} to automatically deference the
553        C{documentElement} of the resulting DOM node.  This eliminates the XML
554        declaration that would otherwise be generated.
555
556        @param element_name: This value is passed through to L{toDOM}, and is
557        useful when the value has no bound element but you want to convert it
558        to XML anyway.
559        """
560        dom = self.toDOM(bds, element_name=element_name)
561        if root_only:
562            dom = dom.documentElement
563        return dom.toxml(encoding)
564
565    def _toDOM_csc (self, dom_support, parent):
566        assert parent is not None
567        if self.__xsiNil:
568            dom_support.addAttribute(parent, XSI.nil, 'true')
569        return getattr(super(_TypeBinding_mixin, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
570
571    def _validateBinding_vx (self):
572        """Override in subclasses for type-specific validation of instance
573        content.
574
575        @return: C{True} if the instance validates
576        @raise pyxb.BatchContentValidationError: complex content does not match model
577        @raise pyxb.SimpleTypeValueError: simple content fails to satisfy constraints
578        """
579        raise NotImplementedError('%s._validateBinding_vx' % (type(self).__name__,))
580
581    def validateBinding (self):
582        """Check whether the binding content matches its content model.
583
584        @return: C{True} if validation succeeds.
585        @raise pyxb.BatchContentValidationError: complex content does not match model
586        @raise pyxb.SimpleTypeValueError: attribute or simple content fails to satisfy constraints
587        """
588        if self._performValidation():
589            self._validateBinding_vx()
590        return True
591
592    def _finalizeContentModel (self):
593        """Inform content model that all additions have been provided.
594
595        This is used to resolve any pending non-determinism when the content
596        of an element is provided through a DOM assignment or through
597        positional arguments in a constructor."""
598        return self
599
600    def _postDOMValidate (self):
601        self.validateBinding()
602        return self
603
604    @classmethod
605    def _Name (cls):
606        """Return the best descriptive name for the type of the instance.
607
608        This is intended to be a human-readable value used in diagnostics, and
609        is the expanded name if the type has one, or the Python type name if
610        it does not."""
611        if cls._ExpandedName is not None:
612            return six.text_type(cls._ExpandedName)
613        return six.text_type(cls)
614
615    def _diagnosticName (self):
616        """The best name available for this instance in diagnostics.
617
618        If the instance is associated with an element, it is the element name;
619        otherwise it is the best name for the type of the instance per L{_Name}."""
620        if self.__element is None:
621            return self._Name()
622        return six.text_type(self.__element.name())
623
624class _DynamicCreate_mixin (pyxb.cscRoot):
625    """Helper to allow overriding the implementation class.
626
627    Generally we'll want to augment the generated bindings by subclassing
628    them, and adding functionality to the subclass.  This mix-in provides a
629    way to communicate the existence of the superseding subclass back to the
630    binding infrastructure, so that when it creates an instance it uses the
631    subclass rather than the unaugmented binding class.
632
633    When a raw generated binding is subclassed, L{_SetSupersedingClass} should be
634    invoked on the raw class passing in the superseding subclass.  E.g.::
635
636      class mywsdl (raw.wsdl):
637        pass
638      raw.wsdl._SetSupersedingClass(mywsdl)
639
640    """
641
642    @classmethod
643    def __SupersedingClassAttribute (cls):
644        return '_%s__SupersedingClass' % (cls.__name__,)
645
646    @classmethod
647    def __AlternativeConstructorAttribute (cls):
648        return '_%s__AlternativeConstructor' % (cls.__name__,)
649
650    @classmethod
651    def _SupersedingClass (cls):
652        """Return the class stored in the class reference attribute."""
653        return getattr(cls, cls.__SupersedingClassAttribute(), cls)
654
655    @classmethod
656    def _AlternativeConstructor (cls):
657        """Return the class stored in the class reference attribute."""
658        rv = getattr(cls, cls.__AlternativeConstructorAttribute(), None)
659        if isinstance(rv, tuple):
660            rv = rv[0]
661        return rv
662
663    @classmethod
664    def _SetSupersedingClass (cls, superseding):
665        """Set the class reference attribute.
666
667        @param superseding: A Python class that is a subclass of this class.
668        """
669        assert (superseding is None) or issubclass(superseding, cls)
670        if superseding is None:
671            cls.__dict__.pop(cls.__SupersedingClassAttribute(), None)
672        else:
673            setattr(cls, cls.__SupersedingClassAttribute(), superseding)
674        return superseding
675
676    @classmethod
677    def _SetAlternativeConstructor (cls, alternative_constructor):
678        attr = cls.__AlternativeConstructorAttribute()
679        if alternative_constructor is None:
680            cls.__dict__.pop(attr, None)
681        else:
682            # Need to use a tuple as the value: if you use an invokable, this
683            # ends up converting it from a function to an unbound method,
684            # which is not what we want.
685            setattr(cls, attr, (alternative_constructor,))
686        assert cls._AlternativeConstructor() == alternative_constructor
687        return alternative_constructor
688
689    @classmethod
690    def _DynamicCreate (cls, *args, **kw):
691        """Invoke the constructor for this class or the one that supersedes it."""
692        ctor = cls._AlternativeConstructor()
693        if ctor is None:
694            ctor = cls._SupersedingClass()
695        try:
696            return ctor(*args, **kw)
697        except TypeError:
698            raise pyxb.SimpleTypeValueError(ctor, args)
699
700class _RepresentAsXsdLiteral_mixin (pyxb.cscRoot):
701    """Marker class for data types using XSD literal string as pythonLiteral.
702
703    This is necessary for any simple data type where Python repr() produces a
704    constructor call involving a class that may not be available by that name;
705    e.g. duration, decimal, and any of the date/time types."""
706    pass
707
708class _NoNullaryNonNillableNew_mixin (pyxb.cscRoot):
709    """Marker class indicating that a simple data type cannot construct
710    a value from XML through an empty string.
711
712    This class should appear immediately L{simpleTypeDefinition} (or whatever
713    inherits from L{simpleTypeDefinition} in cases where it applies."""
714    pass
715
716class simpleTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
717    """L{simpleTypeDefinition} is a base class that is part of the
718    hierarchy of any class that represents the Python datatype for a
719    L{SimpleTypeDefinition<pyxb.xmlschema.structures.SimpleTypeDefinition>}.
720
721    @note: This class, or a descendent of it, must be the first class
722    in the method resolution order when a subclass has multiple
723    parents.  Otherwise, constructor keyword arguments may not be
724    removed before passing them on to Python classes that do not
725    accept them.
726    """
727
728    # A map from leaf classes in the facets module to instance of
729    # those classes that constrain or otherwise affect the datatype.
730    # Note that each descendent of simpleTypeDefinition has its own map.
731    __FacetMap = {}
732
733    _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'XsdLiteral', 'xsdLiteral',
734                            'XsdSuperType', 'XsdPythonType', 'XsdConstraintsOK',
735                            'xsdConstraintsOK', 'XsdValueLength', 'xsdValueLength',
736                            'PythonLiteral', 'pythonLiteral',
737                            'SimpleTypeDefinition' ]))
738    """Symbols that remain the responsibility of this class.  Any
739    public symbols in generated binding subclasses are deconflicted
740    by providing an alternative name in the subclass.  (There
741    currently are no public symbols in generated SimpleTypeDefinion
742    bindings."""
743
744
745    # Determine the name of the class-private facet map.  For the base class
746    # this should produce the same attribute name as Python's privatization
747    # scheme.
748    __FacetMapAttributeNameMap = { }
749    @classmethod
750    def __FacetMapAttributeName (cls):
751        """ """
752        '''
753        if cls == simpleTypeDefinition:
754            return '_%s__FacetMap' % (cls.__name__.strip('_'),)
755
756        # It is not uncommon for a class in one namespace to extend a class of
757        # the same name in a different namespace, so encode the namespace URI
758        # in the attribute name (if it is part of a namespace).
759        ns_uri = ''
760        try:
761            ns_uri = cls._ExpandedName.namespaceURI()
762        except Exception:
763            pass
764        nm = '_' + utility.MakeIdentifier('%s_%s_FacetMap' % (ns_uri, cls.__name__.strip('_')))
765        '''
766        nm = cls.__FacetMapAttributeNameMap.get(cls)
767        if nm is None:
768            nm = cls.__name__
769            if nm.endswith('_'):
770                nm += '1'
771            if cls == simpleTypeDefinition:
772                nm = '_%s__FacetMap' % (nm,)
773            else:
774                # It is not uncommon for a class in one namespace to extend a class of
775                # the same name in a different namespace, so encode the namespace URI
776                # in the attribute name (if it is part of a namespace).
777                ns_uri = ''
778                try:
779                    ns_uri = cls._ExpandedName.namespaceURI()
780                except Exception:
781                    pass
782                nm = '_' + utility.MakeIdentifier('%s_%s_FacetMap' % (ns_uri, nm))
783            cls.__FacetMapAttributeNameMap[cls] = nm
784        return nm
785
786    @classmethod
787    def _FacetMap (cls):
788        """Return a reference to the facet map for this datatype.
789
790        The facet map is a map from leaf facet classes to instances of those
791        classes that constrain or otherwise apply to the lexical or value
792        space of the datatype.  Classes may inherit their facet map from their
793        superclass, or may create a new class instance if the class adds a new
794        constraint type.
795
796        @raise AttributeError: if the facet map has not been defined"""
797        return getattr(cls, cls.__FacetMapAttributeName())
798
799    @classmethod
800    def _InitializeFacetMap (cls, *args):
801        """Initialize the facet map for this datatype.
802
803        This must be called exactly once, after all facets belonging to the
804        datatype have been created.
805
806        @raise pyxb.LogicError: if called multiple times (on the same class)
807        @raise pyxb.LogicError: if called when a parent class facet map has not been initialized
808        :return: the facet map"""
809        fm = None
810        try:
811            fm = cls._FacetMap()
812        except AttributeError:
813            pass
814        if fm is not None:
815            raise pyxb.LogicError('%s facet map initialized multiple times: %s' % (cls.__name__, cls.__FacetMapAttributeName()))
816
817        # Search up the type hierarchy to find the nearest ancestor that has a
818        # facet map.  This gets a bit tricky: if we hit the ceiling early
819        # because the PSTD hierarchy re-based itself on a new Python type, we
820        # have to jump to the XsdSuperType.
821        source_class = cls
822        while fm is None:
823            # Assume we're staying in this hierarchy.  Include source_class in
824            # the candidates, since we might have jumped to it.
825            for super_class in source_class.mro():
826                assert super_class is not None
827                if (super_class == simpleTypeDefinition): # and (source_class.XsdSuperType() is not None):
828                    break
829                if issubclass(super_class, simpleTypeDefinition):
830                    try:
831                        fm = super_class._FacetMap()
832                        break
833                    except AttributeError:
834                        pass
835            if fm is None:
836                try:
837                    source_class = source_class.XsdSuperType()
838                except AttributeError:
839                    source_class = None
840                if source_class is None:
841                    fm = { }
842        if fm is None:
843            raise pyxb.LogicError('%s is not a child of simpleTypeDefinition' % (cls.__name__,))
844        fm = fm.copy()
845        for facet in args:
846            fm[type(facet)] = facet
847        setattr(cls, cls.__FacetMapAttributeName(), fm)
848        return fm
849
850    @classmethod
851    def _ConvertArguments_vx (cls, args, kw):
852        return args
853
854    @classmethod
855    def _ConvertArguments (cls, args, kw):
856        """Pre-process the arguments.
857
858        This is used before invoking the parent constructor.  One application
859        is to apply the whitespace facet processing; if such a request is in
860        the keywords, it is removed so it does not propagate to the
861        superclass.  Another application is to convert the arguments from a
862        string to a list.  Binding-specific applications are performed in the
863        overloaded L{_ConvertArguments_vx} method."""
864        dom_node = kw.pop('_dom_node', None)
865        from_xml = kw.get('_from_xml', dom_node is not None)
866        if dom_node is not None:
867            text_content = domutils.ExtractTextContent(dom_node)
868            if text_content is not None:
869                args = (domutils.ExtractTextContent(dom_node),) + args
870                kw['_apply_whitespace_facet'] = True
871        apply_whitespace_facet = kw.pop('_apply_whitespace_facet', from_xml)
872        if (0 < len(args)) and isinstance(args[0], six.string_types) and apply_whitespace_facet:
873            cf_whitespace = getattr(cls, '_CF_whiteSpace', None)
874            if cf_whitespace is not None:
875                norm_str = six.text_type(cf_whitespace.normalizeString(args[0]))
876                args = (norm_str,) + args[1:]
877        kw['_from_xml'] = from_xml
878        return cls._ConvertArguments_vx(args, kw)
879
880    # Must override new, because new gets invoked before init, and usually
881    # doesn't accept keywords.  In case it does (e.g., datetime.datetime),
882    # only remove the ones that would normally be interpreted by this class.
883    # Do the same argument conversion as is done in init.  Trap errors and
884    # convert them to BadTypeValue errors.
885    #
886    # Note: We explicitly do not validate constraints here.  That's
887    # done in the normal constructor; here, we might be in the process
888    # of building a value that eventually will be legal, but isn't
889    # yet.
890    def __new__ (cls, *args, **kw):
891        # PyXBFactoryKeywords
892        kw.pop('_validate_constraints', None)
893        kw.pop('_require_value', None)
894        kw.pop('_element', None)
895        kw.pop('_fallback_namespace', None)
896        kw.pop('_apply_attributes', None)
897        is_nil = kw.pop('_nil', None)
898        # ConvertArguments will remove _dom_node, _element, and
899        # _apply_whitespace_facet, and it will set _from_xml.
900        args = cls._ConvertArguments(args, kw)
901        from_xml = kw.pop('_from_xml', False)
902        if ((0 == len(args))
903            and from_xml
904            and not is_nil
905            and issubclass(cls, _NoNullaryNonNillableNew_mixin)):
906            raise pyxb.SimpleTypeValueError(cls, args);
907        kw.pop('_location', None)
908        assert issubclass(cls, _TypeBinding_mixin)
909        try:
910            parent = super(simpleTypeDefinition, cls)
911            if parent.__new__ is object.__new__:
912                return parent.__new__(cls)
913            return parent.__new__(cls, *args, **kw)
914        except ValueError:
915            raise pyxb.SimpleTypeValueError(cls, args)
916        except OverflowError:
917            raise pyxb.SimpleTypeValueError(cls, args)
918
919    # Validate the constraints after invoking the parent constructor,
920    # unless told not to.
921    def __init__ (self, *args, **kw):
922        """Initialize a newly created STD instance.
923
924        Usually there is one positional argument, which is a value that can be
925        converted to the underlying Python type.
926
927        @keyword _validate_constraints: If True (default if validation is
928        enabled), the newly constructed value is checked against its
929        constraining facets.
930        @type _validate_constraints: C{bool}
931
932        @keyword _apply_attributes: If C{True} (default), any attributes
933        present in the keywords or DOM node are applied.  Normally presence of
934        such an attribute should produce an error; when creating simple
935        content for a complex type we need the DOM node, but do not want to
936        apply the attributes, so we bypass the application.
937        """
938        # PyXBFactoryKeywords
939        validate_constraints = kw.pop('_validate_constraints', self._validationConfig.forBinding)
940        require_value = kw.pop('_require_value', False)
941        # Save DOM node so we can pull attributes off it
942        dom_node = kw.get('_dom_node')
943        location = kw.get('_location')
944        if (location is None) and isinstance(dom_node, utility.Locatable_mixin):
945            location = dom_node._location()
946        apply_attributes = kw.pop('_apply_attributes', True)
947        # _ConvertArguments handles _dom_node and _apply_whitespace_facet
948        # TypeBinding_mixin handles _nil and _element
949        args = self._ConvertArguments(args, kw)
950        try:
951            super(simpleTypeDefinition, self).__init__(*args, **kw)
952        except OverflowError:
953            raise pyxb.SimpleTypeValueError(type(self), args)
954        if apply_attributes and (dom_node is not None):
955            self._setAttributesFromKeywordsAndDOM(kw, dom_node)
956        if require_value and (not self._constructedWithValue()):
957            if location is None:
958                location = self._location()
959            raise pyxb.SimpleContentAbsentError(self, location)
960        if validate_constraints and not kw.pop('_nil', False):
961            self.xsdConstraintsOK(location)
962
963    # The class attribute name used to store the reference to the STD
964    # component instance must be unique to the class, not to this base class.
965    # Otherwise we mistakenly believe we've already associated a STD instance
966    # with a class (e.g., xsd:normalizedString) when in fact it's associated
967    # with the superclass (e.g., xsd:string)
968    @classmethod
969    def __STDAttrName (cls):
970        return '_%s__SimpleTypeDefinition' % (cls.__name__,)
971
972    @classmethod
973    def _SimpleTypeDefinition (cls, std):
974        """Set the L{pyxb.xmlschema.structures.SimpleTypeDefinition} instance
975        associated with this binding."""
976        attr_name = cls.__STDAttrName()
977        if hasattr(cls, attr_name):
978            old_value = getattr(cls, attr_name)
979            if old_value != std:
980                raise pyxb.LogicError('%s: Attempt to override existing STD %s with %s' % (cls, old_value.name(), std.name()))
981        setattr(cls, attr_name, std)
982
983    @classmethod
984    def SimpleTypeDefinition (cls):
985        """Return the SimpleTypeDefinition instance for the given
986        class.
987
988        This should only be invoked when generating bindings.  An STD must
989        have been associated with the class using L{_SimpleTypeDefinition}."""
990        attr_name = cls.__STDAttrName()
991        assert hasattr(cls, attr_name)
992        return getattr(cls, attr_name)
993
994    @classmethod
995    def XsdLiteral (cls, value):
996        """Convert from a python value to a string usable in an XML
997        document.
998
999        This should be implemented in the subclass."""
1000        raise pyxb.LogicError('%s does not implement XsdLiteral' % (cls,))
1001
1002    def xsdLiteral (self):
1003        """Return text suitable for representing the value of this
1004        instance in an XML document.
1005
1006        The base class implementation delegates to the object class's
1007        XsdLiteral method."""
1008        if self._isNil():
1009            return ''
1010        return self.XsdLiteral(self)
1011
1012    @classmethod
1013    def XsdSuperType (cls):
1014        """Find the nearest parent class in the PST hierarchy.
1015
1016        The value for anySimpleType is None; for all others, it's a
1017        primitive or derived PST descendent (including anySimpleType)."""
1018        for sc in cls.mro():
1019            if sc == cls:
1020                continue
1021            if simpleTypeDefinition == sc:
1022                # If we hit the PST base, this is a primitive type or
1023                # otherwise directly descends from a Python type; return
1024                # the recorded XSD supertype.
1025                return cls._XsdBaseType
1026            if issubclass(sc, simpleTypeDefinition):
1027                return sc
1028        raise pyxb.LogicError('No supertype found for %s' % (cls,))
1029
1030    @classmethod
1031    def _XsdConstraintsPreCheck_vb (cls, value):
1032        """Pre-extended class method to verify other things before
1033        checking constraints.
1034
1035        This is used for list types, to verify that the values in the
1036        list are acceptable, and for token descendents, to check the
1037        lexical/value space conformance of the input.
1038        """
1039        super_fn = getattr(super(simpleTypeDefinition, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: value)
1040        return super_fn(value)
1041
1042    # Cache of pre-computed sequences of class facets in the order required
1043    # for constraint validation
1044    __ClassFacetSequence = { }
1045
1046    @classmethod
1047    def XsdConstraintsOK (cls, value, location=None):
1048        """Validate the given value against the constraints on this class.
1049
1050        @raise pyxb.SimpleTypeValueError: if any constraint is violated.
1051        """
1052
1053        value = cls._XsdConstraintsPreCheck_vb(value)
1054
1055        facet_values = cls.__ClassFacetSequence.get(cls)
1056        if facet_values is None:
1057            # Constraints for simple type definitions are inherited.  Check them
1058            # from least derived to most derived.
1059            classes = [ _x for _x in cls.mro() if issubclass(_x, simpleTypeDefinition) ]
1060            classes.reverse()
1061            cache_result = True
1062            facet_values = []
1063            for clazz in classes:
1064                # When setting up the datatypes, if we attempt to validate
1065                # something before the facets have been initialized (e.g., a
1066                # nonNegativeInteger used as a length facet for the parent
1067                # integer datatype), just ignore that for now.  Don't cache
1068                # the value, though, since a subsequent check after
1069                # initialization should succceed.
1070                try:
1071                    clazz_facets = list(six.itervalues(clazz._FacetMap()))
1072                except AttributeError:
1073                    cache_result = False
1074                    clazz_facets = []
1075                for v in clazz_facets:
1076                    if not (v in facet_values):
1077                        facet_values.append(v)
1078            if cache_result:
1079                cls.__ClassFacetSequence[cls] = facet_values
1080        for f in facet_values:
1081            if not f.validateConstraint(value):
1082                raise pyxb.SimpleFacetValueError(cls, value, f, location)
1083        return value
1084
1085    def xsdConstraintsOK (self, location=None):
1086        """Validate the value of this instance against its constraints."""
1087        return self.XsdConstraintsOK(self, location)
1088
1089    def _validateBinding_vx (self):
1090        if not self._isNil():
1091            self._checkValidValue()
1092        return True
1093
1094    @classmethod
1095    def XsdValueLength (cls, value):
1096        """Return the length of the given value.
1097
1098        The length is calculated by a subclass implementation of
1099        _XsdValueLength_vx in accordance with
1100        http://www.w3.org/TR/xmlschema-2/#rf-length.
1101
1102        The return value is a non-negative integer, or C{None} if length
1103        constraints should be considered trivially satisfied (as with
1104        QName and NOTATION).
1105
1106        @raise pyxb.LogicError: the provided value is not an instance of cls.
1107        @raise pyxb.LogicError: an attempt is made to calculate a length for
1108        an instance of a type that does not support length calculations.
1109        """
1110        assert isinstance(value, cls)
1111        if not hasattr(cls, '_XsdValueLength_vx'):
1112            raise pyxb.LogicError('Class %s does not support length validation' % (cls.__name__,))
1113        return cls._XsdValueLength_vx(value)
1114
1115    def xsdValueLength (self):
1116        """Return the length of this instance within its value space.
1117
1118        See XsdValueLength."""
1119        return self.XsdValueLength(self)
1120
1121    @classmethod
1122    def PythonLiteral (cls, value):
1123        """Return a string which can be embedded into Python source to
1124        represent the given value as an instance of this class."""
1125        class_name = cls.__name__
1126        if issubclass(cls, _RepresentAsXsdLiteral_mixin):
1127            value = value.xsdLiteral()
1128        return '%s(%s)' % (class_name, pyxb.utils.utility.repr2to3(value))
1129
1130    def pythonLiteral (self):
1131        """Return a string which can be embedded into Python source to
1132        represent the value of this instance."""
1133        return self.PythonLiteral(self)
1134
1135    def _toDOM_csc (self, dom_support, parent):
1136        assert parent is not None
1137        dom_support.appendTextChild(self, parent)
1138        return getattr(super(simpleTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
1139
1140    @classmethod
1141    def _IsSimpleTypeContent (cls):
1142        """STDs have simple type content."""
1143        return True
1144
1145    @classmethod
1146    def _IsValidValue (self, value):
1147        try:
1148            self._CheckValidValue(value)
1149            return True
1150        except pyxb.PyXBException:
1151            pass
1152        return False
1153
1154    @classmethod
1155    def _CheckValidValue (cls, value):
1156
1157        """NB: Invoking this on a value that is a list will, if necessary,
1158        replace the members of the list with new values that are of the
1159        correct item type.  This is permitted because only with lists is it
1160        possible to bypass the normal content validation (by invoking
1161        append/extend on the list instance)."""
1162        if value is None:
1163            raise pyxb.SimpleTypeValueError(cls, value)
1164        value_class = cls
1165        if issubclass(cls, STD_list):
1166            if not isinstance(value, collections.Iterable):
1167                raise pyxb.SimpleTypeValueError(cls, value)
1168            for v in value:
1169                if not cls._ItemType._IsValidValue(v):
1170                    raise pyxb.SimpleListValueError(cls, v)
1171        else:
1172            if issubclass(cls, STD_union):
1173                value_class = None
1174                for mt in cls._MemberTypes:
1175                    if mt._IsValidValue(value):
1176                        value_class = mt
1177                        break
1178                if value_class is None:
1179                    raise pyxb.SimpleUnionValueError(cls, value)
1180            #if not (isinstance(value, value_class) or issubclass(value_class, type(value))):
1181            if not isinstance(value, value_class):
1182                raise pyxb.SimpleTypeValueError(cls, value)
1183        value_class.XsdConstraintsOK(value)
1184
1185    def _checkValidValue (self):
1186        self._CheckValidValue(self)
1187
1188    def _isValidValue (self):
1189        self._IsValidValue(self)
1190
1191    def _setAttribute (self, attr_en, value_lex):
1192        # Simple types have no attributes, but the parsing infrastructure
1193        # might invoke this to delegate responsibility for notifying the user
1194        # of the failure.
1195        raise pyxb.AttributeOnSimpleTypeError(self, attr_en, value_lex)
1196
1197    @classmethod
1198    def _description (cls, name_only=False, user_documentation=True):
1199        name = cls._Name()
1200        if name_only:
1201            return name
1202        desc = [ name, ' restriction of ', cls.XsdSuperType()._description(name_only=True) ]
1203        if user_documentation and (cls._Documentation is not None):
1204            desc.extend(["\n", cls._Documentation])
1205        return ''.join(desc)
1206
1207class STD_union (simpleTypeDefinition):
1208    """Base class for union datatypes.
1209
1210    This class descends only from simpleTypeDefinition.  A pyxb.LogicError is
1211    raised if an attempt is made to construct an instance of a subclass of
1212    STD_union.  Values consistent with the member types are constructed using
1213    the Factory class method.  Values are validated using the _ValidatedMember
1214    class method.
1215
1216    Subclasses must provide a class variable _MemberTypes which is a
1217    tuple of legal members of the union."""
1218
1219    _MemberTypes = None
1220    """A list of classes which are permitted as values of the union."""
1221
1222    # Ick: If we don't declare this here, this class's map doesn't get
1223    # initialized.  Alternative is to not descend from simpleTypeDefinition.
1224    # @todo Ensure that pattern and enumeration are valid constraints
1225    __FacetMap = {}
1226
1227    @classmethod
1228    def Factory (cls, *args, **kw):
1229        """Given a value, attempt to create an instance of some member of this
1230        union.  The first instance which can be legally created is returned.
1231
1232        @keyword _validate_constraints: If C{True} (default if validation is
1233        enabled), any constructed value is checked against constraints applied
1234        to the union as well as the member type.
1235
1236        @raise pyxb.SimpleTypeValueError: no member type will permit creation of
1237        an instance from the parameters in C{args} and C{kw}.
1238        """
1239
1240        used_cls = cls._SupersedingClass()
1241        state = used_cls._PreFactory_vx(args, kw)
1242
1243        rv = None
1244        # NB: get, not pop: preserve it for the member type invocations
1245        validate_constraints = kw.get('_validate_constraints', cls._GetValidationConfig().forBinding)
1246        assert isinstance(validate_constraints, bool)
1247        if 0 < len(args):
1248            arg = args[0]
1249            try:
1250                rv = cls._ValidatedMember(arg)
1251            except pyxb.SimpleTypeValueError:
1252                pass
1253        if rv is None:
1254            kw['_validate_constraints'] = True
1255            for mt in cls._MemberTypes:
1256                try:
1257                    rv = mt.Factory(*args, **kw)
1258                    break
1259                except pyxb.SimpleTypeValueError:
1260                    pass
1261                except (ValueError, OverflowError):
1262                    pass
1263                except:
1264                    pass
1265        location = None
1266        if kw is not None:
1267            location = kw.get('_location')
1268        if rv is not None:
1269            if validate_constraints:
1270                cls.XsdConstraintsOK(rv, location)
1271            rv._postFactory_vx(state)
1272            return rv
1273        # The constructor may take any number of arguments, so pass the whole thing.
1274        # Should we also provide the keywords?
1275        raise pyxb.SimpleUnionValueError(cls, args, location)
1276
1277    @classmethod
1278    def _ValidatedMember (cls, value):
1279        """Validate the given value as a potential union member.
1280
1281        @raise pyxb.SimpleTypeValueError: the value is not an instance of a
1282        member type."""
1283        if not isinstance(value, cls._MemberTypes):
1284            for mt in cls._MemberTypes:
1285                try:
1286                    # Force validation so we get the correct type, otherwise
1287                    # first member will be accepted.
1288                    value = mt.Factory(value, _validate_constraints=True)
1289                    return value
1290                except (TypeError, pyxb.SimpleTypeValueError):
1291                    pass
1292            raise pyxb.SimpleUnionValueError(cls, value)
1293        return value
1294
1295    def __new__ (self, *args, **kw):
1296        raise pyxb.LogicError('%s: cannot construct instances of union' % (self.__class__.__name__,))
1297
1298    def __init__ (self, *args, **kw):
1299        raise pyxb.LogicError('%s: cannot construct instances of union' % (self.__class__.__name__,))
1300
1301    @classmethod
1302    def _description (cls, name_only=False, user_documentation=True):
1303        name = cls._Name()
1304        if name_only:
1305            return name
1306        desc = [ name, ', union of ']
1307        desc.append(', '.join([ _td._description(name_only=True) for _td in cls._MemberTypes ]))
1308        return ''.join(desc)
1309
1310    @classmethod
1311    def XsdLiteral (cls, value):
1312        """Convert from a binding value to a string usable in an XML document."""
1313        return cls._ValidatedMember(value).xsdLiteral()
1314
1315
1316class STD_list (simpleTypeDefinition, six.list_type):
1317    """Base class for collection datatypes.
1318
1319    This class descends from the Python list type, and incorporates
1320    simpleTypeDefinition.  Subclasses must define a class variable _ItemType
1321    which is a reference to the class of which members must be instances."""
1322
1323    _ItemType = None
1324    """A reference to the binding class for items within this list."""
1325
1326    # Ick: If we don't declare this here, this class's map doesn't get
1327    # initialized.  Alternative is to not descend from simpleTypeDefinition.
1328    __FacetMap = {}
1329
1330    @classmethod
1331    def _ValidatedItem (cls, value, kw=None):
1332        """Verify that the given value is permitted as an item of this list.
1333
1334        This may convert the value to the proper type, if it is
1335        compatible but not an instance of the item type.  Returns the
1336        value that should be used as the item, or raises an exception
1337        if the value cannot be converted.
1338
1339        @param kw: optional dictionary of standard constructor keywords used
1340        when exceptions must be built.  In particular, C{_location} may be
1341        useful.
1342        """
1343        if isinstance(value, cls._ItemType):
1344            pass
1345        elif issubclass(cls._ItemType, STD_union):
1346            value = cls._ItemType._ValidatedMember(value)
1347        else:
1348            try:
1349                value = cls._ItemType(value)
1350            except (pyxb.SimpleTypeValueError, TypeError):
1351                location = None
1352                if kw is not None:
1353                    location = kw.get('_location')
1354                raise pyxb.SimpleListValueError(cls, value, location)
1355        return value
1356
1357    @classmethod
1358    def _ConvertArguments_vx (cls, args, kw):
1359        # If the first argument is a string, split it on spaces and use the
1360        # resulting list of tokens.
1361        if 0 < len(args):
1362            arg1 = args[0]
1363            if isinstance(arg1, six.string_types):
1364                args = (arg1.split(),) + args[1:]
1365                arg1 = args[0]
1366            if isinstance(arg1, collections.Iterable):
1367                new_arg1 = [ cls._ValidatedItem(_v, kw) for _v in arg1 ]
1368                args = (new_arg1,) + args[1:]
1369        super_fn = getattr(super(STD_list, cls), '_ConvertArguments_vx', lambda *a,**kw: args)
1370        return super_fn(args, kw)
1371
1372    @classmethod
1373    def _XsdValueLength_vx (cls, value):
1374        return len(value)
1375
1376    @classmethod
1377    def XsdLiteral (cls, value):
1378        """Convert from a binding value to a string usable in an XML document."""
1379        return ' '.join([ cls._ItemType.XsdLiteral(_v) for _v in value ])
1380
1381    @classmethod
1382    def _description (cls, name_only=False, user_documentation=True):
1383        name = cls._Name()
1384        if name_only:
1385            return name
1386        desc = [ name, ', list of ', cls._ItemType._description(name_only=True) ]
1387        return ''.join(desc)
1388
1389    # Convert a single value to the required type, if not already an instance
1390    @classmethod
1391    def __ConvertOne (cls, v):
1392        return cls._ValidatedItem(v)
1393
1394    # Convert a sequence of values to the required type, if not already instances
1395    def __convertMany (self, values):
1396        return [ self._ValidatedItem(_v) for _v in values ]
1397
1398    def __setitem__ (self, key, value):
1399        if isinstance(key, slice):
1400            super(STD_list, self).__setitem__(key, self.__convertMany(value))
1401        else:
1402            super(STD_list, self).__setitem__(key, self._ValidatedItem(value))
1403
1404    if six.PY2:
1405        def __setslice__ (self, start, end, values):
1406            super(STD_list, self).__setslice__(start, end, self.__convertMany(values))
1407
1408    def __contains__ (self, item):
1409        return super(STD_list, self).__contains__(self._ValidatedItem(item))
1410
1411    # Standard mutable sequence methods, per Python Library Reference "Mutable Sequence Types"
1412
1413    def append (self, x):
1414        super(STD_list, self).append(self._ValidatedItem(x))
1415
1416    def extend (self, x, _from_xml=False):
1417        super(STD_list, self).extend(self.__convertMany(x))
1418
1419    def count (self, x):
1420        return super(STD_list, self).count(self._ValidatedItem(x))
1421
1422    def index (self, x, *args):
1423        return super(STD_list, self).index(self._ValidatedItem(x), *args)
1424
1425    def insert (self, i, x):
1426        super(STD_list, self).insert(i, self._ValidatedItem(x))
1427
1428    def remove (self, x):
1429        super(STD_list, self).remove(self._ValidatedItem(x))
1430
1431class element (utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1432    """Class that represents a schema element within a binding.
1433
1434    This gets a little confusing.  Within a schema, the
1435    L{pyxb.xmlschema.structures.ElementDeclaration} type represents an
1436    U{element
1437    declaration<http://www.w3.org/TR/xmlschema-1/#cElement_Declarations>}.
1438    Those declarations may be global (have a name that is visible in the
1439    namespace), or local (have a name that is visible only within a complex
1440    type definition).  Further, local (but not global) declarations may have a
1441    reference to a global declaration (which might be in a different
1442    namespace).
1443
1444    Within a PyXB binding, the element declarations from the original complex
1445    type definition that have the same
1446    U{QName<http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-qname>}
1447    (after deconflicting the
1448    U{LocalPart<http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-LocalPart>})
1449    are associated with an attribute in the class for the complex type.  Each
1450    of these attributes is defined via a
1451    L{pyxb.binding.content.ElementDeclaration} which provides the mechanism by
1452    which the binding holds values associated with that element.
1453
1454    Furthermore, in the FAC-based content model each schema element
1455    declaration is associated with an
1456    L{ElementUse<pyxb.binding.content.ElementUse>} instance to locate the
1457    point in the schema where content came from.  Instances that refer to the
1458    same schema element declaration share the same underlying
1459    L{pyxb.binding.content.ElementDeclaration}.
1460
1461    This element isn't any of those elements.  This element is the type used
1462    for an attribute which associates the name of a element with data required
1463    to represent it, all within a particular scope (a module for global scope,
1464    the binding class for a complex type definition for local scope).  From
1465    the perspective of a PyXB user they look almost like a class, in that you
1466    can call them to create instances of the underlying complex type.
1467
1468    Global and local elements are represented by instances of this class.
1469    """
1470
1471    def name (self):
1472        """The expanded name of the element within its scope."""
1473        return self.__name
1474    __name = None
1475
1476    def typeDefinition (self):
1477        """The L{_TypeBinding_mixin} subclass for values of this element."""
1478        return self.__typeDefinition._SupersedingClass()
1479    __typeDefinition = None
1480
1481    def xsdLocation (self):
1482        """The L{pyxb.utils.utility.Location} where the element appears in the schema."""
1483        return self.__xsdLocation
1484    __xsdLocation = None
1485
1486    def scope (self):
1487        """The scope of the element.  This is either C{None}, representing a
1488        top-level element, or an instance of C{complexTypeDefinition} for
1489        local elements."""
1490        return self.__scope
1491    __scope = None
1492
1493    def nillable (self):
1494        """Indicate whether values matching this element can have U{nil
1495        <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set."""
1496        return self.__nillable
1497    __nillable = False
1498
1499    def abstract (self):
1500        """Indicate whether this element is abstract (must use substitution
1501        group members for matches)."""
1502        return self.__abstract
1503    __abstract = False
1504
1505    def documentation (self):
1506        """Contents of any documentation annotation in the definition."""
1507        return self.__documentation
1508    __documentation = None
1509
1510    def defaultValue (self):
1511        """The default value of the element.
1512
1513        C{None} if the element has no default value.
1514
1515        @note: A non-C{None} value is always an instance of a simple type,
1516        even if the element has complex content."""
1517        return self.__defaultValue
1518    __defaultValue = None
1519
1520    def fixed (self):
1521        """C{True} if the element content cannot be changed"""
1522        return self.__fixed
1523    __fixed = False
1524
1525    def substitutionGroup (self):
1526        """The L{element} instance to whose substitution group this element
1527        belongs.  C{None} if this element is not part of a substitution
1528        group."""
1529        return self.__substitutionGroup
1530    def _setSubstitutionGroup (self, substitution_group):
1531        self.__substitutionGroup = substitution_group
1532        if substitution_group is not None:
1533            self.substitutesFor = self._real_substitutesFor
1534        return self
1535    __substitutionGroup = None
1536
1537    def findSubstituendDecl (self, ctd_class):
1538        ed = ctd_class._ElementMap.get(self.name())
1539        if ed is not None:
1540            return ed
1541        if self.substitutionGroup() is None:
1542            return None
1543        return self.substitutionGroup().findSubstituendDecl(ctd_class)
1544
1545    def _real_substitutesFor (self, other):
1546        """Determine whether an instance of this element can substitute for the other element.
1547
1548        See U{Substitution Group OK<http://www.w3.org/TR/xmlschema-1/#cos-equiv-derived-ok-rec>}.
1549
1550        @todo: Do something about blocking constraints.  This ignores them, as
1551        does everything leading to this point.
1552        """
1553        if self.substitutionGroup() is None:
1554            return False
1555        if other is None:
1556            return False
1557        assert isinstance(other, element)
1558        # On the first call, other is likely to be the local element.  We need
1559        # the global one.
1560        if other.scope() is not None:
1561            other = other.name().elementBinding()
1562            if other is None:
1563                return False
1564            assert other.scope() is None
1565        # Do both these refer to the same (top-level) element?
1566        if self.name().elementBinding() == other:
1567            return True
1568        return (self.substitutionGroup() == other) or self.substitutionGroup().substitutesFor(other)
1569
1570    def substitutesFor (self, other):
1571        """Stub replaced by _real_substitutesFor when element supports substitution groups."""
1572        return False
1573
1574    def memberElement (self, name):
1575        """Return a reference to the element instance used for the given name
1576        within this element.
1577
1578        The type for this element must be a complex type definition."""
1579        return self.typeDefinition()._UseForTag(name).elementBinding()
1580
1581    def __init__ (self, name, type_definition, scope=None, nillable=False, abstract=False, unicode_default=None, fixed=False, substitution_group=None, documentation=None, location=None):
1582        """Create a new element binding.
1583        """
1584        assert isinstance(name, pyxb.namespace.ExpandedName)
1585        self.__name = name
1586        self.__typeDefinition = type_definition
1587        self.__scope = scope
1588        self.__nillable = nillable
1589        self.__abstract = abstract
1590        if unicode_default is not None:
1591            # Override default None.  If this is a complex type with simple
1592            # content, use the underlying simple type value.
1593            self.__defaultValue = self.__typeDefinition.Factory(unicode_default, _from_xml=True)
1594            if isinstance(self.__defaultValue, complexTypeDefinition):
1595                self.__defaultValue = self.__defaultValue.value()
1596        self.__fixed = fixed
1597        self.__substitutionGroup = substitution_group
1598        self.__documentation = documentation
1599        self.__xsdLocation = location
1600        super(element, self).__init__()
1601
1602    def __call__ (self, *args, **kw):
1603        """Invoke the Factory method on the type associated with this element.
1604
1605        @keyword _dom_node: This keyword is removed.  If present, it must be C{None}.
1606
1607        @note: Other keywords are passed to L{_TypeBinding_mixin.Factory}.
1608
1609        @raise pyxb.AbstractElementError: This element is abstract and no DOM
1610        node was provided.
1611        """
1612        dom_node = kw.pop('_dom_node', None)
1613        assert dom_node is None, 'Cannot pass DOM node directly to element constructor; use createFromDOM'
1614        if '_element' in kw:
1615            raise pyxb.LogicError('Cannot set _element in element-based instance creation')
1616        kw['_element'] = self
1617        # Can't create instances of abstract elements.
1618        if self.abstract():
1619            location = kw.get('_location')
1620            if (location is None) and isinstance(dom_node, utility.Locatable_mixin):
1621                location = dom_node._location()
1622            raise pyxb.AbstractElementError(self, location, args)
1623        if self.__defaultValue is not None:
1624            if 0 == len(args):
1625                # No initial value; use the default
1626                args = [ self.__defaultValue ]
1627            elif self.__fixed:
1628                # Validate that the value is consistent with the fixed value
1629                if 1 < len(args):
1630                    raise ValueError(*args)
1631                args = [ self.compatibleValue(args[0], **kw) ]
1632        rv = self.typeDefinition().Factory(*args, **kw)
1633        rv._setElement(self)
1634        return rv
1635
1636    def compatibleValue (self, value, **kw):
1637        """Return a variant of the value that is compatible with this element.
1638
1639        This mostly defers to L{_TypeBinding_mixin._CompatibleValue}.
1640
1641        @raise pyxb.SimpleTypeValueError: if the value is not both
1642        type-consistent and value-consistent with the element's type.
1643        """
1644        # None is always None, unless there's a default.
1645        if value is None:
1646            return self.__defaultValue
1647        is_plural = kw.pop('is_plural', False)
1648        if is_plural:
1649            if not isinstance(value, collections.Iterable):
1650                raise pyxb.SimplePluralValueError(self.typeDefinition(), value)
1651            return [ self.compatibleValue(_v) for _v in value ]
1652        compValue = self.typeDefinition()._CompatibleValue(value, **kw);
1653        if self.__fixed and (compValue != self.__defaultValue):
1654            raise pyxb.ElementChangeError(self, value)
1655        if isinstance(value, _TypeBinding_mixin) and (value._element() is not None) and value._element().substitutesFor(self):
1656            return value
1657        if self.abstract():
1658            location = None
1659            if isinstance(value, utility.Locatable_mixin):
1660                location = value._location()
1661            raise pyxb.AbstractElementError(self, location, value)
1662        return compValue
1663
1664    @classmethod
1665    def CreateDOMBinding (cls, node, element_binding, **kw):
1666        """Create a binding from a DOM node.
1667
1668        @param node: The DOM node
1669
1670        @param element_binding: An instance of L{element} that would normally
1671        be used to determine the type of the binding.  The actual type of
1672        object returned is determined by the type definition associated with
1673        the C{element_binding} and the value of any U{xsi:type
1674        <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute found in
1675        C{node}, modulated by
1676        L{XSI._InterpretTypeAttribute<pyxb.namespace.builtin._XMLSchema_instance._InterpretTypeAttribute>}.
1677
1678        @keyword _fallback_namespace: The namespace to use as the namespace for
1679        the node, if the node name is unqualified.  This should be an absent
1680        namespace.
1681
1682        @return: A binding for the DOM node.
1683
1684        @raises pyxb.UnrecognizedDOMRootNodeError: if no underlying element or
1685        type for the node can be identified.
1686        """
1687
1688        if xml.dom.Node.ELEMENT_NODE != node.nodeType:
1689            raise ValueError('node is not an element')
1690
1691        fallback_namespace = kw.get('_fallback_namespace')
1692
1693        # Record the element to be associated with the created binding
1694        # instance.
1695        if '_element' in kw:
1696            raise pyxb.LogicError('Cannot set _element in element-based instance creation')
1697
1698        type_class = None
1699        if element_binding is not None:
1700            # Can't create instances of abstract elements.  @todo: Is there any
1701            # way this could be legal given an xsi:type attribute?  I'm pretty
1702            # sure "no"...
1703            if element_binding.abstract():
1704                location = kw.get('location')
1705                if (location is None) and isinstance(node, utility.Locatable_mixin):
1706                    location = node._location()
1707                raise pyxb.AbstractElementError(element_binding, location, node)
1708            kw['_element'] = element_binding
1709            type_class = element_binding.typeDefinition()
1710
1711        # Get the namespace context for the value being created.  If none is
1712        # associated, one will be created.  Do not make assumptions about the
1713        # namespace context; if the user cared, she should have assigned a
1714        # context before calling this.
1715        ns_ctx = pyxb.namespace.NamespaceContext.GetNodeContext(node)
1716        (did_replace, type_class) = XSI._InterpretTypeAttribute(XSI.type.getAttribute(node), ns_ctx, fallback_namespace, type_class)
1717
1718        if type_class is None:
1719            raise pyxb.UnrecognizedDOMRootNodeError(node)
1720
1721        # Pass xsi:nil on to the constructor regardless of whether the element
1722        # is nillable.  Another sop to SOAP-encoding WSDL fans who don't
1723        # bother to provide valid schema for their message content.
1724        is_nil = XSI.nil.getAttribute(node)
1725        if is_nil is not None:
1726            kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil)
1727
1728        try:
1729            pyxb.namespace.NamespaceContext.PushContext(ns_ctx)
1730            rv = type_class.Factory(_dom_node=node, **kw)
1731        finally:
1732            pyxb.namespace.NamespaceContext.PopContext()
1733        assert rv._element() == element_binding
1734        rv._setNamespaceContext(pyxb.namespace.NamespaceContext.GetNodeContext(node))
1735        return rv._postDOMValidate()
1736
1737    # element
1738    @classmethod
1739    def AnyCreateFromDOM (cls, node, fallback_namespace):
1740        """Create an instance of an element from a DOM node.
1741
1742        This method does minimal processing of C{node} and delegates to
1743        L{CreateDOMBinding}.
1744
1745        @param node: An C{xml.dom.Node} representing a root element.  If the
1746        node is a document, that document's root node will be substituted.
1747        The name of the node is extracted as the name of the element to be
1748        created, and the node and the name are passed to L{CreateDOMBinding}.
1749
1750        @param fallback_namespace: The value to pass as C{_fallback_namespace}
1751        to L{CreateDOMBinding}
1752
1753        @return: As with L{CreateDOMBinding}"""
1754        if xml.dom.Node.DOCUMENT_NODE == node.nodeType:
1755            node = node.documentElement
1756        expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace)
1757        return cls.CreateDOMBinding(node, expanded_name.elementBinding(), _fallback_namespace=fallback_namespace)
1758
1759    def elementForName (self, name):
1760        """Return the element that should be used if this element binding is
1761        permitted and an element with the given name is encountered.
1762
1763        Normally, the incoming name matches the name of this binding, and
1764        C{self} is returned.  If the incoming name is different, it is
1765        expected to be the name of a global element which is within this
1766        element's substitution group.  In that case, the binding corresponding
1767        to the named element is return.
1768
1769        @return: An instance of L{element}, or C{None} if no element with the
1770        given name can be found.
1771        """
1772
1773        # Name match means OK.
1774        if self.name() == name:
1775            return self
1776        # No name match means only hope is a substitution group, for which the
1777        # element must be top-level.
1778        top_elt = self.name().elementBinding()
1779        if top_elt is None:
1780            return None
1781        # Members of the substitution group must also be top-level.  NB: If
1782        # named_elt == top_elt, then the adoptName call below improperly
1783        # associated the global namespace with a local element of the same
1784        # name; cf. test-namespace-uu:testBad.
1785        elt_en = top_elt.name().adoptName(name)
1786        assert 'elementBinding' in elt_en.namespace()._categoryMap(), 'No element bindings in %s' % (elt_en.namespace(),)
1787        named_elt = elt_en.elementBinding()
1788        if (named_elt is None) or (named_elt == top_elt):
1789            return None
1790        if named_elt.substitutesFor(top_elt):
1791            return named_elt
1792        return None
1793
1794    def createFromDOM (self, node, fallback_namespace=None, **kw):
1795        """Create an instance of this element using a DOM node as the source
1796        of its content.
1797
1798        This method does minimal processing of C{node} and delegates to
1799        L{_createFromDOM}.
1800
1801        @param node: An C{xml.dom.Node} representing a root element.  If the
1802        node is a document, that document's root node will be substituted.
1803        The name of the node is extracted as the name of the element to be
1804        created, and the node and the name are passed to L{_createFromDOM}
1805
1806        @keyword fallback_namespace: Used as default for
1807        C{_fallback_namespace} in call to L{_createFromDOM}
1808
1809        @note: Keyword parameters are passed to L{CreateDOMBinding}.
1810
1811        @return: As with L{_createFromDOM}
1812        """
1813        if xml.dom.Node.DOCUMENT_NODE == node.nodeType:
1814            node = node.documentElement
1815        if fallback_namespace is not None:
1816            kw.setdefault('_fallback_namespace', fallback_namespace)
1817        expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace)
1818        return self._createFromDOM(node, expanded_name, **kw)
1819
1820    def _createFromDOM (self, node, expanded_name, **kw):
1821        """Create an instance from a DOM node given the name of an element.
1822
1823        This method does minimal processing of C{node} and C{expanded_name}
1824        and delegates to L{CreateDOMBinding}.
1825
1826        @param node: An C{xml.dom.Node} representing a root element.  If the
1827        node is a document, that document's root node will be substituted.
1828        The value is passed to L{CreateDOMBinding}.
1829
1830        @param expanded_name: The expanded name of the element to be used for
1831        content.  This is passed to L{elementForName} to obtain the binding
1832        that is passed to L{CreateDOMBinding}, superseding any identification
1833        that might be inferred from C{node}.  If no name is available, use
1834        L{createFromDOM}.
1835
1836        @note: Keyword parameters are passed to L{CreateDOMBinding}.
1837
1838        @return: As with L{CreateDOMBinding}.
1839        """
1840        if xml.dom.Node.DOCUMENT_NODE == node.nodeType:
1841            node = node.documentElement
1842        return element.CreateDOMBinding(node, self.elementForName(expanded_name), **kw)
1843
1844    def __str__ (self):
1845        return 'Element %s' % (self.name(),)
1846
1847    def _description (self, name_only=False, user_documentation=True):
1848        name = six.text_type(self.name())
1849        if name_only:
1850            return name
1851        desc = [ name, ' (', self.typeDefinition()._description(name_only=True), ')' ]
1852        if self.scope() is not None:
1853            desc.extend([', local to ', self.scope()._description(name_only=True) ])
1854        if self.nillable():
1855            desc.append(', nillable')
1856        if self.substitutionGroup() is not None:
1857            desc.extend([', substitutes for ', self.substitutionGroup()._description(name_only=True) ])
1858        if user_documentation and (self.documentation() is not None):
1859            desc.extend(["\n", self.documentation() ])
1860        return six.u('').join(desc)
1861
1862class enumeration_mixin (pyxb.cscRoot):
1863    """Marker in case we need to know that a PST has an enumeration constraint facet."""
1864
1865    _ReservedSymbols = set([ 'itervalues', 'values', 'iteritems', 'items' ])
1866
1867    @classmethod
1868    def itervalues (cls):
1869        """Return a generator for the values that the enumeration can take."""
1870        return six.itervalues(cls._CF_enumeration)
1871
1872    @classmethod
1873    def values (cls):
1874        """Return a list of values that the enumeration can take."""
1875        return list(cls.itervalues()) # nosix
1876
1877    @classmethod
1878    def iteritems (cls):
1879        """Generate the associated L{pyxb.binding.facet._EnumerationElement} instances."""
1880        return six.iteritems(cls._CF_enumeration)
1881
1882    @classmethod
1883    def items (cls):
1884        """Return the associated L{pyxb.binding.facet._EnumerationElement} instances."""
1885        return list(cls.iteritems()) # nosix
1886
1887    @classmethod
1888    def _elementForValue (cls, value):
1889        """Return the L{_EnumerationElement} instance that has the given value.
1890
1891        @raise KeyError: the value is not valid for the enumeration."""
1892        return cls._CF_enumeration.elementForValue(value)
1893
1894    @classmethod
1895    def _valueForUnicode (cls, ustr):
1896        """Return the enumeration value corresponding to the given unicode string.
1897
1898        If ustr is not a valid option for this enumeration, return None."""
1899        return cls._CF_enumeration.valueForUnicode(ustr)
1900
1901class _Content (object):
1902    """Base for any wrapper added to L{complexTypeDefinition.orderedContent}."""
1903
1904    def __getValue (self):
1905        """The value of the content.
1906
1907        This is a unicode string for L{NonElementContent}, and (ideally) an
1908        instance of L{_TypeBinding_mixin} for L{ElementContent}."""
1909        return self.__value
1910    __value = None
1911    value = property(__getValue)
1912
1913    @classmethod
1914    def ContentIterator (cls, input):
1915        """Return an iterator that filters and maps a sequence of L{_Content}
1916        instances.
1917
1918        The returned iterator will filter out sequence members that are not
1919        instances of the class from which the iterator was created.  Further,
1920        only the L{value} field of the sequence member is returned.
1921
1922        Thus the catenated text of the non-element content of an instance can
1923        be obtained with::
1924
1925           text = six.u('').join(NonElementContent.ContentIterator(instance.orderedContent()))
1926
1927        See also L{pyxb.NonElementContent}
1928        """
1929        class _Iterator (six.Iterator):
1930            def __init__ (self, input):
1931                self.__input = iter(input)
1932            def __iter__ (self):
1933                return self
1934            def __next__ (self):
1935                while True:
1936                    content = next(self.__input)
1937                    if isinstance(content, cls):
1938                        return content.value
1939        return _Iterator(input)
1940
1941    def __init__ (self, value):
1942        self.__value = value
1943
1944class ElementContent (_Content):
1945    """Marking wrapper for element content.
1946
1947    The value should be translated into XML and made a child of its parent."""
1948
1949    def __getElementDeclaration (self):
1950        """The L{pyxb.binding.content.ElementDeclaration} associated with the element content.
1951        This may be C{None} if the value is a wildcard."""
1952        return self.__elementDeclaration
1953    __elementDeclaration = None
1954
1955    elementDeclaration = property(__getElementDeclaration)
1956
1957    def __init__ (self, value, element_declaration=None, instance=None, tag=None):
1958        """Create a wrapper associating a value with its element declaration.
1959
1960        Normally the element declaration is determined by consulting the
1961        content model when creating a binding instance.  When manipulating the
1962        preferred content list, this may be inconvenient to obtain; in that case
1963        provide the C{instance} in which the content appears immediately,
1964        along with the C{tag} that is used for the Python attribute that holds
1965        the element.
1966
1967        @param value: the value of the element.  Should be an instance of
1968        L{_TypeBinding_mixin}, but for simple types might be a Python native
1969        type.
1970
1971        @keyword element_declaration: The
1972        L{pyxb.binding.content.ElementDeclaration} associated with the element
1973        value.  Should be C{None} if the element matches wildcard content.
1974
1975        @keyword instance: Alternative path to providing C{element_declaration}
1976        @keyword tag: Alternative path to providing C{element_declaration}
1977        """
1978
1979        import pyxb.binding.content
1980        super(ElementContent, self).__init__(value)
1981        if instance is not None:
1982            if not isinstance(instance, complexTypeDefinition):
1983                raise pyxb.UsageError('Unable to determine element declaration')
1984            element_declaration = instance._UseForTag(tag)
1985        assert (element_declaration is None) or isinstance(element_declaration, pyxb.binding.content.ElementDeclaration)
1986        self.__elementDeclaration = element_declaration
1987
1988class NonElementContent (_Content):
1989    """Marking wrapper for non-element content.
1990
1991    The value will be unicode text, and should be appended as character
1992    data."""
1993    def __init__ (self, value):
1994        super(NonElementContent, self).__init__(six.text_type(value))
1995
1996class complexTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1997    """Base for any Python class that serves as the binding for an
1998    XMLSchema complexType.
1999
2000    Subclasses should define a class-level _AttributeMap variable which maps
2001    from the unicode tag of an attribute to the AttributeUse instance that
2002    defines it.  Similarly, subclasses should define an _ElementMap variable.
2003    """
2004
2005    _CT_EMPTY = 'EMPTY'                 #<<< No content
2006    _CT_SIMPLE = 'SIMPLE'               #<<< Simple (character) content
2007    _CT_MIXED = 'MIXED'                 #<<< Children may be elements or other (e.g., character) content
2008    _CT_ELEMENT_ONLY = 'ELEMENT_ONLY'   #<<< Expect only element content.
2009
2010    _ContentTypeTag = None
2011
2012    _TypeDefinition = None
2013    """Subclass of simpleTypeDefinition that corresponds to the type content.
2014    Only valid if _ContentTypeTag is _CT_SIMPLE"""
2015
2016    # A value that indicates whether the content model for this type supports
2017    # wildcard elements.  Supporting classes should override this value.
2018    _HasWildcardElement = False
2019
2020    # Map from expanded names to ElementDeclaration instances
2021    _ElementMap = { }
2022    """Map from expanded names to ElementDeclaration instances."""
2023
2024    # Per-instance map from tags to attribute values for wildcard attributes.
2025    # Value is C{None} if the type does not support wildcard attributes.
2026    __wildcardAttributeMap = None
2027
2028    def wildcardAttributeMap (self):
2029        """Obtain access to wildcard attributes.
2030
2031        The return value is C{None} if this type does not support wildcard
2032        attributes.  If wildcard attributes are allowed, the return value is a
2033        map from QNames to the unicode string value of the corresponding
2034        attribute.
2035
2036        @todo: The map keys should be namespace extended names rather than
2037        QNames, as the in-scope namespace may not be readily available to the
2038        user.
2039        """
2040        return self.__wildcardAttributeMap
2041
2042    # Per-instance list of DOM nodes interpreted as wildcard elements.
2043    # Value is None if the type does not support wildcard elements.
2044    __wildcardElements = None
2045
2046    def wildcardElements (self):
2047        """Obtain access to wildcard elements.
2048
2049        The return value is C{None} if the content model for this type does not
2050        support wildcard elements.  If wildcard elements are allowed, the
2051        return value is a list of values corresponding to conformant
2052        unrecognized elements, in the order in which they were encountered.
2053        If the containing binding was created from an XML document and enough
2054        information was present to determine the binding of the member
2055        element, the value is a binding instance.  Otherwise, the value is the
2056        original DOM Element node.
2057        """
2058        return self.__wildcardElements
2059
2060    def __init__ (self, *args, **kw):
2061        """Create a new instance of this binding.
2062
2063        Arguments are used as transition values along the content model.
2064        Keywords are passed to the constructor of any simple content, or used
2065        to initialize attribute and element values whose L{id
2066        <content.ElementDeclaration.id>} (not L{name <content.ElementDeclaration.name>})
2067        matches the keyword.
2068
2069        @keyword _dom_node: The node to use as the source of binding content.
2070        @type _dom_node: C{xml.dom.Element}
2071
2072        @keyword _location: An optional instance of
2073        L{pyxb.utils.utility.Location} showing the origin the binding.  If
2074        C{None}, a value from C{_dom_node} is used if available.
2075
2076        @keyword _from_xml: See L{_TypeBinding_mixin.Factory}
2077
2078        @keyword _finalize_content_model: If C{True} the constructor invokes
2079        L{_TypeBinding_mixin._finalizeContentModel} prior to return.  The
2080        value defaults to C{False} when content is assigned through keyword
2081        parameters (bypassing the content model) or neither a C{_dom_node} nor
2082        positional element parameters have been provided, and to C{True} in
2083        all other cases.
2084        """
2085
2086        fallback_namespace = kw.pop('_fallback_namespace', None)
2087        is_nil = False
2088        dom_node = kw.pop('_dom_node', None)
2089        location = kw.pop('_location', None)
2090        from_xml = kw.pop('_from_xml', dom_node is not None)
2091        do_finalize_content_model = kw.pop('_finalize_content_model', None)
2092        if dom_node is not None:
2093            if (location is None) and isinstance(dom_node, pyxb.utils.utility.Locatable_mixin):
2094                location = dom_node._location()
2095            if xml.dom.Node.DOCUMENT_NODE == dom_node.nodeType:
2096                dom_node = dom_node.documentElement
2097            #kw['_validate_constraints'] = False
2098            is_nil = XSI.nil.getAttribute(dom_node)
2099            if is_nil is not None:
2100                is_nil = kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil)
2101        if location is not None:
2102            self._setLocation(location)
2103        if self._AttributeWildcard is not None:
2104            self.__wildcardAttributeMap = { }
2105        if self._HasWildcardElement:
2106            self.__wildcardElements = []
2107        if self._Abstract:
2108            raise pyxb.AbstractInstantiationError(type(self), location, dom_node)
2109        super(complexTypeDefinition, self).__init__(**kw)
2110        self.reset()
2111        self._setAttributesFromKeywordsAndDOM(kw, dom_node)
2112        did_set_kw_elt = False
2113        for fu in six.itervalues(self._ElementMap):
2114            iv = kw.pop(fu.id(), None)
2115            if iv is not None:
2116                did_set_kw_elt = True
2117                fu.set(self, iv)
2118        if do_finalize_content_model is None:
2119            do_finalize_content_model = not did_set_kw_elt
2120        if kw and kw.pop('_strict_keywords', True):
2121            [ kw.pop(_fkw, None) for _fkw in self._PyXBFactoryKeywords ]
2122            if kw:
2123                raise pyxb.UnprocessedKeywordContentError(self, kw)
2124        if 0 < len(args):
2125            if did_set_kw_elt:
2126                raise pyxb.UsageError('Cannot mix keyword and positional args for element initialization')
2127            self.extend(args, _from_xml=from_xml, _location=location)
2128        elif self._CT_SIMPLE == self._ContentTypeTag:
2129            value = self._TypeDefinition.Factory(_require_value=not self._isNil(), _dom_node=dom_node, _location=location, _nil=self._isNil(), _apply_attributes=False, *args)
2130            if value._constructedWithValue():
2131                self.append(value)
2132        elif dom_node is not None:
2133            self.extend(dom_node.childNodes[:], fallback_namespace)
2134        else:
2135            do_finalize_content_model = False
2136        if do_finalize_content_model:
2137            self._finalizeContentModel()
2138
2139    # Specify the symbols to be reserved for all CTDs.
2140    _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'wildcardElements', 'wildcardAttributeMap',
2141                             'xsdConstraintsOK', 'content', 'orderedContent', 'append', 'extend', 'value', 'reset' ]))
2142
2143    # None, or a reference to a pyxb.utils.fac.Automaton instance that defines
2144    # the content model for the type.
2145    _Automaton = None
2146
2147    @classmethod
2148    def _AddElement (cls, element):
2149        """Method used by generated code to associate the element binding with a use in this type.
2150
2151        This is necessary because all complex type classes appear in the
2152        module prior to any of the element instances (which reference type
2153        classes), so the association must be formed after the element
2154        instances are available."""
2155        return cls._UseForTag(element.name())._setElementBinding(element)
2156
2157    @classmethod
2158    def _UseForTag (cls, tag, raise_if_fail=True):
2159        """Return the ElementDeclaration object corresponding to the element name.
2160
2161        @param tag: The L{ExpandedName} of an element in the class."""
2162        try:
2163            rv = cls._ElementMap[tag]
2164        except KeyError:
2165            if raise_if_fail:
2166                raise
2167            rv = None
2168        return rv
2169
2170    def __childrenForDOM (self):
2171        """Generate a list of children in the order in which they should be
2172        added to the parent when creating a DOM representation of this
2173        object.
2174
2175        @note: This is only used when L{pyxb.RequireValidWhenGenerating} has
2176        disabled validation.  Consequently, it may not generate valid XML.
2177        """
2178        order = []
2179        for ed in six.itervalues(self._ElementMap):
2180            value = ed.value(self)
2181            if value is None:
2182                continue
2183            if isinstance(value, list) and ed.isPlural():
2184                order.extend([ ElementContent(_v, ed) for _v in value ])
2185                continue
2186            order.append(ElementContent(value, ed))
2187        return order
2188
2189    def _validatedChildren (self):
2190        """Provide the child elements and non-element content in an order
2191        consistent with the content model.
2192
2193        Returns a sequence of tuples representing a valid path through the
2194        content model where each transition corresponds to one of the member
2195        element instances within this instance.  The tuple is a pair
2196        comprising the L{content.ElementDeclaration} instance and the value for the
2197        transition.
2198
2199        If the content of the instance does not validate against the content
2200        model, an exception is raised.
2201
2202        @return: C{None} or a list as described above.
2203        """
2204        if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE):
2205            return []
2206        self._resetAutomaton()
2207        return self.__automatonConfiguration.sequencedChildren()
2208
2209    def _symbolSet (self):
2210        """Return a map from L{content.ElementDeclaration} instances to a list of
2211        values associated with that use.
2212
2213        This is used as the set of symbols available for transitions when
2214        validating content against a model.  Note that the original
2215        L{content.ElementUse} that may have validated the assignment of the
2216        symbol to the content is no longer available, which may result in a
2217        different order being generated by the content model.  Preservation of
2218        the original order mitigates this risk.
2219
2220        The value C{None} is used to provide the wildcard members, if any.
2221
2222        If an element use has no associated values, it must not appear in the
2223        returned map.
2224
2225        @raise pyxb.SimpleTypeValueError: when unable to convert element
2226        content to the binding declaration type.
2227        """
2228        rv = { }
2229        for eu in six.itervalues(self._ElementMap):
2230            value = eu.value(self)
2231            if value is None:
2232                continue
2233            converter = eu.elementBinding().compatibleValue
2234            if eu.isPlural():
2235                if 0 < len(value):
2236                    rv[eu] = [ converter(_v) for _v in value ]
2237            else:
2238                rv[eu] = [ converter(value)]
2239        wce = self.__wildcardElements
2240        if (wce is not None) and (0 < len(wce)):
2241            rv[None] = wce[:]
2242        return rv
2243
2244    def _validateAttributes (self):
2245        for au in six.itervalues(self._AttributeMap):
2246            au.validate(self)
2247
2248    def _validateBinding_vx (self):
2249        if self._isNil():
2250            if (self._IsSimpleTypeContent() and (self.__content is not None)) or self.__content:
2251                raise pyxb.ContentInNilInstanceError(self, self.__content)
2252            return True
2253        if self._IsSimpleTypeContent() and (self.__content is None):
2254            raise pyxb.SimpleContentAbsentError(self, self._location())
2255        order = self._validatedChildren()
2256        for content in order:
2257            if isinstance (content, NonElementContent):
2258                continue
2259            if isinstance(content.value, _TypeBinding_mixin):
2260                content.value.validateBinding()
2261            elif content.elementDeclaration is not None:
2262                _log.warning('Cannot validate value %s in field %s', content.value, content.elementDeclaration.id())
2263        self._validateAttributes()
2264        return True
2265
2266    def _setAttribute (self, attr_en, value_lex):
2267        au = self._AttributeMap.get(attr_en)
2268        if au is None:
2269            if self._AttributeWildcard is None:
2270                raise pyxb.UnrecognizedAttributeError(type(self), attr_en, self)
2271            self.__wildcardAttributeMap[attr_en] = value_lex
2272        else:
2273            au.set(self, value_lex, from_xml=True)
2274        return au
2275
2276    def xsdConstraintsOK (self, location=None):
2277        """Validate the content against the simple type.
2278
2279        @return: C{True} if the content validates against its type.
2280        @raise pyxb.NotSimpleContentError: this type does not have simple content.
2281        @raise pyxb.SimpleContentAbsentError: the content of this type has not been set
2282        """
2283        # @todo: type check
2284        if self._CT_SIMPLE != self._ContentTypeTag:
2285            raise pyxb.NotSimpleContentError(self)
2286        if self._isNil():
2287            return True
2288        if self.__content is None:
2289            if location is None:
2290                location = self._location()
2291            raise pyxb.SimpleContentAbsentError(self, location)
2292        return self.value().xsdConstraintsOK(location)
2293
2294    # __content is used in two ways: when complex content is used, it is as
2295    # documented in L{orderedContent}.  When simple content is used, it is as
2296    # documented in L{value}.
2297    __content = None
2298
2299    def orderedContent (self):
2300        """Return the element and non-element content of the instance in order.
2301
2302        This must be a complex type with complex content.  The return value is
2303        a list of the element and non-element content in a preferred order.
2304
2305        The returned list contains L{element<ElementContent>} and
2306        L{non-element<NonElementContent>} content in the order which it was
2307        added to the instance.  This may have been through parsing a document,
2308        constructing an instance using positional arguments, invoking the
2309        L{append} or L{extend} methods, or assigning directly to an instance
2310        attribute associated with an element binding.
2311
2312        @note: Be aware that assigning directly to an element attribute does not
2313        remove any previous value for the element from the content list.
2314
2315        @note: Be aware that element values directly appended to an instance
2316        attribute with list type (viz., that corresponds to an element that
2317        allows more than one occurrence) will not appear in the ordered
2318        content list.
2319
2320        The order in the list may influence the generation of documents
2321        depending on L{pyxb.ValidationConfig} values that apply to an
2322        instance.  Non-element content is emitted immediately prior to the
2323        following element in this list.  Any trailing non-element content is
2324        emitted after the last element in the content.  The list should
2325        include all element content.  Element content in this list that is not
2326        present within an element member of the binding instance may result in
2327        an error, or may be ignored.
2328
2329        @note: The returned value is mutable, allowing the caller to change
2330        the order to be used.
2331
2332        @raise pyxb.NotComplexContentError: this is not a complex type with mixed or element-only content
2333        """
2334        if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE):
2335            raise pyxb.NotComplexContentError(self)
2336        return self.__content
2337
2338    @classmethod
2339    def __WarnOnContent (cls):
2340        if cls.__NeedWarnOnContent:
2341            import traceback
2342            cls.__NeedWarnOnContent = False
2343            _log.warning('Deprecated complexTypeDefinition method "content" invoked\nPlease use "orderedContent"\n%s', ''.join(traceback.format_stack()[:-2]))
2344            pass
2345    __NeedWarnOnContent = True
2346
2347    def content (self):
2348        """Legacy interface for ordered content.
2349
2350        This version does not accurately distinguish non-element content from
2351        element content that happens to have unicode type.
2352
2353        @deprecated: use L{orderedContent}."""
2354        self.__WarnOnContent()
2355        if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE):
2356            raise pyxb.NotComplexContentError(self)
2357        return [ _v.value for _v in self.__content ]
2358
2359    def value (self):
2360        """Return the value of the element.
2361
2362        This must be a complex type with simple content.  The returned value
2363        is expected to be an instance of some L{simpleTypeDefinition} class.
2364
2365        @raise pyxb.NotSimpleContentError: this is not a complex type with simple content
2366        """
2367        if self._CT_SIMPLE != self._ContentTypeTag:
2368            raise pyxb.NotSimpleContentError(self)
2369        return self.__content
2370
2371    def _setValue (self, value):
2372        """Change the simple content value without affecting attributes."""
2373        if self._CT_SIMPLE != self._ContentTypeTag:
2374            raise pyxb.NotSimpleContentError(self)
2375        location = self._location()
2376        if self._isNil():
2377            if value is not None:
2378                raise pyxb.ContentInNilInstanceError(self, value, location)
2379        else:
2380            if not isinstance(value, self._TypeDefinition):
2381                value = self._TypeDefinition.Factory(value)
2382            self.__setContent(value)
2383            if self._validationConfig.forBinding:
2384                self.xsdConstraintsOK(location)
2385        return self
2386
2387    def _resetContent (self, reset_elements=False):
2388        if reset_elements:
2389            for eu in six.itervalues(self._ElementMap):
2390                eu.reset(self)
2391        nv = None
2392        if self._ContentTypeTag in (self._CT_MIXED, self._CT_ELEMENT_ONLY):
2393            nv = []
2394        return self.__setContent(nv)
2395
2396    __automatonConfiguration = None
2397    def _resetAutomaton (self):
2398        if self._Automaton is not None:
2399            if self.__automatonConfiguration is None:
2400                import pyxb.binding.content
2401                self.__automatonConfiguration = pyxb.binding.content.AutomatonConfiguration(self)
2402            self.__automatonConfiguration.reset()
2403        return self.__automatonConfiguration
2404
2405    def _automatonConfiguration (self):
2406        """For whitebox testing use only"""
2407        return self.__automatonConfiguration
2408
2409    def reset (self):
2410        """Reset the instance.
2411
2412        This resets all element and attribute fields, and discards any
2413        recorded content.  It resets the content model automaton to its
2414        initial state.
2415
2416        @see: Manipulate the return value of L{orderedContent} if your intent is
2417        to influence the generation of documents from the binding instance
2418        without changing its (element) content.
2419        """
2420
2421        self._resetContent(reset_elements=True)
2422        for au in six.itervalues(self._AttributeMap):
2423            au.reset(self)
2424        self._resetAutomaton()
2425        return self
2426
2427    @classmethod
2428    def _ElementBindingDeclForName (cls, element_name):
2429        """Determine what the given name means as an element in this type.
2430
2431        Normally, C{element_name} identifies an element definition within this
2432        type.  If so, the returned C{element_decl} identifies that definition,
2433        and the C{element_binding} is extracted from that use.
2434
2435        It may also be that the C{element_name} does not appear as an element
2436        definition, but that it identifies a global element.  In that case,
2437        the returned C{element_binding} identifies the global element.  If,
2438        further, that element is a member of a substitution group which does
2439        have an element definition in this class, then the returned
2440        C{element_decl} identifies that definition.
2441
2442        If a non-C{None} C{element_decl} is returned, there will be an
2443        associated C{element_binding}.  However, it is possible to return a
2444        non-C{None} C{element_binding}, but C{None} as the C{element_decl}.  In
2445        that case, the C{element_binding} can be used to create a binding
2446        instance, but the content model will have to treat it as a wildcard.
2447
2448        @param element_name: The name of the element in this type, either an
2449        expanded name or a local name if the element has an absent namespace.
2450
2451        @return: C{( element_binding, element_decl )}
2452        """
2453        element_decl = cls._ElementMap.get(element_name)
2454        element_binding = None
2455        if element_decl is None:
2456            try:
2457                element_binding = element_name.elementBinding()
2458            except pyxb.NamespaceError:
2459                pass
2460            if element_binding is not None:
2461                element_decl = element_binding.findSubstituendDecl(cls)
2462        else:
2463            element_binding = element_decl.elementBinding()
2464        return (element_binding, element_decl)
2465
2466    def append (self, value, **kw):
2467        """Add the value to the instance.
2468
2469        The value should be a DOM node or other value that is or can be
2470        converted to a binding instance, or a string if the instance allows
2471        mixed content.  The value must be permitted by the content model.
2472
2473        @raise pyxb.ContentValidationError: the value is not permitted at the current
2474        state of the content model.
2475        """
2476
2477        # @todo: Allow caller to provide default element use; it's available
2478        # in saxer.
2479        element_decl = kw.get('_element_decl', None)
2480        maybe_element = kw.get('_maybe_element', True)
2481        location = kw.get('_location', None)
2482        if self._isNil():
2483            raise pyxb.ContentInNilInstanceError(self, value, location)
2484        fallback_namespace = kw.get('_fallback_namespace', None)
2485        require_validation = kw.get('_require_validation', self._validationConfig.forBinding)
2486        from_xml = kw.get('_from_xml', False)
2487        element_binding = None
2488        if element_decl is not None:
2489            from pyxb.binding import content
2490            assert isinstance(element_decl, content.ElementDeclaration)
2491            element_binding = element_decl.elementBinding()
2492            assert element_binding is not None
2493        # Convert the value if it's XML and we recognize it.
2494        if isinstance(value, xml.dom.Node):
2495            from_xml = True
2496            assert maybe_element
2497            assert element_binding is None
2498            node = value
2499            require_validation = pyxb.GlobalValidationConfig.forBinding
2500            if xml.dom.Node.COMMENT_NODE == node.nodeType:
2501                # @todo: Note that we're allowing comments inside the bodies
2502                # of simple content elements, which isn't really Hoyle.
2503                return self
2504            if node.nodeType in (xml.dom.Node.TEXT_NODE, xml.dom.Node.CDATA_SECTION_NODE):
2505                value = node.data
2506                maybe_element = False
2507            else:
2508                # Do type conversion here
2509                assert xml.dom.Node.ELEMENT_NODE == node.nodeType
2510                expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace)
2511                (element_binding, element_decl) = self._ElementBindingDeclForName(expanded_name)
2512                if element_binding is not None:
2513                    # If we have an element binding, we need to use it because
2514                    # it knows how to resolve substitution groups.
2515                    value = element_binding._createFromDOM(node, expanded_name, _fallback_namespace=fallback_namespace)
2516                else:
2517                    # If we don't have an element binding, we might still be
2518                    # able to convert this if it has an xsi:type attribute
2519                    # that names a valid type.
2520                    xsi_type = XSI.type.getAttribute(node)
2521                    try_create = False
2522                    if xsi_type is not None:
2523                        ns_ctx = pyxb.namespace.NamespaceContext.GetNodeContext(node)
2524                        (try_create, type_class) = XSI._InterpretTypeAttribute(xsi_type, ns_ctx, fallback_namespace, None)
2525                    if try_create:
2526                        value = element.CreateDOMBinding(node, None, _fallback_namespace=fallback_namespace)
2527                    else:
2528                        _log.warning('Unable to convert DOM node %s at %s to binding', expanded_name, getattr(node, 'location', '[UNAVAILABLE]'))
2529        if (not maybe_element) and isinstance(value, six.string_types) and (self._ContentTypeTag in (self._CT_EMPTY, self._CT_ELEMENT_ONLY)):
2530            if (0 == len(value.strip())) and not self._isNil():
2531                return self
2532        if maybe_element and (self.__automatonConfiguration is not None):
2533            # Allows element content.
2534            if not require_validation:
2535                if element_decl is not None:
2536                    element_decl.setOrAppend(self, value)
2537                    return self
2538                if self.__wildcardElements is not None:
2539                    self._appendWildcardElement(value)
2540                    return self
2541                raise pyxb.StructuralBadDocumentError(container=self, content=value)
2542            # Attempt to place the value based on the content model
2543            num_cand = self.__automatonConfiguration.step(value, element_decl)
2544            if 1 <= num_cand:
2545                # Resolution was successful (possibly non-deterministic)
2546                return self
2547        # We couldn't place this thing.  If it's element content, it has
2548        # to be placed.  Is it element content?
2549        #
2550        # If it's bound to an element, it's element content.
2551        #
2552        # Complex type instance?  Element content.
2553        #
2554        # Uninterpretable DOM nodes or binding wrappers?  Element content.
2555        #
2556        # Simple type definition?  Well, if the thing we're trying to fill
2557        # accepts mixed content or has simple content, technically we
2558        # could convert the value to text and use it.  So that's not
2559        # element content.
2560        if ((element_binding is not None)
2561            or isinstance(value, (xml.dom.Node, complexTypeDefinition, pyxb.BIND))
2562            or (isinstance(value, simpleTypeDefinition) and not (self._IsSimpleTypeContent() or self._IsMixed()))):
2563            # Element content.  If it has an automaton we can provide more
2564            # information.  If it doesn't, it must consume text and we should
2565            # use a different exception.
2566            if self.__automatonConfiguration:
2567                raise pyxb.UnrecognizedContentError(self, self.__automatonConfiguration, value, location)
2568            raise pyxb.NonElementValidationError(value, location)
2569
2570        # We have something that doesn't seem to be an element.  Are we
2571        # expecting simple content?
2572        if self._IsSimpleTypeContent():
2573            if self.__content is not None:
2574                raise pyxb.ExtraSimpleContentError(self, value)
2575            if not self._isNil():
2576                if not isinstance(value, self._TypeDefinition):
2577                    value = self._TypeDefinition.Factory(value, _from_xml=from_xml)
2578                self.__setContent(value)
2579                if require_validation:
2580                    # NB: This only validates the value, not any associated
2581                    # attributes, which is correct to be parallel to complex
2582                    # content validation.
2583                    self.xsdConstraintsOK(location)
2584            return self
2585
2586        # Do we allow non-element content?
2587        if not self._IsMixed():
2588            raise pyxb.MixedContentError(self, value, location)
2589
2590        # It's character information.
2591        self._addContent(NonElementContent(value))
2592        return self
2593
2594    def _appendWildcardElement (self, value):
2595        if (isinstance(value, xml.dom.Node)
2596            or (isinstance(value, _TypeBinding_mixin) and (value._element is not None))):
2597            # Something that we can interpret as an element
2598            self._addContent(ElementContent(value, None))
2599            self.__wildcardElements.append(value)
2600        elif self._IsMixed():
2601            # Not an element, but allowed as mixed content
2602            self._addContent(NonElementContent(value))
2603        else:
2604            # Not an element and no mixed content allowed: error
2605            raise pyxb.MixedContentError(self, value)
2606
2607    def extend (self, value_list, _fallback_namespace=None, _from_xml=False, _location=None):
2608        """Invoke L{append} for each value in the list, in turn."""
2609        kw = { '_fallback_namespace': _fallback_namespace,
2610               '_from_xml': _from_xml,
2611               '_location': _location }
2612        [ self.append(_v, **kw) for _v in value_list ]
2613        return self
2614
2615    def __setContent (self, value):
2616        self.__content = value
2617        return self.__content
2618
2619    def _addContent (self, wrapped_value):
2620        # This assert is inadequate in the case of plural/non-plural elements with an STD_list base type.
2621        # Trust that validation elsewhere was done correctly.
2622        #assert self._IsMixed() or (not self._performValidation()) or isinstance(child, _TypeBinding_mixin) or isinstance(child, six.string_types), 'Unrecognized child %s type %s' % (child, type(child))
2623        assert not (self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE))
2624        assert isinstance(wrapped_value, _Content)
2625        self.__content.append(wrapped_value)
2626        if isinstance(wrapped_value, ElementContent):
2627            value = wrapped_value.value
2628            ed = wrapped_value.elementDeclaration
2629            if isinstance(value, _TypeBinding_mixin) and (ed is not None) and (value._element() is None):
2630                assert isinstance(ed.elementBinding(), element)
2631                value._setElement(ed.elementBinding())
2632
2633    @classmethod
2634    def _IsMixed (cls):
2635        return (cls._CT_MIXED == cls._ContentTypeTag)
2636
2637    def _finalizeContentModel (self):
2638        # Override parent implementation.
2639        if self.__automatonConfiguration:
2640            self.__automatonConfiguration.resolveNondeterminism()
2641
2642    def _postDOMValidate (self):
2643        # It's probably finalized already, but just in case...
2644        self._finalizeContentModel()
2645        if self._validationConfig.forBinding:
2646            # @todo isNil should verify that no content is present.
2647            if (not self._isNil()) and (self.__automatonConfiguration is not None):
2648                if not self.__automatonConfiguration.isAccepting():
2649                    if self._IsSimpleTypeContent():
2650                        raise pyxb.SimpleContentAbsentError(self, self._location())
2651                    self.__automatonConfiguration.diagnoseIncompleteContent()
2652            self._validateAttributes()
2653        return self
2654
2655    def _setDOMFromAttributes (self, dom_support, element):
2656        """Add any appropriate attributes from this instance into the DOM element."""
2657        for au in six.itervalues(self._AttributeMap):
2658            if pyxb.GlobalValidationConfig.forDocument:
2659                au.validate(self)
2660            au.addDOMAttribute(dom_support, self, element)
2661        if self.__wildcardAttributeMap:
2662            for (an, av) in six.iteritems(self.__wildcardAttributeMap):
2663                dom_support.addAttribute(element, an, av)
2664        return element
2665
2666    def _toDOM_csc (self, dom_support, parent):
2667        """Create a DOM element with the given tag holding the content of this instance."""
2668        element = parent
2669        self._setDOMFromAttributes(dom_support, element)
2670        if self._isNil():
2671            pass
2672        elif self._CT_EMPTY == self._ContentTypeTag:
2673            pass
2674        elif self._CT_SIMPLE == self._ContentTypeTag:
2675            if self.__content is None:
2676                raise pyxb.SimpleContentAbsentError(self, self._location())
2677            dom_support.appendTextChild(self.value(), element)
2678        else:
2679            if pyxb.GlobalValidationConfig.forDocument:
2680                order = self._validatedChildren()
2681            else:
2682                order = self.__childrenForDOM()
2683            for content in order:
2684                assert id(content.value) != id(self)
2685                if isinstance(content, NonElementContent):
2686                    dom_support.appendTextChild(content.value, element)
2687                    continue
2688                if content.elementDeclaration is None:
2689                    if isinstance(content.value, xml.dom.Node):
2690                        dom_support.appendChild(content.value, element)
2691                    else:
2692                        content.value.toDOM(dom_support, parent)
2693                else:
2694                    content.elementDeclaration.toDOM(dom_support, parent, content.value)
2695            mixed_content = self.orderedContent()
2696            for mc in mixed_content:
2697                pass
2698        return getattr(super(complexTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
2699
2700    @classmethod
2701    def _IsSimpleTypeContent (cls):
2702        """CTDs with simple content are simple; other CTDs are not."""
2703        return cls._CT_SIMPLE == cls._ContentTypeTag
2704
2705    @classmethod
2706    def _description (cls, name_only=False, user_documentation=True):
2707        name = cls._Name()
2708        if name_only:
2709            return name
2710        desc = [ name ]
2711        if cls._CT_EMPTY == cls._ContentTypeTag:
2712            desc.append(', empty content')
2713        elif cls._CT_SIMPLE == cls._ContentTypeTag:
2714            desc.extend([', simple content type ', cls._TypeDefinition._description(name_only=True)])
2715        else:
2716            if cls._CT_MIXED == cls._ContentTypeTag:
2717                desc.append(', mixed content')
2718            else:
2719                assert cls._CT_ELEMENT_ONLY == cls._ContentTypeTag
2720                desc.append(', element-only content')
2721        if (0 < len(cls._AttributeMap)) or (cls._AttributeWildcard is not None):
2722            desc.append("\nAttributes:\n  ")
2723            desc.append("\n  ".join([ _au._description(user_documentation=False) for _au in six.itervalues(cls._AttributeMap) ]))
2724            if cls._AttributeWildcard is not None:
2725                desc.append("\n  Wildcard attribute(s)")
2726        if (0 < len(cls._ElementMap)) or cls._HasWildcardElement:
2727            desc.append("\nElements:\n  ")
2728            desc.append("\n  ".join([ _eu._description(user_documentation=False) for _eu in six.itervalues(cls._ElementMap) ]))
2729            if cls._HasWildcardElement:
2730                desc.append("\n  Wildcard element(s)")
2731        return ''.join(desc)
2732
2733## Local Variables:
2734## fill-column:78
2735## End:
2736