1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Classes corresponding to W3C XML Schema components.
17
18 Class names and behavior should conform to the schema components described in
19 U{XML Schema Part 1: Structures<http://www.w3.org/TR/xmlschema-1/>}.
20 References to sections in the documentation of this module generally refers to
21 that document.
22
23 Each class has a C{CreateFromDOM} class method that creates an instance and
24 initializes it from a DOM node. Only the L{Wildcard}, L{Particle}, and
25 L{ModelGroup} components are created from non-DOM sources. However, the
26 requirements on DOM interface are restricted to attributes, child nodes, and
27 basic fields, though all these must support namespaces.
28
29 @group Mixins: *_mixin
30 @group Ur Type Specializations: *UrType*
31 @group Utilities: _ImportElementInformationItem
32
33 """
34
35 import re
36 import logging
37 from xml.dom import Node
38 import copy
39 from pyxb.utils.six.moves.urllib import parse as urlparse
40 import os.path
41
42 import pyxb
43 import pyxb.xmlschema
44 import pyxb.namespace.archive
45 import pyxb.namespace.resolution
46
47 from pyxb.binding import basis, datatypes, facets
48 from pyxb.utils import domutils, six
49 import pyxb.utils.utility
50
51 _log = logging.getLogger(__name__)
52
53
54 _PastAddBuiltInTypes = False
55
56
57 from pyxb.namespace import XMLSchema as xsd
58
59 -class _SchemaComponent_mixin (pyxb.namespace._ComponentDependency_mixin,
60 pyxb.namespace.archive._ArchivableObject_mixin,
61 pyxb.utils.utility.PrivateTransient_mixin,
62 pyxb.utils.utility.Locatable_mixin):
63 """A mix-in that marks the class as representing a schema component.
64
65 This exists so that we can determine the owning schema for any
66 component we encounter. This is normally done at construction
67 time by passing a C{schema=val} parameter to the constructor.
68 """
69
70
71
72 __PrivateTransient = set()
73
75 """The namespace context for this schema.
76
77 This defines where it looks things up, where it puts things it
78 creates, the in-scope namespace declarations, etc. Must be defined
79 for anything that does any sort of QName interpretation. The value is
80 generally a reference to a namespace context associated with the DOM
81 element node corresponding to this component."""
82 if self.__namespaceContext is None:
83 raise pyxb.LogicError('Attempt to access missing namespace context for %s' % (self,))
84 return self.__namespaceContext
86
87
88 self.schemaOrderSortKey()
89 self.__namespaceContext = None
90 return self
91 __namespaceContext = None
92 __PrivateTransient.add('namespaceContext')
93
94
95
96
97
98 __nameInBinding = None
99
100
101
102 __owner = None
103 __PrivateTransient.add('owner')
104
105
106 __ownedComponents = None
107 __PrivateTransient.add('ownedComponent')
108
110 """The context into which declarations in or subordinate to this node are placed."""
111 return self.__scope
112 __scope = None
113
117
121
123 """Set the scope of this instance after construction.
124
125 This should only be invoked on cloned declarations being incorporated
126 into a complex type definition. Note that the source of the clone may
127 be any scope: indeterminate if from a model (attribute) group
128 definition; global if a reference to a global component; or ctd if
129 inherited from a complex base type."""
130 assert self.__cloneSource is not None
131 assert isinstance(self, _ScopedDeclaration_mixin)
132 assert isinstance(ctd, ComplexTypeDefinition)
133 self.__scope = ctd
134 return self
135
137 """Initialize portions of a component.
138
139 @keyword scope: The scope in which the component is defined
140
141 @keyword namespace_context: The NamespaceContext to use within this component
142
143 @keyword node: If no C{namespace_context} is provided, a DOM node must
144 be provided from which a namespace context can be identified.
145
146 @keyword owner: Reference to the component that owns this one (the
147 immediately enclosing component). Is C{None} in the case of top-level
148 components.
149
150 @keyword schema: Reference to the L{Schema} component to which the
151 component belongs. Required for every component except L{Schema},
152 L{Annotation}, and L{Wildcard}.
153 """
154
155 self.__ownedComponents = set()
156 self.__scope = kw.get('scope')
157 self.__namespaceContext = kw.get('namespace_context')
158 node = kw.get('node')
159 owner = kw.get('owner')
160 if self.__namespaceContext is None:
161 if node is None:
162 raise pyxb.LogicError('Schema component constructor must be given namespace_context or node')
163 self.__namespaceContext = pyxb.namespace.NamespaceContext.GetNodeContext(node)
164 if self.__namespaceContext is None:
165 raise pyxb.LogicError('No namespace_context for schema component')
166
167 super(_SchemaComponent_mixin, self).__init__(*args, **kw)
168
169 self._namespaceContext().targetNamespace()._associateComponent(self)
170
171 self._setOwner(owner)
172 if isinstance(node, pyxb.utils.utility.Locatable_mixin):
173 self._setLocation(node._location())
174 elif isinstance(owner, pyxb.utils.utility.Locatable_mixin):
175 self._setLocation(owner._location())
176
177 schema = kw.get('schema')
178 if schema is not None:
179 self._setObjectOrigin(schema.originRecord())
180 else:
181 assert isinstance(self, (Schema, Annotation, Wildcard)), 'No origin available for type %s' % (type(self),)
182
183 if isinstance(self, ComplexTypeDefinition):
184 assert 1 < len(self.__namespaceContext.inScopeNamespaces())
185
187 """Dissociate this component from its owning namespace.
188
189 This should only be done whwen there are no other references to the
190 component, and you want to ensure it does not appear in the model."""
191 self._namespaceContext().targetNamespace()._replaceComponent(self, None)
192 return self
193
195 """Set the owner of this component.
196
197 If C{owner} is C{None}, this has no effect. Otherwise, the
198 component's current owner must be either C{None} or the same as the
199 input C{owner}."""
200
201 if owner is not None:
202 assert (self.__owner is None) or (self.__owner == owner), 'Owner was %s set to %s' % (self.__owner, owner)
203 self.__owner = owner
204 owner.__ownedComponents.add(self)
205 return self
206
209
210
211 __cloneSource = None
212 __PrivateTransient.add('cloneSource')
213
215 """The source component from which this is a clone.
216
217 Returns C{None} if this is not a clone."""
218 return self.__cloneSource
219
220
221 __clones = None
222 __PrivateTransient.add('clones')
223
225 """The set of instances cloned from this component.
226
227 Returns None if no instances have been cloned from this."""
228 return self.__clones
229
256
257 - def _clone (self, owner, origin):
281
286
291
293 """Return the name of this component, as best it can be determined.
294
295 For example, ModelGroup instances will be named by their
296 ModelGroupDefinition, if available. Returns None if no name can be
297 inferred."""
298 if isinstance(self, _NamedComponent_mixin):
299 return self.name()
300 if isinstance(self, ModelGroup):
301 agd = self.modelGroupDefinition()
302 if agd is not None:
303 return agd.name()
304 return None
305
307 """Return the name by which this component is known in the generated
308 binding.
309
310 @note: To support builtin datatypes, type definitions with an
311 associated L{pythonSupport<SimpleTypeDefinition.pythonSupport>} class
312 initialize their binding name from the class name when the support
313 association is created. As long as no built-in datatype conflicts
314 with a language keyword, this should be fine."""
315 return self.__nameInBinding
316
318 """Return C{True} iff this is a component which has a user-visible
319 Python construct which serves as its binding.
320
321 Type definitions have classes as their bindings. Global element
322 declarations have instances of L{pyxb.binding.basis.element} as their
323 bindings."""
324 return self.isTypeDefinition() or (isinstance(self, ElementDeclaration) and self._scopeIsGlobal())
325
327 """Set the name by which this component shall be known in the XSD binding."""
328 self.__nameInBinding = name_in_binding
329 return self
330
332 """Override fields in this instance with those from the other.
333
334 Post-extended; description in leaf implementation in
335 ComplexTypeDefinition and SimpleTypeDefinition."""
336 assert self != other
337 self_fn = lambda *_args, **_kw: self
338 getattr(super(_SchemaComponent_mixin, self), '_updateFromOther_csc', self_fn)(other)
339
340 if self.__nameInBinding is None:
341 self.__nameInBinding = other.__nameInBinding
342 return self
343
345 """A key to be used when sorting components for binding generation.
346
347 This is a tuple comprising the namespace URI, schema location, and
348 line and column of the component definition within the schema. The
349 purpose is to ensure consistent order of binding components in
350 generated code, to simplify maintenance involving the generated
351 sources.
352
353 To support Python 3 values that are C{None} are replaced with the
354 default value for whatever type belongs in the corresponding
355 position: (uri:str, locbase:str, locline:int, loccol:int) """
356 if self.__schemaOrderSortKey is None:
357 ns = None
358 if isinstance(self, _NamedComponent_mixin):
359 ns = self.bindingNamespace()
360 if ns is None:
361 ns = self._namespaceContext().targetNamespace()
362 elif isinstance(self, _ParticleTree_mixin):
363 ns = self._namespaceContext().targetNamespace()
364 ns_uri = ''
365 if (ns is not None) and (ns.uri() is not None):
366 ns_uri = ns.uri()
367 key_elts = [ns_uri]
368 loc = self._location()
369 v = ''
370 if (loc is not None) and (loc.locationBase is not None):
371 v = loc.locationBase
372 key_elts.append(v)
373 v = 0
374 if (loc is not None) and (loc.lineNumber is not None):
375 v = loc.lineNumber
376 key_elts.append(v)
377 v = 0
378 if (loc is not None) and (loc.columnNumber is not None):
379 v = loc.columnNumber
380 key_elts.append(v)
381 self.__schemaOrderSortKey = tuple(key_elts)
382 return self.__schemaOrderSortKey
383 __schemaOrderSortKey = None
384
386 """A sort key matching preferred content order.
387
388 This is an ordinal (integer) used to control which candidate
389 transitions are attempted first when testing symbols against the
390 content automaton state.
391
392 @note: The value associated with a node (especially a L{ModelGroup} or
393 L{Particle} will be different for different complex types, and is
394 valid only during generation of the automata code for a given type."""
395 assert self.__facStateSortKey is not None
396 return self.__facStateSortKey
397
399 """Set the automata state sort key.
400
401 @param key: the ordinal used for sorting."""
402 self.__facStateSortKey = key
403 __facStateSortKey = None
404 __PrivateTransient.add('facStateSortKey')
405
406 -class _ParticleTree_mixin (pyxb.cscRoot):
407 - def _walkParticleTree (self, visit, arg):
408 """Mix-in supporting walks of L{Particle} trees.
409
410 This invokes a provided function on each node in a tree defining the
411 content model of a particle, both on the way down the tree and on the
412 way back up. A standard implementation would be::
413
414 def _walkParticleTree (self, visit, arg):
415 visit(self, True, arg)
416 self.__term.walkParticleTree(visit, arg)
417 visit(self, False, arg)
418
419 @param visit: A callable with parameters C{node, entering, arg} where
420 C{node} is an instance of a class inheriting L{_ParticleTree_mixin},
421 C{entering} indicates tree transition status, and C{arg} is a
422 caller-provided state parameter. C{entering} is C{True} if C{node}
423 has particle children and the call is before they are visited;
424 C{None} if the C{node} has no particle children; and C{False} if
425 C{node} has particle children and they have been visited.
426
427 @param arg: The caller-provided state parameter to be passed along
428 with the node and entry/exit status in the invocation of C{visit}.
429 """
430 raise NotImplementedError('%s._walkParticleTree' % (self.__class__.__name__,))
431
433 """This class is a mix-in which guarantees that only one instance
434 of the class will be created. It is used to ensure that the
435 ur-type instances are pointer-equivalent even when unpickling.
436 See ComplexTypeDefinition.UrTypeDefinition()."""
438 singleton_property = '_%s__singleton' % (cls.__name__,)
439 if not (singleton_property in cls.__dict__):
440 setattr(cls, singleton_property, super(_Singleton_mixin, cls).__new__(cls, *args, **kw))
441 return cls.__dict__[singleton_property]
442
444 """Mix-in that supports an optional single annotation that describes the component.
445
446 Most schema components have annotations. The ones that don't are
447 L{AttributeUse}, L{Particle}, and L{Annotation}. L{ComplexTypeDefinition}
448 and L{Schema} support multiple annotations, so do not mix-in this
449 class."""
450
451
452 __annotation = None
453
457
465
467 """Override fields in this instance with those from the other.
468
469 Post-extended; description in leaf implementation in
470 ComplexTypeDefinition and SimpleTypeDefinition."""
471 assert self != other
472 self_fn = lambda *_args, **_kw: self
473 getattr(super(_Annotated_mixin, self), '_updateFromOther_csc', self_fn)(other)
474
475 self.__annotation = other.__annotation
476 return self
477
480
482 """A helper that encapsulates a reference to an anonymous type in a different namespace.
483
484 Normally references to components in other namespaces can be made using
485 the component's name. This is not the case when a namespace derives from
486 a base type in another namespace and needs to reference the attribute or
487 element declarations held in that type. If these declarations are local
488 to the base complex type, they cannot be identified by name. This class
489 provides a pickleable representation for them that behaves rather like an
490 L{pyxb.namespace.ExpandedName} instance in that it can be used to
491 dereference various component types."""
492
493 __AnonymousCategory = pyxb.namespace.archive.NamespaceArchive._AnonymousCategory()
494
495 __namespace = None
496 __anonymousName = None
497 - def __init__ (self, namespace, anonymous_name):
498 """Create a new anonymous reference.
499
500 @param namespace: The namespace in which the component is declared.
501 @type namespace: L{pyxb.namespace.Namespace}
502 @param anonymous_name: A generated name guaranteed to be unique within
503 the namespace. See L{_NamedComponent_mixin._anonymousName}.
504 @type anonymous_name: C{basestring}.
505 """
506 self.__namespace = namespace
507 self.__anonymousName = anonymous_name
508 assert self.__anonymousName is not None
509
510 @classmethod
512 """Return the component referred to by the provided reference,
513 regardless of whether it is a normal or anonymous reference."""
514 if not isinstance(object_reference, _PickledAnonymousReference):
515 assert isinstance(object_reference, tuple)
516 object_reference = pyxb.namespace.ExpandedName(object_reference)
517 return object_reference
518
521
524
528
531
532 typeDefinition = __lookupObject
533 attributeGroupDefinition = __lookupObject
534 modelGroupDefinition = __lookupObject
535 attributeDeclaration = __lookupObject
536 elementDeclaration = __lookupObject
537 identityConstraintDefinition = __lookupObject
538 notationDeclaration = __lookupObject
539
543
545 """Mix-in to hold the name and targetNamespace of a component.
546
547 The name may be None, indicating an anonymous component. The
548 targetNamespace is never None, though it could be an empty namespace. The
549 name and targetNamespace values are immutable after creation.
550
551 This class overrides the pickling behavior: when pickling a Namespace,
552 objects that do not belong to that namespace are pickled as references,
553 not as values. This ensures the uniqueness of objects when multiple
554 namespace definitions are pre-loaded.
555
556 This class must follow L{_SchemaComponent_mixin} in the MRO.
557 """
558
559 __PrivateTransient = set()
560
562 """Name of the component within its scope or namespace.
563
564 This is an NCName. The value isNone if the component is
565 anonymous. The attribute is immutable after the component is
566 created creation."""
567 return self.__name
568 __name = None
569
571 """Return true iff this instance is locally scoped (has no name)."""
572 return self.__name is None
573
598 __anonymousName = None
599
601 """The targetNamespace of a component.
602
603 This is None, or a reference to a Namespace in which the
604 component is declared (either as a global or local to one of
605 the namespace's complex type definitions). This is immutable
606 after creation.
607 """
608 return self.__targetNamespace
609 __targetNamespace = None
610
612 """The namespace in which this component's binding is placed."""
613 return self.__bindingNamespace
616 __bindingNamespace = None
617
619 """A map from template keys to component-specific values.
620
621 This is used in code generation to maintain unique names for accessor
622 methods, identifiers, keys, and other characteristics associated with
623 the code generated in support of the binding for this component."""
624 return self.__templateMap
625 __templateMap = None
626
627 __AnonymousCategory = pyxb.namespace.archive.NamespaceArchive._AnonymousCategory()
628
634
636 """Return the schema component from which this component was defined.
637
638 Needed so we can distinguish components that came from different
639 locations, since that imposes an external order dependency on them and
640 on cross-namespace inclusions.
641
642 @note: This characteristic is removed when the component is stored in
643 a namespace archive."""
644 return self.__schema
645 __schema = None
646 __PrivateTransient.add('schema')
647
653
655 """Return C{True} if this component should be pickled by value in the
656 given namespace.
657
658 When pickling, a declaration component is considered to belong to the
659 namespace if it has a local scope which belongs to the namespace. In
660 that case, the declaration is a clone of something that does not
661 belong to the namespace; but the clone does.
662
663 @see: L{_bindsInNamespace}
664
665 @return: C{False} if the component should be pickled by reference.
666 """
667 if isinstance(self._scope(), ComplexTypeDefinition):
668 return self._scope()._picklesInArchive(archive)
669 assert not (self.targetNamespace() is None), '%s has no tns, scope %s, location %s, schema %s' % (self, self._scope(), self._location(), self._schema().targetNamespace())
670 assert not (self._objectOrigin() is None)
671 new_flag = (self._objectOrigin().generationUID() == archive.generationUID())
672 return new_flag
673
675 """Return C{True} if the binding for this component should be
676 generated in the given namespace.
677
678 This is the case when the component is in the given namespace. It's
679 also the case when the component has no associated namespace (but not
680 an absent namespace). Be aware that cross-namespace inheritance means
681 you will get references to elements in another namespace when
682 generating code for a subclass; that's fine, and those references
683 should not be generated locally.
684 """
685 return self.targetNamespace() in (ns, None)
686
692
694 """Pickling support.
695
696 Normally, we just create a new instance of this class.
697 However, if we're unpickling a reference in a loadable schema,
698 we need to return the existing component instance by looking
699 up the name in the component map of the desired namespace. We
700 can tell the difference because no normal constructors that
701 inherit from this have positional arguments; only invocations
702 by unpickling with a value returned in __getnewargs__ do.
703
704 This does require that the dependent namespace already have
705 been validated (or that it be validated here). That shouldn't
706 be a problem, except for the dependency loop resulting from
707 use of xml:lang in the XMLSchema namespace. For that issue,
708 see pyxb.namespace._XMLSchema.
709 """
710
711 if 0 == len(args):
712 rv = super(_NamedComponent_mixin, cls).__new__(cls)
713 return rv
714 ( object_reference, scope, icls ) = args
715
716 object_reference = _PickledAnonymousReference.FromPickled(object_reference)
717
718
719
720 object_reference.validateComponentModel()
721 rv = None
722 if isinstance(scope, (tuple, _PickledAnonymousReference)):
723
724
725 scope_ref = _PickledAnonymousReference.FromPickled(scope)
726 if object_reference.namespace() != scope_ref.namespace():
727 scope_ref.validateComponentModel()
728 assert 'typeDefinition' in scope_ref.namespace().categories()
729 scope_ctd = scope_ref.typeDefinition()
730 if scope_ctd is None:
731 raise pyxb.SchemaValidationError('Unable to resolve local scope %s' % (scope_ref,))
732 if issubclass(icls, AttributeDeclaration):
733 rv = scope_ctd.lookupScopedAttributeDeclaration(object_reference)
734 elif issubclass(icls, ElementDeclaration):
735 rv = scope_ctd.lookupScopedElementDeclaration(object_reference)
736 if rv is None:
737 raise pyxb.SchemaValidationError('Unable to resolve %s as %s in scope %s' % (object_reference, icls, scope_ref))
738 elif _ScopedDeclaration_mixin.ScopeIsGlobal(scope) or _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope):
739 if (issubclass(icls, SimpleTypeDefinition) or issubclass(icls, ComplexTypeDefinition)):
740 rv = object_reference.typeDefinition()
741 elif issubclass(icls, AttributeGroupDefinition):
742 rv = object_reference.attributeGroupDefinition()
743 elif issubclass(icls, ModelGroupDefinition):
744 rv = object_reference.modelGroupDefinition()
745 elif issubclass(icls, AttributeDeclaration):
746 rv = object_reference.attributeDeclaration()
747 elif issubclass(icls, ElementDeclaration):
748 rv = object_reference.elementDeclaration()
749 elif issubclass(icls, IdentityConstraintDefinition):
750 rv = object_reference.identityConstraintDefinition()
751 if rv is None:
752 raise pyxb.SchemaValidationError('Unable to resolve %s as %s' % (object_reference, icls))
753 if rv is None:
754 raise pyxb.SchemaValidationError('Unable to resolve reference %s, scope %s ns %s type %s, class %s' % (object_reference, scope, (scope is None and "<unknown>" or scope.targetNamespace()), type(scope), icls))
755 return rv
756
777
779 """Return true iff this and the other component share the same name and target namespace.
780
781 Anonymous components are inherently name inequivalent, except to
782 themselves. This relies on equivalence as defined for
783 pyxb.namespace.ExpandedName, for which None is not equivalent to any
784 non-anonymous name."""
785
786 return (self == other) or ((not self.isAnonymous()) and (self.expandedName() == other.expandedName()))
787
789 """Return True iff this and the other component have matching types.
790
791 It appears that name equivalence is used; two complex type definitions
792 with identical structures are not considered equivalent (at least, per
793 XMLSpy).
794 """
795 return (type(self) == type(other)) and self.isNameEquivalent(other)
796
798 """Return True iff this type can serve as a restriction of the other
799 type for the purposes of U{element consistency<http://www.w3.org/TR/xmlschema-1/#cos-element-consistent>}.
800
801 It appears that name equivalence is normally used; two complex type
802 definitions with identical structures are not considered equivalent
803 (at least, per XMLSpy). However, some OpenGIS standards demonstrate
804 that derivation by restriction from the other type is also acceptable.
805 That opens a whole can of worms; see
806 L{ElementDeclaration.isAdaptable}.
807 """
808 this = self
809
810 while this is not None:
811 if this.isTypeEquivalent(other):
812 return True
813
814 assert this.isResolved() and other.isResolved()
815 if isinstance(self, ComplexTypeDefinition):
816 if self.DM_restriction != this.derivationMethod():
817 return False
818 else:
819 assert isinstance(self, SimpleTypeDefinition)
820 if self._DA_restriction != this._derivationAlternative():
821 return False
822 if not this.baseTypeDefinition().isDerivationConsistent(other):
823 return False
824 this = this.baseTypeDefinition()
825 return False
826
832
850
875
877 """Pickling support.
878
879 If this instance is being pickled as a reference, provide the
880 arguments that are necessary so that the unpickler can locate
881 the appropriate component rather than create a duplicate
882 instance."""
883
884 if self.__pickleAsReference():
885 scope = self._scope()
886 if isinstance(self, _ScopedDeclaration_mixin):
887
888
889
890
891
892 if self.SCOPE_global == self.scope():
893 pass
894 elif isinstance(self.scope(), ComplexTypeDefinition):
895 scope = self.scope()._picklingReference()
896 assert isinstance(scope, (tuple, _PickledAnonymousReference)), self
897 else:
898 assert self._scopeIsIndeterminate()
899
900
901 else:
902 assert isinstance(self, _NamedComponent_mixin), 'Pickling unnamed component %s in indeterminate scope by reference' % (self,)
903 assert not isinstance(scope, ComplexTypeDefinition), '%s %s %s %s' % (self, self.name(), scope, self._objectOrigin())
904
905 rv = ( self._picklingReference(), scope, self.__class__ )
906 return rv
907 return ()
908
925
935
937 """Mix-in indicating that the component contains a simple-type
938 value that may be constrained."""
939
940 VC_na = 0
941 VC_default = 1
942 VC_fixed = 2
943
944
945
946 __valueConstraint = None
948 """A constraint on the value of the attribute or element.
949
950 Either None, or a pair consisting of a string in the lexical
951 space of the typeDefinition and one of VC_default and
952 VC_fixed."""
953 return self.__valueConstraint
954
963
972
989
991 """Mix-in class for named components that have a scope.
992
993 Scope is important when doing cross-namespace inheritance,
994 e.g. extending or restricting a complex type definition that is
995 from a different namespace. In this case, we will need to retain
996 a reference to the external component when the schema is
997 serialized.
998
999 This is done in the pickling process by including the scope when
1000 pickling a component as a reference. The scope is the
1001 SCOPE_global if global; otherwise, it is a tuple containing the
1002 external namespace URI and the NCName of the complex type
1003 definition in that namespace. We assume that the complex type
1004 definition has global scope; otherwise, it should not have been
1005 possible to extend or restrict it. (Should this be untrue, there
1006 are comments in the code about a possible solution.)
1007
1008 @warning: This mix-in must follow L{_NamedComponent_mixin} in the C{mro}.
1009 """
1010
1011 SCOPE_global = 'global'
1012 XSCOPE_indeterminate = 'indeterminate'
1013
1014 @classmethod
1017
1018 @classmethod
1021
1022 @classmethod
1025
1027 """Return True if this scope currently assigned to this instance is compatible with the given scope.
1028
1029 If either scope is indeterminate, presume they will ultimately be
1030 compatible. Scopes that are equal are compatible, as is a local scope
1031 if this already has a global scope."""
1032 if self.ScopeIsIndeterminate(scope) or self.ScopeIsIndeterminate(self.scope()):
1033 return True
1034 if self.scope() == scope:
1035 return True
1036 return (self.SCOPE_global == self.scope()) and isinstance(scope, ComplexTypeDefinition)
1037
1038
1039
1040
1042 """The scope for the declaration.
1043
1044 Valid values are SCOPE_global, or a complex type definition.
1045 A value of None means a non-global declaration that is not
1046 owned by a complex type definition. These can only appear in
1047 attribute group definitions, model group definitions, and element
1048 declarations.
1049
1050 @todo: For declarations in named model groups (viz., local
1051 elements that aren't references), the scope needs to be set by
1052 the owning complex type.
1053 """
1054 return self._scope()
1055
1056
1057
1058
1059
1060 __baseDeclaration = None
1066
1068 """Support for components that accept attribute wildcards.
1069
1070 That is L{AttributeGroupDefinition} and L{ComplexTypeDefinition}. The
1071 calculations of the appropriate wildcard are sufficiently complex that
1072 they need to be abstracted out to a mix-in class."""
1073
1074
1075 __attributeWildcard = None
1076
1078 """Return the L{Wildcard} component associated with attributes of this
1079 instance, or C{None} if attribute wildcards are not present in the
1080 instance."""
1081 return self.__attributeWildcard
1082
1084 """Set the attribute wildcard property for this instance."""
1085 assert (attribute_wildcard is None) or isinstance(attribute_wildcard, Wildcard)
1086 self.__attributeWildcard = attribute_wildcard
1087 return self
1088
1090 """Return the nodes that are relevant for attribute processing.
1091
1092 @param node_list: A sequence of nodes found in a definition content
1093 information item.
1094
1095 @return: A tuple C{( attributes, attributeGroups, attributeWildcard)}
1096 where C{attributes} is the subsequence of C{node_list} that are
1097 XMLSchema C{attribute} nodes; C{attributeGroups} is analogous; and
1098 C{attributeWildcard} is a single DOM node with XMLSchema name
1099 C{anyAttribute} (or C{None}, if no such node is present in the list).
1100
1101 @raise pyxb.SchemaValidationError: An C{attributeGroup} node is
1102 present but does not have the required C{ref} attribute.
1103 @raise pyxb.SchemaValidationError: Multiple C{anyAttribute} nodes are
1104 identified.
1105 """
1106
1107 attributes = []
1108 attribute_groups = []
1109 any_attribute = None
1110
1111 for node in node_list:
1112 if Node.ELEMENT_NODE != node.nodeType:
1113 continue
1114 if xsd.nodeIsNamed(node, 'attribute'):
1115
1116 attributes.append(node)
1117 elif xsd.nodeIsNamed(node, 'attributeGroup'):
1118
1119 agd_en = domutils.NodeAttributeQName(node, 'ref')
1120 if agd_en is None:
1121 raise pyxb.SchemaValidationError('Require ref attribute on internal attributeGroup elements')
1122 attribute_groups.append(agd_en)
1123 elif xsd.nodeIsNamed(node, 'anyAttribute'):
1124 if any_attribute is not None:
1125 raise pyxb.SchemaValidationError('Multiple anyAttribute children are not allowed')
1126 any_attribute = node
1127
1128 return (attributes, attribute_groups, any_attribute)
1129
1130 @classmethod
1131 - def CompleteWildcard (cls, namespace_context, attribute_groups, local_wildcard):
1132 """Implement the algorithm as described the
1133 U{specification<http://www.w3.org/TR/xmlschema-1/#declare-type>}.
1134
1135 @param namespace_context: The L{pyxb.namespace.NamespaceContext} to be
1136 associated with any created L{Wildcard} instance
1137 @param attribute_groups: A list of L{AttributeGroupDefinition} instances
1138 @param local_wildcard: A L{Wildcard} instance computed from a relevant
1139 XMLSchema C{anyAttribute} element, or C{None} if no attribute wildcard
1140 is relevant
1141 """
1142
1143
1144 agd_wildcards = []
1145 for agd in attribute_groups:
1146 assert isinstance(agd, AttributeGroupDefinition)
1147 if agd.attributeWildcard() is not None:
1148 agd_wildcards.append(agd.attributeWildcard())
1149 agd_constraints = [ _agd.namespaceConstraint() for _agd in agd_wildcards ]
1150
1151
1152 if 0 == len(agd_wildcards):
1153 return local_wildcard
1154
1155 if local_wildcard is not None:
1156
1157 return Wildcard(process_contents=local_wildcard.processContents(),
1158 namespace_constraint=Wildcard.IntensionalIntersection(agd_constraints + [local_wildcard.namespaecConstraint()]),
1159 annotation=local_wildcard.annotation(),
1160 namespace_context=namespace_context)
1161
1162 return Wildcard(process_contents=agd_wildcards[0].processContents(),
1163 namespace_constraint=Wildcard.IntensionalIntersection(agd_constraints),
1164 namespace_context=namespace_context)
1165
1166 -class AttributeDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _ValueConstraint_mixin, _ScopedDeclaration_mixin):
1167 """An XMLSchema U{Attribute Declaration<http://www.w3.org/TR/xmlschema-1/#cAttribute_Declarations>} component.
1168 """
1169
1170
1171 __typeDefinition = None
1173 """The simple type definition to which an attribute value must
1174 conform."""
1175 return self.__typeDefinition
1176
1177
1178 __typeExpandedName = None
1179
1183
1188
1189 @classmethod
1202
1203
1204 @classmethod
1206 """Create an attribute declaration from the given DOM node.
1207
1208 wxs is a Schema instance within which the attribute is being
1209 declared.
1210
1211 node is a DOM element. The name must be one of ( 'all',
1212 'choice', 'sequence' ), and the node must be in the XMLSchema
1213 namespace.
1214
1215 scope is the _ScopeDeclaration_mxin context into which the
1216 attribute declaration is placed. It can be SCOPE_global, a
1217 complex type definition, or XSCOPE_indeterminate if this is an
1218 anonymous declaration within an attribute group. It is a
1219 required parameter for this function.
1220 """
1221
1222 scope = kw['scope']
1223 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope)
1224
1225
1226 assert xsd.nodeIsNamed(node, 'attribute')
1227
1228 name = domutils.NodeAttribute(node, 'name')
1229
1230
1231 if xsd.nodeIsNamed(node.parentNode, 'schema'):
1232 assert cls.SCOPE_global == scope
1233 elif domutils.NodeAttribute(node, 'ref') is None:
1234
1235 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
1236 else:
1237 raise pyxb.SchemaValidationError('Internal attribute declaration by reference')
1238
1239 rv = cls(name=name, node=node, **kw)
1240 rv._annotationFromDOM(node)
1241 rv._valueConstraintFromDOM(node)
1242
1243 rv.__typeExpandedName = domutils.NodeAttributeQName(node, 'type')
1244
1245 kw.pop('node', None)
1246 kw['owner'] = rv
1247
1248 st_node = domutils.LocateUniqueChild(node, 'simpleType')
1249 if st_node is not None:
1250 rv.__typeDefinition = SimpleTypeDefinition.CreateFromDOM(st_node, **kw)
1251 elif rv.__typeExpandedName is None:
1252 rv.__typeDefinition = SimpleTypeDefinition.SimpleUrTypeDefinition()
1253
1254 if rv.__typeDefinition is None:
1255 rv._queueForResolution('creation')
1256 return rv
1257
1260
1261
1276
1278 """Override fields in this instance with those from the other.
1279
1280 This method is invoked only by Schema._addNamedComponent, and
1281 then only when a built-in type collides with a schema-defined
1282 type. Material like facets is not (currently) held in the
1283 built-in copy, so the DOM information is copied over to the
1284 built-in STD, which is subsequently re-resolved.
1285
1286 Returns self.
1287 """
1288 assert self != other
1289 assert self.name() is not None
1290 assert self.isNameEquivalent(other)
1291 super(AttributeDeclaration, self)._updateFromOther_csc(other)
1292
1293
1294
1295 if not other.isResolved():
1296 if pyxb.namespace.BuiltInObjectUID == self._objectOrigin().generationUID():
1297
1298 _log.warning('Not destroying builtin %s: %s', self.expandedName(), self.__typeDefinition)
1299 else:
1300 self.__typeDefinition = None
1301 return self
1302
1303
1305 """Attribute declarations require their type."""
1306 return frozenset([ self.__typeDefinition ])
1307
1308 -class AttributeUse (_SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _ValueConstraint_mixin):
1309 """An XMLSchema U{Attribute Use<http://www.w3.org/TR/xmlschema-1/#cAttribute_Use>} component."""
1310
1311
1312
1313 __use = None
1314
1315 USE_required = 0x01
1316 USE_optional = 0x02
1317 USE_prohibited = 0x04
1318
1321
1324
1325
1326 __refExpandedName = None
1327
1328 __restrictionOf = None
1336
1337
1339 """The attribute declaration for this use.
1340
1341 When the use scope is assigned, the declaration is cloned (if
1342 necessary) so that each declaration corresponds to only one use. We
1343 rely on this in code generation, because the template map for the use
1344 is stored in its declaration."""
1345 return self.__attributeDeclaration
1346 __attributeDeclaration = None
1347
1348
1351
1366
1367 @classmethod
1376
1377
1378 @classmethod
1380 """Create an Attribute Use from the given DOM node.
1381
1382 wxs is a Schema instance within which the attribute use is
1383 being defined.
1384
1385 node is a DOM element. The name must be 'attribute', and the
1386 node must be in the XMLSchema namespace.
1387
1388 scope is the _ScopeDeclaration_mixin context into which any
1389 required anonymous attribute declaration is put. This must be
1390 a complex type definition, or None if this use is in an
1391 attribute group.
1392 """
1393
1394 scope = kw['scope']
1395 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
1396 assert xsd.nodeIsNamed(node, 'attribute')
1397 schema = kw['schema']
1398 rv = cls(node=node, **kw)
1399
1400 rv.__use = cls.USE_optional
1401 use = domutils.NodeAttribute(node, 'use')
1402 if use is not None:
1403 if 'required' == use:
1404 rv.__use = cls.USE_required
1405 elif 'optional' == use:
1406 rv.__use = cls.USE_optional
1407 elif 'prohibited' == use:
1408 rv.__use = cls.USE_prohibited
1409 else:
1410 raise pyxb.SchemaValidationError('Unexpected value %s for attribute use attribute' % (use,))
1411
1412 rv._valueConstraintFromDOM(node)
1413
1414 rv.__refExpandedName = domutils.NodeAttributeQName(node, 'ref')
1415 if rv.__refExpandedName is None:
1416
1417 kw.pop('node', None)
1418 kw['owner'] = rv
1419 kw['target_namespace'] = schema.targetNamespaceForNode(node, AttributeDeclaration)
1420 rv.__attributeDeclaration = AttributeDeclaration.CreateFromDOM(node, **kw)
1421
1422 if not rv.isResolved():
1423 rv._queueForResolution('creation')
1424
1425 return rv
1426
1429
1440
1441
1443 """Attribute uses require their declarations, but only if lax."""
1444 if not include_lax:
1445 return frozenset()
1446 return frozenset([ self.attributeDeclaration() ])
1447
1448
1468
1471
1472
1473 -class ElementDeclaration (_ParticleTree_mixin, _SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _ValueConstraint_mixin, _ScopedDeclaration_mixin):
1474 """An XMLSchema U{Element Declaration<http://www.w3.org/TR/xmlschema-1/#cElement_Declarations>} component."""
1475
1476
1477 __typeDefinition = None
1479 """The simple or complex type to which the element value conforms."""
1480 return self.__typeDefinition
1504
1505 __substitutionGroupExpandedName = None
1506
1507 __typeExpandedName = None
1508
1509 __nillable = False
1512
1513 __identityConstraintDefinitions = None
1517
1518 __substitutionGroupAffiliation = None
1522
1523 SGE_none = 0
1524 SGE_extension = 0x01
1525 SGE_restriction = 0x02
1526 SGE_substitution = 0x04
1527
1528 _SGE_Map = { 'extension' : SGE_extension
1529 , 'restriction' : SGE_restriction }
1530 _DS_Map = _SGE_Map.copy()
1531 _DS_Map.update( { 'substitution' : SGE_substitution } )
1532
1533
1534 __substitutionGroupExclusions = SGE_none
1535
1536
1537 __disallowedSubstitutions = SGE_none
1538
1539 __abstract = False
1542
1544 """Return False, since element declarations are not wildcards."""
1545 return False
1546
1547
1549 """Element declarations depend on the type definition of their
1550 content."""
1551 return frozenset([self.__typeDefinition])
1552
1555
1556
1557 @classmethod
1559 """Create an element declaration from the given DOM node.
1560
1561 wxs is a Schema instance within which the element is being
1562 declared.
1563
1564 scope is the _ScopeDeclaration_mixin context into which the
1565 element declaration is recorded. It can be SCOPE_global, a
1566 complex type definition, or None in the case of elements
1567 declared in a named model group.
1568
1569 node is a DOM element. The name must be 'element', and the
1570 node must be in the XMLSchema namespace."""
1571
1572 scope = kw['scope']
1573 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope)
1574
1575
1576 assert xsd.nodeIsNamed(node, 'element')
1577
1578
1579 name = domutils.NodeAttribute(node, 'name')
1580 if xsd.nodeIsNamed(node.parentNode, 'schema'):
1581 assert _ScopedDeclaration_mixin.SCOPE_global == scope
1582 elif domutils.NodeAttribute(node, 'ref') is None:
1583
1584 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
1585 else:
1586 raise pyxb.SchemaValidationError('Created reference as element declaration')
1587
1588 rv = cls(name=name, node=node, **kw)
1589 rv._annotationFromDOM(node)
1590 rv._valueConstraintFromDOM(node)
1591
1592 rv.__substitutionGroupExpandedName = domutils.NodeAttributeQName(node, 'substitutionGroup')
1593
1594 kw.pop('node', None)
1595 kw['owner'] = rv
1596
1597
1598
1599
1600
1601 if rv._scopeIsGlobal():
1602 kw['scope'] = _ScopedDeclaration_mixin.XSCOPE_indeterminate
1603
1604 identity_constraints = []
1605 for cn in node.childNodes:
1606 if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'key', 'unique', 'keyref'):
1607 identity_constraints.append(IdentityConstraintDefinition.CreateFromDOM(cn, **kw))
1608 rv.__identityConstraintDefinitions = identity_constraints
1609
1610 rv.__typeDefinition = None
1611 rv.__typeExpandedName = domutils.NodeAttributeQName(node, 'type')
1612 simpleType_node = domutils.LocateUniqueChild(node, 'simpleType')
1613 complexType_node = domutils.LocateUniqueChild(node, 'complexType')
1614 if rv.__typeExpandedName is not None:
1615 if (simpleType_node is not None) and (complexType_node is not None):
1616 raise pyxb.SchemaValidationError('Cannot combine type attribute with simpleType or complexType child')
1617 if (rv.__typeDefinition is None) and (simpleType_node is not None):
1618 rv._typeDefinition(SimpleTypeDefinition.CreateFromDOM(simpleType_node, **kw))
1619 if (rv.__typeDefinition is None) and (complexType_node is not None):
1620 rv._typeDefinition(ComplexTypeDefinition.CreateFromDOM(complexType_node, **kw))
1621 if rv.__typeDefinition is None:
1622 if rv.__typeExpandedName is None:
1623
1624 for cn in node.childNodes:
1625 if Particle.IsParticleNode(cn):
1626 raise pyxb.SchemaValidationError('Node %s in element must be wrapped by complexType.' % (cn.localName,))
1627 rv._typeDefinition(ComplexTypeDefinition.UrTypeDefinition())
1628 rv.__isResolved = (rv.__typeDefinition is not None) and (rv.__substitutionGroupExpandedName is None)
1629 if not rv.__isResolved:
1630 rv._queueForResolution('creation')
1631
1632 attr_val = domutils.NodeAttribute(node, 'nillable')
1633 if attr_val is not None:
1634 rv.__nillable = datatypes.boolean(attr_val)
1635
1636 attr_val = domutils.NodeAttribute(node, 'abstract')
1637 if attr_val is not None:
1638 rv.__abstract = datatypes.boolean(attr_val)
1639
1640 schema = kw['schema']
1641 rv.__disallowedSubstitutions = schema.blockForNode(node, cls._DS_Map)
1642 rv.__substitutionGroupExclusions = schema.finalForNode(node, cls._SGE_Map)
1643
1644 return rv
1645
1647 """Determine whether this element declaration is adaptable.
1648
1649 OK, this gets ugly. First, if this declaration isn't resolved, it's
1650 clearly not adaptable.
1651
1652 Now: For it to be adaptable, we must know enough about its type to
1653 verify that it is derivation-consistent with any other uses of the
1654 same name in the same complex type. If the element's type is
1655 resolved, that's good enough.
1656
1657 If the element's type isn't resolved, we're golden as long as
1658 type-equivalent types were used. But it's also allowed for the
1659 derived ctd to use the element name constraining it to a derivation of
1660 the element base type. (Go see namespace
1661 http://www.opengis.net/ows/1.1 types PositionType, PositionType2D,
1662 BoundingBox, and WGS84BoundingBox for an example). So, we really do
1663 have to have the element's type resolved.
1664
1665 Except that if a CTD's content incorporates an element with the same
1666 type as the CTD (i.e., nested), this will never happen, because the
1667 CTD can't get resolved until after it has been resolved.
1668 (Go see {http://www.opengis.net/ows/1.1}ContentsBaseType and
1669 {http://www.opengis.net/ows/1.1}DatasetDescriptionSummaryBaseType for
1670 an example).
1671
1672 So, we give the world a break and assume that if the type we're trying
1673 to resolve is the same as the type of an element in that type, then
1674 the element type will be resolved by the point it's needed. In point
1675 of fact, it won't, but we'll only notice that if a CTD contains an
1676 element whose type is a restriction of the CTD. In that case,
1677 isDerivationConsistent will blow chunks and somebody'll have to come
1678 back and finish up this mess.
1679 """
1680
1681 if not self.isResolved():
1682 return False
1683 if self.typeDefinition().isResolved():
1684 return True
1685
1686
1687 existing_decl = ctd.lookupScopedElementDeclaration(self.expandedName())
1688 if existing_decl is None:
1689
1690
1691 return True
1692
1693 if self.typeDefinition().isTypeEquivalent(existing_decl.typeDefinition()):
1694
1695 return True
1696
1697
1698 _log.warning('Require %s to be resolved; might be a loop.', self.typeDefinition())
1699 return False
1700
1701
1711
1712 __isResolved = False
1715
1716
1737
1738 - def _walkParticleTree (self, visit, arg):
1739 visit(self, None, arg)
1740
1745
1746
1747 -class ComplexTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
1748 __PrivateTransient = set()
1749
1750
1751 __baseTypeDefinition = None
1755
1756 DM_empty = 0
1757 DM_extension = 0x01
1758 DM_restriction = 0x02
1759
1760 _DM_Map = { 'extension' : DM_extension
1761 , 'restriction' : DM_restriction }
1762
1763
1764
1765 __derivationMethod = None
1769
1770
1771 __final = DM_empty
1772
1773
1774 __abstract = False
1777
1778
1779 __attributeUses = None
1781 """A frozenset() of AttributeUse instances."""
1782 return self.__attributeUses
1783
1784
1785
1786 __scopedAttributeDeclarations = None
1788 """Find an attribute declaration with the given name that is local to this type.
1789
1790 Returns None if there is no such local attribute declaration."""
1791 if self.__scopedAttributeDeclarations is None:
1792 return None
1793 return self.__scopedAttributeDeclarations.get(expanded_name)
1794
1795
1796
1797 __scopedElementDeclarations = None
1799 """Find an element declaration with the given name that is local to this type.
1800
1801 Returns None if there is no such local element declaration."""
1802 if self.__scopedElementDeclarations is None:
1803 return None
1804 return self.__scopedElementDeclarations.get(expanded_name)
1805
1806 __localScopedDeclarations = None
1828
1830 """Record the given declaration as being locally scoped in
1831 this type."""
1832 assert isinstance(decl, _ScopedDeclaration_mixin)
1833 if isinstance(decl, ElementDeclaration):
1834 scope_map = self.__scopedElementDeclarations
1835 elif isinstance(decl, AttributeDeclaration):
1836 scope_map = self.__scopedAttributeDeclarations
1837 else:
1838 raise pyxb.LogicError('Unexpected instance of %s recording as local declaration' % (type(decl),))
1839 decl_en = decl.expandedName()
1840 existing_decl = scope_map.setdefault(decl_en, decl)
1841 if decl != existing_decl:
1842 if isinstance(decl, ElementDeclaration):
1843
1844 existing_type = existing_decl.typeDefinition()
1845 pending_type = decl.typeDefinition()
1846 if not pending_type.isDerivationConsistent(existing_type):
1847 raise pyxb.SchemaValidationError('Conflicting element declarations for %s: existing %s versus new %s' % (decl.expandedName(), existing_type, pending_type))
1848 elif isinstance(decl, AttributeDeclaration):
1849 raise pyxb.SchemaValidationError('Multiple attribute declarations for %s' % (decl.expandedName(),))
1850 else:
1851 assert False, 'Unrecognized type %s' % (type(decl),)
1852 decl._baseDeclaration(existing_decl)
1853 return self
1854
1860
1861 CT_EMPTY = 'EMPTY'
1862 CT_SIMPLE = 'SIMPLE'
1863 CT_MIXED = 'MIXED'
1864 CT_ELEMENT_ONLY = 'ELEMENT_ONLY'
1865
1866 - def _contentTypeTag (self):
1867 """Return the value of the content type identifier, i.e. one of the
1868 CT_ constants. Return value is None if no content type has been
1869 defined."""
1870 if isinstance(self.__contentType, tuple):
1871 return self.__contentType[0]
1872 return self.__contentType
1873
1875 if isinstance(self.__contentType, tuple):
1876 return self.__contentType[1]
1877 return None
1878
1879
1880 __contentType = None
1881 - def contentType (self):
1882 """Identify the sort of content in this type.
1883
1884 Valid values are:
1885 - C{CT_EMPTY}
1886 - ( C{CT_SIMPLE}, a L{SimpleTypeDefinition} instance )
1887 - ( C{CT_MIXED}, a L{Particle} instance )
1888 - ( C{CT_ELEMENT_ONLY}, a L{Particle} instance )
1889 """
1890 return self.__contentType
1891
1893 if self.CT_EMPTY == self.contentType():
1894 return 'EMPTY'
1895 ( tag, particle ) = self.contentType()
1896 if self.CT_SIMPLE == tag:
1897 return 'Simple [%s]' % (particle,)
1898 if self.CT_MIXED == tag:
1899 return 'Mixed [%s]' % (particle,)
1900 if self.CT_ELEMENT_ONLY == tag:
1901 return 'Element [%s]' % (particle,)
1902 raise pyxb.LogicError('Unhandled content type')
1903
1904
1905 __prohibitedSubstitutions = DM_empty
1906
1907
1908 __annotations = None
1909
1915
1925
1927 """Override fields in this instance with those from the other.
1928
1929 This method is invoked only by Schema._addNamedComponent, and
1930 then only when a built-in type collides with a schema-defined
1931 type. Material like facets is not (currently) held in the
1932 built-in copy, so the DOM information is copied over to the
1933 built-in STD, which is subsequently re-resolved.
1934
1935 Returns self.
1936 """
1937 assert self != other
1938 assert self.isNameEquivalent(other)
1939 super(ComplexTypeDefinition, self)._updateFromOther_csc(other)
1940
1941 if not other.isResolved():
1942 if pyxb.namespace.BuiltInObjectUID != self._objectOrigin().generationUID():
1943 self.__derivationMethod = None
1944
1945 return self
1946
1947 __UrTypeDefinition = None
1948 @classmethod
1950 """Create the ComplexTypeDefinition instance that approximates
1951 the ur-type.
1952
1953 See section 3.4.7.
1954 """
1955
1956
1957
1958
1959
1960
1961
1962 if cls.__UrTypeDefinition is None:
1963
1964 assert schema is not None
1965
1966 ns_ctx = schema.targetNamespace().initialNamespaceContext()
1967
1968 kw = { 'name' : 'anyType',
1969 'schema' : schema,
1970 'namespace_context' : ns_ctx,
1971 'binding_namespace' : schema.targetNamespace(),
1972 'derivation_method' : cls.DM_restriction,
1973 'scope' : _ScopedDeclaration_mixin.SCOPE_global }
1974 bi = _UrTypeDefinition(**kw)
1975
1976
1977 bi.__baseTypeDefinition = bi
1978
1979
1980 bi._setAttributeWildcard(Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw))
1981
1982
1983
1984
1985
1986
1987 kw = { 'namespace_context' : ns_ctx
1988 , 'schema' : schema
1989 , 'scope': _ScopedDeclaration_mixin.XSCOPE_indeterminate }
1990 w = Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw)
1991 p = Particle(w, min_occurs=0, max_occurs=None, **kw)
1992 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ p ], **kw)
1993 bi.__contentType = ( cls.CT_MIXED, Particle(m, **kw) )
1994
1995
1996 bi.__attributeUses = set()
1997
1998
1999 bi.__final = cls.DM_empty
2000 bi.__prohibitedSubstitutions = cls.DM_empty
2001
2002 bi.__abstract = False
2003
2004
2005 bi.setNameInBinding(bi.name())
2006
2007
2008 bi.__derivationMethod = cls.DM_restriction
2009
2010 cls.__UrTypeDefinition = bi
2011 return cls.__UrTypeDefinition
2012
2014 """Indicate whether this simple type is a built-in type."""
2015 return (self.UrTypeDefinition() == self)
2016
2017
2033
2034
2035 @classmethod
2037
2038 assert xsd.nodeIsNamed(node, 'complexType')
2039
2040 name = domutils.NodeAttribute(node, 'name')
2041
2042 rv = cls(name=name, node=node, derivation_method=None, **kw)
2043
2044
2045
2046
2047
2048 if rv._scopeIsGlobal():
2049 assert isinstance(rv.owner(), Schema)
2050 if rv.isAnonymous():
2051 raise pyxb.SchemaValidationError("Anonymous complex type at schema top level")
2052 else:
2053 assert not isinstance(rv.owner(), Schema)
2054 if not rv.isAnonymous():
2055 raise pyxb.SchemaValidationError('Name attribute invalid on non-global complex types: %s' % (rv.expandedName(),))
2056
2057 kw.pop('node', None)
2058 kw['owner'] = rv
2059 kw['scope'] = rv
2060
2061 return rv.__setContentFromDOM(node, **kw)
2062
2063 __baseExpandedName = None
2064
2065 __ckw = None
2066 __anyAttribute = None
2067 __attributeGroupNames = None
2068 __usesC1 = None
2069 __usesC1C2 = None
2070 __attributeGroups = None
2071 __PrivateTransient.update(['ckw', 'anyAttribute', 'attributeGroupNames', 'usesC1', 'usesC1C2', 'attributeGroups' ])
2072
2073
2075
2076 if self.__usesC1C2 is None:
2077
2078 uses_c1 = self.__usesC1
2079 uses_c2 = set()
2080 self.__attributeGroups = []
2081 for ag_en in self.__attributeGroupNames:
2082 agd = ag_en.attributeGroupDefinition()
2083 if agd is None:
2084 raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,))
2085 if not agd.isResolved():
2086 self._queueForResolution('unresolved attribute group', depends_on=agd)
2087 return self
2088 self.__attributeGroups.append(agd)
2089 uses_c2.update(agd.attributeUses())
2090
2091 uses_c1c2 = uses_c1.union(uses_c2)
2092 for au in uses_c1c2:
2093 if not au.isResolved():
2094 self._queueForResolution('attribute use not resolved')
2095 return self
2096 ad = au.attributeDeclaration()
2097 if not ad.isResolved():
2098 ad_en = ad.expandedName()
2099 self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad)
2100 return self
2101
2102 self.__usesC1C2 = frozenset([ _u._adaptForScope(self) for _u in uses_c1c2 ])
2103
2104
2105
2106
2107
2108
2109 uses_c3 = set()
2110 if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition):
2111
2112
2113 uses_c3 = set(self.__baseTypeDefinition.__attributeUses)
2114 assert self.__baseTypeDefinition.isResolved()
2115 for au in uses_c3:
2116 if not au.isResolved():
2117 self._queueForResolution('unresolved attribute use from base type', depends_on=au)
2118 return self
2119 ad = au.attributeDeclaration()
2120 if not ad.isResolved():
2121 ad_en = ad.expandedName()
2122 self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad)
2123 return self
2124 assert not au.attributeDeclaration()._scopeIsIndeterminate()
2125
2126 if self.DM_restriction == method:
2127
2128
2129
2130 for au in self.__usesC1C2:
2131 matching_uses = au.matchingQNameMembers(uses_c3)
2132 assert matching_uses is not None
2133 assert 1 >= len(matching_uses), 'Multiple inherited attribute uses with name %s'
2134 for au2 in matching_uses:
2135 assert au2.isResolved()
2136 uses_c3.remove(au2)
2137 au._setRestrictionOf(au2)
2138 else:
2139
2140
2141
2142 assert self.DM_extension == method
2143
2144 use_map = { }
2145 for au in self.__usesC1C2.union(uses_c3):
2146 assert au.isResolved()
2147 ad_en = au.attributeDeclaration().expandedName()
2148 if ad_en in use_map:
2149 raise pyxb.SchemaValidationError('Multiple definitions for %s in CTD %s' % (ad_en, self.expandedName()))
2150 use_map[ad_en] = au
2151
2152
2153
2154 self.__attributeUses = frozenset(six.itervalues(use_map))
2155 if not self._scopeIsIndeterminate():
2156 for au in self.__attributeUses:
2157 assert not au.attributeDeclaration()._scopeIsIndeterminate(), 'indeterminate scope for %s' % (au,)
2158
2159
2160
2161 local_wildcard = None
2162 if self.__anyAttribute is not None:
2163 local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute)
2164
2165
2166 complete_wildcard = _AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), self.__attributeGroups, local_wildcard)
2167
2168
2169 if self.DM_restriction == method:
2170
2171 self._setAttributeWildcard(complete_wildcard)
2172 else:
2173 assert (self.DM_extension == method)
2174 assert self.baseTypeDefinition().isResolved()
2175
2176 base_wildcard = None
2177 if isinstance(self.baseTypeDefinition(), ComplexTypeDefinition):
2178 base_wildcard = self.baseTypeDefinition().attributeWildcard()
2179
2180 if base_wildcard is not None:
2181 if complete_wildcard is None:
2182
2183 self._setAttributeWildcard(base_wildcard)
2184 else:
2185
2186 self._setAttributeWildcard(Wildcard (process_contents=complete_wildcard.processContents(),
2187 namespace_constraint = Wildcard.IntensionalUnion([complete_wildcard.namespaceConstraint(),
2188 base_wildcard.namespaceConstraint()]),
2189 annotation=complete_wildcard.annotation(),
2190 namespace_context=self._namespaceContext()))
2191 else:
2192
2193 self._setAttributeWildcard(complete_wildcard)
2194
2195
2196
2197
2198 del self.__usesC1
2199 del self.__usesC1C2
2200 del self.__attributeGroups
2201 self.__ckw = None
2202
2203
2204
2205
2206 self.__derivationMethod = method
2207 return self
2208
2209 - def __simpleContent (self, method, **kw):
2210
2211 if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition):
2212
2213 parent_content_type = self.__baseTypeDefinition.__contentType
2214 if ((type(parent_content_type) == tuple) \
2215 and (self.CT_SIMPLE == parent_content_type[0]) \
2216 and (self.DM_restriction == method)):
2217
2218 assert self.__ctscRestrictionNode is not None
2219 std = self.__ctscClause2STD
2220 if std is None:
2221 std = parent_content_type[1]
2222 assert isinstance(std, SimpleTypeDefinition)
2223 if not std.isResolved():
2224 return None
2225 restriction_node = self.__ctscRestrictionNode
2226 self.__ctscClause2STD = None
2227 self.__ctscRestrictionNode = None
2228 return ( self.CT_SIMPLE, std._createRestriction(self, restriction_node) )
2229 if ((type(parent_content_type) == tuple) \
2230 and (self.CT_MIXED == parent_content_type[0]) \
2231 and parent_content_type[1].isEmptiable()):
2232
2233 assert isinstance(self.__ctscClause2STD, SimpleTypeDefinition)
2234 return ( self.CT_SIMPLE, self.__ctscClause2STD )
2235
2236 return parent_content_type
2237
2238 return ( self.CT_SIMPLE, self.__baseTypeDefinition )
2239
2240 __ctscClause2STD = None
2241 __ctscRestrictionNode = None
2242 __PrivateTransient.update(['ctscRestrictionNode' ])
2243 __effectiveMixed = None
2244 __effectiveContent = None
2245 __pendingDerivationMethod = None
2246 __isComplexContent = None
2247 - def _isComplexContent (self):
2249 __ctscRestrictionMode = None
2250 __contentStyle = None
2251
2252 - def __setComplexContentFromDOM (self, type_node, content_node, definition_node_list, method, **kw):
2253
2254
2255 ckw = kw.copy()
2256 ckw['namespace_context'] = pyxb.namespace.NamespaceContext.GetNodeContext(type_node)
2257
2258
2259 mixed_attr = None
2260 if content_node is not None:
2261 mixed_attr = domutils.NodeAttribute(content_node, 'mixed')
2262 if mixed_attr is None:
2263 mixed_attr = domutils.NodeAttribute(type_node, 'mixed')
2264 if mixed_attr is not None:
2265 effective_mixed = datatypes.boolean(mixed_attr)
2266 else:
2267 effective_mixed = False
2268
2269
2270 test_2_1_1 = True
2271 test_2_1_2 = False
2272 test_2_1_3 = False
2273 typedef_node = None
2274 for cn in definition_node_list:
2275 if Node.ELEMENT_NODE != cn.nodeType:
2276 continue
2277 if xsd.nodeIsNamed(cn, 'simpleContent', 'complexContent'):
2278
2279 raise pyxb.LogicError('Missed explicit wrapper in complexType content')
2280 if Particle.IsTypedefNode(cn):
2281 typedef_node = cn
2282 test_2_1_1 = False
2283 if xsd.nodeIsNamed(cn, 'all', 'sequence') \
2284 and (not domutils.HasNonAnnotationChild(cn)):
2285 test_2_1_2 = True
2286 if xsd.nodeIsNamed(cn, 'choice') \
2287 and (not domutils.HasNonAnnotationChild(cn)):
2288 mo_attr = domutils.NodeAttribute(cn, 'minOccurs')
2289 if ((mo_attr is not None) \
2290 and (0 == datatypes.integer(mo_attr))):
2291 test_2_1_3 = True
2292 satisfied_predicates = 0
2293 if test_2_1_1:
2294 satisfied_predicates += 1
2295 if test_2_1_2:
2296 satisfied_predicates += 1
2297 if test_2_1_3:
2298 satisfied_predicates += 1
2299 if 1 == satisfied_predicates:
2300 if effective_mixed:
2301
2302 assert (typedef_node is None) or test_2_1_2
2303 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[], **ckw)
2304 effective_content = Particle(m, **ckw)
2305 else:
2306
2307 effective_content = self.CT_EMPTY
2308 else:
2309
2310 assert typedef_node is not None
2311 effective_content = Particle.CreateFromDOM(typedef_node, **kw)
2312
2313
2314
2315
2316
2317
2318
2319 self.__effectiveMixed = effective_mixed
2320 self.__effectiveContent = effective_content
2321 self.__ckw = ckw
2322
2323 - def __complexContent (self, method):
2324 ckw = self.__ckw
2325
2326
2327 if self.__effectiveMixed:
2328 ct = self.CT_MIXED
2329 else:
2330 ct = self.CT_ELEMENT_ONLY
2331
2332 if self.DM_restriction == method:
2333
2334 if self.CT_EMPTY == self.__effectiveContent:
2335
2336 content_type = self.CT_EMPTY
2337 else:
2338
2339 content_type = ( ct, self.__effectiveContent )
2340 assert 0 == len(self.__scopedElementDeclarations)
2341
2342
2343
2344
2345 self.__scopedElementDeclarations.update(self.__baseTypeDefinition.__scopedElementDeclarations)
2346 else:
2347
2348 assert self.DM_extension == method
2349 assert self.__baseTypeDefinition.isResolved()
2350 parent_content_type = self.__baseTypeDefinition.contentType()
2351 if self.CT_EMPTY == self.__effectiveContent:
2352 content_type = parent_content_type
2353 elif self.CT_EMPTY == parent_content_type:
2354
2355 content_type = ( ct, self.__effectiveContent )
2356 else:
2357 assert type(parent_content_type) == tuple
2358 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ parent_content_type[1], self.__effectiveContent ], **ckw)
2359 content_type = ( ct, Particle(m, **ckw) )
2360
2361 assert (self.CT_EMPTY == content_type) or ((type(content_type) == tuple) and (content_type[1] is not None))
2362 return content_type
2363
2365 """Indicate whether this complex type is fully defined.
2366
2367 All built-in type definitions are resolved upon creation.
2368 Schema-defined type definitionss are held unresolved until the
2369 schema has been completely read, so that references to later
2370 schema-defined types can be resolved. Resolution is performed
2371 after the entire schema has been scanned and type-definition
2372 instances created for all topLevel{Simple,Complex}Types.
2373
2374 If a built-in type definition is also defined in a schema
2375 (which it should be), the built-in definition is kept, with
2376 the schema-related information copied over from the matching
2377 schema-defined type definition. The former then replaces the
2378 latter in the list of type definitions to be resolved. See
2379 Schema._addNamedComponent.
2380 """
2381
2382 return (self.__derivationMethod is not None)
2383
2384
2385
2389
2390 - def __setContentFromDOM (self, node, **kw):
2391 schema = kw.get('schema')
2392 assert schema is not None
2393 self.__prohibitedSubstitutions = schema.blockForNode(node, self._DM_Map)
2394 self.__final = schema.finalForNode(node, self._DM_Map)
2395
2396 attr_val = domutils.NodeAttribute(node, 'abstract')
2397 if attr_val is not None:
2398 self.__abstract = datatypes.boolean(attr_val)
2399
2400
2401
2402 definition_node_list = node.childNodes
2403 is_complex_content = True
2404 self.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition()
2405 method = self.DM_restriction
2406
2407
2408
2409
2410 first_elt = domutils.LocateFirstChildElement(node)
2411 content_node = None
2412 clause2_std = None
2413 ctsc_restriction_node = None
2414 if first_elt:
2415 have_content = False
2416 if xsd.nodeIsNamed(first_elt, 'simpleContent'):
2417 have_content = True
2418 is_complex_content = False
2419 elif xsd.nodeIsNamed(first_elt, 'complexContent'):
2420 have_content = True
2421 else:
2422
2423
2424 if not Particle.IsParticleNode(first_elt, 'attributeGroup', 'attribute', 'anyAttribute'):
2425 raise pyxb.SchemaValidationError('Unexpected element %s at root of complexType' % (first_elt.nodeName,))
2426 if have_content:
2427
2428 content_node = domutils.LocateFirstChildElement(node, require_unique=True)
2429 assert content_node == first_elt
2430
2431
2432
2433 ions = domutils.LocateFirstChildElement(content_node, absent_ok=False)
2434 if xsd.nodeIsNamed(ions, 'restriction'):
2435 method = self.DM_restriction
2436 if not is_complex_content:
2437
2438 ctsc_restriction_node = ions
2439 ions_st = domutils.LocateUniqueChild(ions,'simpleType')
2440 if ions_st is not None:
2441 clause2_std = SimpleTypeDefinition.CreateFromDOM(ions_st, **kw)
2442 elif xsd.nodeIsNamed(ions, 'extension'):
2443 method = self.DM_extension
2444 else:
2445 raise pyxb.SchemaValidationError('Expected restriction or extension as sole child of %s in %s' % (content_node.nodeName, self.name()))
2446 self.__baseExpandedName = domutils.NodeAttributeQName(ions, 'base')
2447 if self.__baseExpandedName is None:
2448 raise pyxb.SchemaValidationError('Element %s missing base attribute' % (ions.nodeName,))
2449 self.__baseTypeDefinition = None
2450
2451 definition_node_list = ions.childNodes
2452
2453 self.__pendingDerivationMethod = method
2454 self.__isComplexContent = is_complex_content
2455 self.__ctscRestrictionNode = ctsc_restriction_node
2456 self.__ctscClause2STD = clause2_std
2457
2458 (attributes, attribute_group_names, any_attribute) = self._attributeRelevantChildren(definition_node_list)
2459 self.__usesC1 = set()
2460 for cn in attributes:
2461 au = AttributeUse.CreateFromDOM(cn, **kw)
2462 self.__usesC1.add(au)
2463 self.__attributeGroupNames = attribute_group_names
2464 self.__anyAttribute = any_attribute
2465
2466 if self.__isComplexContent:
2467 self.__setComplexContentFromDOM(node, content_node, definition_node_list, self.__pendingDerivationMethod, **kw)
2468
2469
2470
2471 self._annotationFromDOM(node)
2472
2473 if not self.isResolved():
2474 self._queueForResolution('creation')
2475
2476 return self
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2541
2543 """Complex type definitions have no built-in type support."""
2544 return None
2545
2550
2552 """Subclass ensures there is only one ur-type."""
2554 """The ur-type does have a Python class backing it up."""
2555 return datatypes.anyType
2556
2561
2562
2563 -class AttributeGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
2564 """An XMLSchema U{Attribute Group Definition<http://www.w3.org/TR/xmlschema-1/#cAttribute_Group_Definitions>} component."""
2565 __PrivateTransient = set()
2566
2567
2568 __attributeUses = None
2569
2572
2573
2574
2577
2578 @classmethod
2589
2590 __anyAttribute = None
2591 __attributeGroupNames = None
2592 __PrivateTransient.update(['anyAttribute', 'attributeGroupNames'])
2593
2594
2595 @classmethod
2631
2632
2633 __isResolved = False
2636
2663
2664
2666 """Attribute group declarations require their uses, but only if lax."""
2667 if not include_lax:
2668 return frozenset()
2669 return frozenset(self.attributeUses())
2670
2673
2675 """An XMLSchema U{Model Group Definition<http://www.w3.org/TR/xmlschema-1/#cModel_Group_Definitions>} component."""
2676
2677 __modelGroup = None
2678
2680 """The model group for which this definition provides a name."""
2681 return self.__modelGroup
2682
2683
2684 @classmethod
2686 """Create a Model Group Definition from a DOM element node.
2687
2688 wxs is a Schema instance within which the model group is being
2689 defined.
2690
2691 node is a DOM element. The name must be 'group', and the node
2692 must be in the XMLSchema namespace. The node must have a
2693 'name' attribute, and must not have a 'ref' attribute.
2694 """
2695 assert xsd.nodeIsNamed(node, 'group')
2696
2697 assert domutils.NodeAttribute(node, 'ref') is None
2698
2699 name = domutils.NodeAttribute(node, 'name')
2700 kw['scope'] = _ScopedDeclaration_mixin.XSCOPE_indeterminate
2701 rv = cls(name=name, node=node, **kw)
2702 rv._annotationFromDOM(node)
2703
2704 kw.pop('node', None)
2705 kw['owner'] = rv
2706
2707 for cn in node.childNodes:
2708 if Node.ELEMENT_NODE != cn.nodeType:
2709 continue
2710 if ModelGroup.IsGroupMemberNode(cn):
2711 assert not rv.__modelGroup
2712
2713
2714
2715 rv.__modelGroup = ModelGroup.CreateFromDOM(cn, model_group_definition=rv, **kw)
2716 assert rv.__modelGroup is not None
2717 return rv
2718
2719
2721 """Model group definitions depend on the contained model group."""
2722 if not include_lax:
2723 return frozenset()
2724 return frozenset([self.__modelGroup])
2725
2728
2729
2730 -class ModelGroup (_ParticleTree_mixin, _SchemaComponent_mixin, _Annotated_mixin):
2731 """An XMLSchema U{Model Group<http://www.w3.org/TR/xmlschema-1/#cModel_Group>} component."""
2732 C_INVALID = 0
2733 C_ALL = 0x01
2734 C_CHOICE = 0x02
2735 C_SEQUENCE = 0x03
2736
2737
2738
2739 __compositor = C_INVALID
2742
2743 @classmethod
2753
2757
2758
2759
2760 __particles = None
2761 - def particles (self):
2762 return self.__particles
2763
2765 """A model group has an unresolvable particle if any of its
2766 particles is unresolvable. Duh."""
2767 for p in self.particles():
2768 if not p.isAdaptable(ctd):
2769 return False
2770 return True
2771
2773 """Return the minimum and maximum of the number of elements that can
2774 appear in a sequence matched by this particle.
2775
2776 See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range}
2777 """
2778 if self.__compositor in (self.C_ALL, self.C_SEQUENCE):
2779 sum_minoccurs = 0
2780 sum_maxoccurs = 0
2781 for prt in self.__particles:
2782 (prt_min, prt_max) = prt.effectiveTotalRange()
2783 sum_minoccurs += prt_min
2784 if sum_maxoccurs is not None:
2785 if prt_max is None:
2786 sum_maxoccurs = None
2787 else:
2788 sum_maxoccurs += prt_max
2789 prod_maxoccurs = particle.maxOccurs()
2790 if prod_maxoccurs is not None:
2791 if sum_maxoccurs is None:
2792 prod_maxoccurs = None
2793 else:
2794 prod_maxoccurs *= sum_maxoccurs
2795 return (sum_minoccurs * particle.minOccurs(), prod_maxoccurs)
2796 assert self.__compositor == self.C_CHOICE
2797 if 0 == len(self.__particles):
2798 min_minoccurs = 0
2799 max_maxoccurs = 0
2800 else:
2801 (min_minoccurs, max_maxoccurs) = self.__particles[0].effectiveTotalRange()
2802 for prt in self.__particles[1:]:
2803 (prt_min, prt_max) = prt.effectiveTotalRange()
2804 if prt_min < min_minoccurs:
2805 min_minoccurs = prt_min
2806 if prt_max is None:
2807 max_maxoccurs = None
2808 elif (max_maxoccurs is not None) and (prt_max > max_maxoccurs):
2809 max_maxoccurs = prt_max
2810 min_minoccurs *= particle.minOccurs()
2811 if (max_maxoccurs is not None) and (particle.maxOccurs() is not None):
2812 max_maxoccurs *= particle.maxOccurs()
2813 return (min_minoccurs, max_maxoccurs)
2814
2815
2816
2817
2818 __modelGroupDefinition = None
2820 """The ModelGroupDefinition that names this group, or None if it is unnamed."""
2821 return self.__modelGroupDefinition
2822
2823 - def __init__ (self, compositor, particles, *args, **kw):
2824 """Create a new model group.
2825
2826 compositor must be a legal compositor value (one of C_ALL, C_CHOICE, C_SEQUENCE).
2827
2828 particles must be a list of zero or more Particle instances.
2829
2830 scope is the _ScopeDeclaration_mixin context into which new
2831 declarations are recorded. It can be SCOPE_global, a complex
2832 type definition, or None if this is (or is within) a named
2833 model group.
2834
2835 model_group_definition is an instance of ModelGroupDefinition
2836 if this is a named model group. It defaults to None
2837 indicating a local group.
2838 """
2839
2840 super(ModelGroup, self).__init__(*args, **kw)
2841 assert 'scope' in kw
2842 self.__compositor = compositor
2843 self.__particles = particles
2844 self.__modelGroupDefinition = kw.get('model_group_definition')
2845
2847 """Return True if the model includes a wildcard amongst its particles."""
2848 for p in self.particles():
2849 if p.hasWildcardElement():
2850 return True
2851 return False
2852
2853
2855 if not include_lax:
2856 return frozenset()
2857 return frozenset(self.__particles)
2858
2859
2860 @classmethod
2862 """Create a model group from the given DOM node.
2863
2864 wxs is a Schema instance within which the model group is being
2865 defined.
2866
2867 node is a DOM element. The name must be one of ( 'all',
2868 'choice', 'sequence' ), and the node must be in the XMLSchema
2869 namespace.
2870
2871 scope is the _ScopeDeclaration_mxin context that is assigned
2872 to declarations that appear within the model group. It can be
2873 None, indicating no scope defined, or a complex type
2874 definition.
2875 """
2876
2877 scope = kw['scope']
2878 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
2879
2880 if xsd.nodeIsNamed(node, 'all'):
2881 compositor = cls.C_ALL
2882 elif xsd.nodeIsNamed(node, 'choice'):
2883 compositor = cls.C_CHOICE
2884 else:
2885 assert xsd.nodeIsNamed(node, 'sequence')
2886 compositor = cls.C_SEQUENCE
2887 particles = []
2888
2889 kw.pop('owner', None)
2890 for cn in node.childNodes:
2891 if Node.ELEMENT_NODE != cn.nodeType:
2892 continue
2893 if Particle.IsParticleNode(cn):
2894
2895 particles.append(Particle.CreateFromDOM(node=cn, **kw))
2896 elif not xsd.nodeIsNamed(cn, 'annotation'):
2897 raise pyxb.SchemaValidationError('Unexpected element %s in model group' % (cn.nodeName,))
2898 rv = cls(compositor, particles, node=node, **kw)
2899 for p in particles:
2900 p._setOwner(rv)
2901 rv._annotationFromDOM(node)
2902 return rv
2903
2904 @classmethod
2907
2908
2919
2920 - def _walkParticleTree (self, visit, arg):
2921 visit(self, True, arg)
2922 for p in self.particles():
2923 p._walkParticleTree(visit, arg)
2924 visit(self, False, arg)
2925
2927 comp = None
2928 if self.C_ALL == self.compositor():
2929 comp = 'ALL'
2930 elif self.C_CHOICE == self.compositor():
2931 comp = 'CHOICE'
2932 elif self.C_SEQUENCE == self.compositor():
2933 comp = 'SEQUENCE'
2934 return '%s:(%s)' % (comp, six.u(',').join( [ six.text_type(_p) for _p in self.particles() ] ) )
2935
2936 -class Particle (_ParticleTree_mixin, _SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin):
2937 """An XMLSchema U{Particle<http://www.w3.org/TR/xmlschema-1/#cParticle>} component."""
2938
2939
2940 __minOccurs = 1
2941 - def minOccurs (self):
2942 """The minimum number of times the term may appear.
2943
2944 Defaults to 1."""
2945 return self.__minOccurs
2946
2947
2948 __maxOccurs = 1
2949 - def maxOccurs (self):
2950 """Upper limit on number of times the term may appear.
2951
2952 If None, the term may appear any number of times; otherwise,
2953 this is an integral value indicating the maximum number of times
2954 the term may appear. The default value is 1; the value, unless
2955 None, must always be at least minOccurs().
2956 """
2957 return self.__maxOccurs
2958
2959
2960 __term = None
2962 """A reference to a ModelGroup, Wildcard, or ElementDeclaration."""
2963 return self.__term
2964 __pendingTerm = None
2965
2966 __refExpandedName = None
2967 __resolvableType = None
2968
2970 """Extend the concept of effective total range to all particles.
2971
2972 See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range} and
2973 U{http://www.w3.org/TR/xmlschema-1/#cos-choice-range}
2974 """
2975 if isinstance(self.__term, ModelGroup):
2976 return self.__term.effectiveTotalRange(self)
2977 return (self.minOccurs(), self.maxOccurs())
2978
2979 - def isEmptiable (self):
2980 """Return C{True} iff this particle can legitimately match an empty
2981 sequence (no content).
2982
2983 See U{http://www.w3.org/TR/xmlschema-1/#cos-group-emptiable}
2984 """
2985 return 0 == self.effectiveTotalRange()[0]
2986
2988 """Return True iff this particle has a wildcard in its term.
2989
2990 Note that the wildcard may be in a nested model group."""
2991 return self.term().hasWildcardElement()
2992
2993 - def __init__ (self, term, *args, **kw):
2994 """Create a particle from the given DOM node.
2995
2996 term is a XML Schema Component: one of ModelGroup,
2997 ElementDeclaration, and Wildcard.
2998
2999 The following keyword arguments are processed:
3000
3001 min_occurs is a non-negative integer value with default 1,
3002 denoting the minimum number of terms required by the content
3003 model.
3004
3005 max_occurs is a positive integer value with default 1, or None
3006 indicating unbounded, denoting the maximum number of terms
3007 allowed by the content model.
3008
3009 scope is the _ScopeDeclaration_mxin context that is assigned
3010 to declarations that appear within the particle. It can be
3011 None, indicating no scope defined, or a complex type
3012 definition.
3013 """
3014
3015 super(Particle, self).__init__(*args, **kw)
3016
3017 min_occurs = kw.get('min_occurs', 1)
3018 max_occurs = kw.get('max_occurs', 1)
3019
3020 assert 'scope' in kw
3021 assert (self._scopeIsIndeterminate()) or isinstance(self._scope(), ComplexTypeDefinition)
3022
3023 if term is not None:
3024 self.__term = term
3025
3026 assert isinstance(min_occurs, six.integer_types)
3027 self.__minOccurs = min_occurs
3028 assert (max_occurs is None) or isinstance(max_occurs, six.integer_types)
3029 self.__maxOccurs = max_occurs
3030 if self.__maxOccurs is not None:
3031 if self.__minOccurs > self.__maxOccurs:
3032 raise pyxb.LogicError('Particle minOccurs %s is greater than maxOccurs %s on creation' % (min_occurs, max_occurs))
3033
3034
3035 - def _resolve (self):
3036 if self.isResolved():
3037 return self
3038
3039
3040 if ModelGroup == self.__resolvableType:
3041 group_decl = self.__refExpandedName.modelGroupDefinition()
3042 if group_decl is None:
3043 raise pyxb.SchemaValidationError('Model group reference %s cannot be found' % (self.__refExpandedName,))
3044
3045 self.__pendingTerm = group_decl.modelGroup()
3046 assert self.__pendingTerm is not None
3047 elif ElementDeclaration == self.__resolvableType:
3048
3049
3050
3051 if self.__refExpandedName is not None:
3052 assert self.__pendingTerm is None
3053 self.__pendingTerm = self.__refExpandedName.elementDeclaration()
3054 if self.__pendingTerm is None:
3055 raise pyxb.SchemaValidationError('Unable to locate element referenced by %s' % (self.__refExpandedName,))
3056 assert self.__pendingTerm is not None
3057
3058
3059
3060
3061 assert self.__pendingTerm is not None
3062 else:
3063 assert False
3064
3065 self.__term = self.__pendingTerm
3066 assert self.__term is not None
3067
3068 return self
3069
3070 - def isResolved (self):
3071 return self.__term is not None
3072
3073
3074 @classmethod
3075 - def CreateFromDOM (cls, node, **kw):
3076 """Create a particle from the given DOM node.
3077
3078 wxs is a Schema instance within which the model group is being
3079 defined.
3080
3081 node is a DOM element. The name must be one of ( 'group',
3082 'element', 'any', 'all', 'choice', 'sequence' ), and the node
3083 must be in the XMLSchema namespace.
3084
3085 scope is the _ScopeDeclaration_mxin context that is assigned
3086 to declarations that appear within the model group. It can be
3087 None, indicating no scope defined, or a complex type
3088 definition.
3089 """
3090 scope = kw['scope']
3091 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
3092
3093 kw.update({ 'min_occurs' : 1
3094 , 'max_occurs' : 1
3095 , 'node' : node })
3096
3097 if not Particle.IsParticleNode(node):
3098 raise pyxb.LogicError('Attempted to create particle from illegal element %s' % (node.nodeName,))
3099 attr_val = domutils.NodeAttribute(node, 'minOccurs')
3100 if attr_val is not None:
3101 kw['min_occurs'] = datatypes.nonNegativeInteger(attr_val)
3102 attr_val = domutils.NodeAttribute(node, 'maxOccurs')
3103 if attr_val is not None:
3104 if 'unbounded' == attr_val:
3105 kw['max_occurs'] = None
3106 else:
3107 kw['max_occurs'] = datatypes.nonNegativeInteger(attr_val)
3108
3109 rv = cls(None, **kw)
3110
3111 kw.pop('node', None)
3112 kw['owner'] = rv
3113
3114 rv.__refExpandedName = domutils.NodeAttributeQName(node, 'ref')
3115 rv.__pendingTerm = None
3116 rv.__resolvableType = None
3117 if xsd.nodeIsNamed(node, 'group'):
3118
3119
3120
3121 if rv.__refExpandedName is None:
3122 raise pyxb.SchemaValidationError('group particle without reference')
3123 rv.__resolvableType = ModelGroup
3124 elif xsd.nodeIsNamed(node, 'element'):
3125 if rv.__refExpandedName is None:
3126 schema = kw.get('schema')
3127 assert schema is not None
3128 target_namespace = schema.targetNamespaceForNode(node, ElementDeclaration)
3129 incoming_tns = kw.get('target_namespace')
3130 if incoming_tns is not None:
3131 assert incoming_tns == target_namespace
3132 else:
3133 kw['target_namespace'] = target_namespace
3134 rv.__term = ElementDeclaration.CreateFromDOM(node=node, **kw)
3135 else:
3136
3137
3138
3139 for tag in ('nillable', 'default', 'fixed', 'form', 'block', 'type'):
3140 av = domutils.NodeAttribute(node, tag)
3141 if av is not None:
3142 raise pyxb.SchemaValidationError('element with "ref" cannot have "%s"' % (tag,))
3143 rv.__resolvableType = ElementDeclaration
3144 assert not xsd.nodeIsNamed(node.parentNode, 'schema')
3145 elif xsd.nodeIsNamed(node, 'any'):
3146
3147 rv.__term = Wildcard.CreateFromDOM(node=node)
3148 elif ModelGroup.IsGroupMemberNode(node):
3149
3150
3151
3152 rv.__term = ModelGroup.CreateFromDOM(node, **kw)
3153 else:
3154 raise pyxb.LogicError('Unhandled node in Particle.CreateFromDOM: %s' % (node.toxml("utf-8"),))
3155
3156 if not rv.isResolved():
3157 rv._queueForResolution('creation')
3158 return rv
3159
3160
3161 - def _bindingRequires_vx (self, include_lax):
3162 if not include_lax:
3163 return frozenset()
3164 return frozenset([ self.__term ])
3165
3166
3167 - def _adaptForScope (self, owner, ctd):
3168 rv = self
3169 assert isinstance(ctd, ComplexTypeDefinition)
3170 maybe_rv = self._clone(owner, ctd._objectOrigin())
3171 term = rv.__term._adaptForScope(maybe_rv, ctd)
3172 do_clone = (self._scope() != ctd) or (rv.__term != term)
3173 if do_clone:
3174 rv = maybe_rv
3175 rv.__term = term
3176 return rv
3177
3178 - def isAdaptable (self, ctd):
3179 """A particle has an unresolvable particle if it cannot be
3180 resolved, or if it has resolved to a term which is a model
3181 group that has an unresolvable particle.
3182 """
3183 if not self.isResolved():
3184 return False
3185 return self.term().isAdaptable(ctd)
3186
3187 - def walkParticleTree (self, visit, arg):
3188 """The entry-point to walk a particle tree defining a content model.
3189
3190 See L{_ParticleTree_mixin._walkParticleTree}."""
3191 self._walkParticleTree(visit, arg)
3192
3193 - def _walkParticleTree (self, visit, arg):
3194 visit(self, True, arg)
3195 self.__term._walkParticleTree(visit, arg)
3196 visit(self, False, arg)
3197
3198 @classmethod
3199 - def IsTypedefNode (cls, node):
3200 return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence')
3201
3202 @classmethod
3203 - def IsParticleNode (cls, node, *others):
3204 return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence', 'element', 'any', *others)
3205
3206 - def __str__ (self):
3207
3208 return 'PART{%s:%d,%s}[%x]' % ('TERM', self.minOccurs(), self.maxOccurs(), id(self))
3209
3210
3211
3212 -class Wildcard (_ParticleTree_mixin, _SchemaComponent_mixin, _Annotated_mixin):
3213 """An XMLSchema U{Wildcard<http://www.w3.org/TR/xmlschema-1/#cParticle>} component."""
3214
3215 NC_any = '##any'
3216 NC_not = '##other'
3217 NC_targetNamespace = '##targetNamespace'
3218 NC_local = '##local'
3219
3220 __namespaceConstraint = None
3222 """A constraint on the namespace for the wildcard.
3223
3224 Valid values are:
3225 - L{Wildcard.NC_any}
3226 - A tuple ( L{Wildcard.NC_not}, a_namespace )
3227 - set(of_namespaces)
3228
3229 Note that namespace are represented by
3230 L{Namespace<pyxb.namespace.Namespace>} instances, not the URIs that
3231 actually define a namespace. Absence of a namespace is represented by
3232 C{None}, both in the "not" pair and in the set.
3233 """
3234 return self.__namespaceConstraint
3235
3236 @classmethod
3238 """http://www.w3.org/TR/xmlschema-1/#cos-aw-union"""
3239 assert 0 < len(constraints)
3240 o1 = constraints.pop(0)
3241 while 0 < len(constraints):
3242 o2 = constraints.pop(0)
3243
3244 if (o1 == o2):
3245 continue
3246
3247 if (cls.NC_any == o1) or (cls.NC_any == o2):
3248 o1 = cls.NC_any
3249 continue
3250
3251 if isinstance(o1, set) and isinstance(o2, set):
3252 o1 = o1.union(o2)
3253 continue
3254
3255 if (isinstance(o1, tuple) and isinstance(o2, tuple)) and (o1[1] != o2[1]):
3256 o1 = ( cls.NC_not, None )
3257 continue
3258
3259
3260 c_tuple = None
3261 c_set = None
3262 if isinstance(o1, tuple):
3263 assert isinstance(o2, set)
3264 c_tuple = o1
3265 c_set = o2
3266 else:
3267 assert isinstance(o1, set)
3268 assert isinstance(o2, tuple)
3269 c_tuple = o2
3270 c_set = o1
3271 negated_ns = c_tuple[1]
3272 if negated_ns is not None:
3273
3274 if (negated_ns in c_set) and (None in c_set):
3275 o1 = cls.NC_any
3276 continue
3277
3278 if negated_ns in c_set:
3279 o1 = ( cls.NC_not, None )
3280 continue
3281
3282 if None in c_set:
3283 raise pyxb.SchemaValidationError('Union of wildcard namespace constraints not expressible')
3284 o1 = c_tuple
3285 continue
3286
3287 if None in c_set:
3288 o1 = cls.NC_any
3289 else:
3290 o1 = ( cls.NC_not, None )
3291 return o1
3292
3293 @classmethod
3295 """http://www.w3.org/TR/xmlschema-1/#cos-aw-intersect"""
3296 assert 0 < len(constraints)
3297 o1 = constraints.pop(0)
3298 while 0 < len(constraints):
3299 o2 = constraints.pop(0)
3300
3301 if (o1 == o2):
3302 continue
3303
3304 if (cls.NC_any == o1) or (cls.NC_any == o2):
3305 if cls.NC_any == o1:
3306 o1 = o2
3307 continue
3308
3309 if isinstance(o1, set) and isinstance(o2, set):
3310 o1 = o1.intersection(o2)
3311 continue
3312 if isinstance(o1, tuple) and isinstance(o2, tuple):
3313 ns1 = o1[1]
3314 ns2 = o2[1]
3315
3316 if (ns1 is not None) and (ns2 is not None) and (ns1 != ns2):
3317 raise pyxb.SchemaValidationError('Intersection of wildcard namespace constraints not expressible')
3318
3319 assert (ns1 is None) or (ns2 is None)
3320 if ns1 is None:
3321 assert ns2 is not None
3322 o1 = ( cls.NC_not, ns2 )
3323 else:
3324 assert ns1 is not None
3325 o1 = ( cls.NC_not, ns1 )
3326 continue
3327
3328
3329
3330 c_tuple = None
3331 c_set = None
3332 if isinstance(o1, tuple):
3333 assert isinstance(o2, set)
3334 c_tuple = o1
3335 c_set = o2
3336 else:
3337 assert isinstance(o1, set)
3338 assert isinstance(o2, tuple)
3339 c_tuple = o2
3340 c_set = o1
3341 negated_ns = c_tuple[1]
3342 if negated_ns in c_set:
3343 c_set.remove(negated_ns)
3344 if None in c_set:
3345 c_set.remove(None)
3346 o1 = c_set
3347 return o1
3348
3349 PC_skip = 'skip'
3350 PC_lax = 'lax'
3351 PC_strict = 'strict'
3352
3353
3354 __processContents = None
3355 - def processContents (self):
3356 return self.__processContents
3357
3359 """Return True, since Wildcard components are wildcards."""
3360 return True
3361
3367
3370
3371 - def _walkParticleTree (self, visit, arg):
3372 visit(self, None, arg)
3373
3374
3376 """Wildcards are scope-independent; return self"""
3377 return self
3378
3379
3380 @classmethod
3382 namespace_context = pyxb.namespace.NamespaceContext.GetNodeContext(node)
3383 assert xsd.nodeIsNamed(node, 'any', 'anyAttribute')
3384 nc = domutils.NodeAttribute(node, 'namespace')
3385 if nc is None:
3386 namespace_constraint = cls.NC_any
3387 else:
3388 if cls.NC_any == nc:
3389 namespace_constraint = cls.NC_any
3390 elif cls.NC_not == nc:
3391 namespace_constraint = ( cls.NC_not, namespace_context.targetNamespace() )
3392 else:
3393 ncs = set()
3394 for ns_uri in nc.split():
3395 if cls.NC_local == ns_uri:
3396 ncs.add(None)
3397 elif cls.NC_targetNamespace == ns_uri:
3398 ncs.add(namespace_context.targetNamespace())
3399 else:
3400 ncs.add(pyxb.namespace.NamespaceForURI(ns_uri, create_if_missing=True))
3401 namespace_constraint = frozenset(ncs)
3402
3403 pc = domutils.NodeAttribute(node, 'processContents')
3404 if pc is None:
3405 process_contents = cls.PC_strict
3406 else:
3407 if pc in [ cls.PC_skip, cls.PC_lax, cls.PC_strict ]:
3408 process_contents = pc
3409 else:
3410 raise pyxb.SchemaValidationError('illegal value "%s" for any processContents attribute' % (pc,))
3411
3412 rv = cls(node=node, namespace_constraint=namespace_constraint, process_contents=process_contents, **kw)
3413 rv._annotationFromDOM(node)
3414 return rv
3415
3416
3417 -class IdentityConstraintDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin, pyxb.namespace.resolution._Resolvable_mixin):
3418 """An XMLSchema U{Identity Constraint Definition<http://www.w3.org/TR/xmlschema-1/#cIdentity-constraint_Definitions>} component."""
3419
3420 ICC_KEY = 0x01
3421 ICC_KEYREF = 0x02
3422 ICC_UNIQUE = 0x04
3423
3424 __identityConstraintCategory = None
3427
3428 __selector = None
3431
3432 __fields = None
3435
3436 __referencedKey = None
3437 __referAttribute = None
3438 __icc = None
3439
3440 __annotations = None
3443
3444
3445 @classmethod
3447 name = domutils.NodeAttribute(node, 'name')
3448 scope = kw['scope']
3449 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope)
3450 rv = cls(name=name, node=node, **kw)
3451
3452 kw.pop('node', None)
3453 kw['owner'] = rv
3454
3455
3456 rv.__isResolved = True
3457 icc = None
3458 if xsd.nodeIsNamed(node, 'key'):
3459 icc = rv.ICC_KEY
3460 elif xsd.nodeIsNamed(node, 'keyref'):
3461 icc = rv.ICC_KEYREF
3462 rv.__referAttribute = domutils.NodeAttribute(node, 'refer')
3463 if rv.__referAttribute is None:
3464 raise pyxb.SchemaValidationError('Require refer attribute on keyref elements')
3465 rv.__isResolved = False
3466 elif xsd.nodeIsNamed(node, 'unique'):
3467 icc = rv.ICC_UNIQUE
3468 else:
3469 raise pyxb.LogicError('Unexpected identity constraint node %s' % (node.toxml("utf-8"),))
3470 rv.__icc = icc
3471
3472 cn = domutils.LocateUniqueChild(node, 'selector')
3473 rv.__selector = domutils.NodeAttribute(cn, 'xpath')
3474 if rv.__selector is None:
3475 raise pyxb.SchemaValidationError('selector element missing xpath attribute')
3476
3477 rv.__fields = []
3478 for cn in domutils.LocateMatchingChildren(node, 'field'):
3479 xp_attr = domutils.NodeAttribute(cn, 'xpath')
3480 if xp_attr is None:
3481 raise pyxb.SchemaValidationError('field element missing xpath attribute')
3482 rv.__fields.append(xp_attr)
3483
3484 rv._annotationFromDOM(node)
3485 rv.__annotations = []
3486 if rv.annotation() is not None:
3487 rv.__annotations.append(rv)
3488
3489 for cn in node.childNodes:
3490 if (Node.ELEMENT_NODE != cn.nodeType):
3491 continue
3492 an = None
3493 if xsd.nodeIsNamed(cn, 'selector', 'field'):
3494 an = domutils.LocateUniqueChild(cn, 'annotation')
3495 elif xsd.nodeIsNamed(cn, 'annotation'):
3496 an = cn
3497 if an is not None:
3498 rv.__annotations.append(Annotation.CreateFromDOM(an, **kw))
3499
3500 rv.__identityConstraintCategory = icc
3501 if rv.ICC_KEYREF != rv.__identityConstraintCategory:
3502 rv._namespaceContext().targetNamespace().addCategoryObject('identityConstraintDefinition', rv.name(), rv)
3503
3504 if not rv.isResolved():
3505 rv._queueForResolution('creation')
3506 return rv
3507
3508 __isResolved = False
3511
3512
3527
3528
3530 """Constraint definitions that are by reference require the referenced constraint."""
3531 rv = set()
3532 if include_lax and (self.__referencedKey is not None):
3533 rv.add(self.__referencedKey)
3534 return frozenset(rv)
3535
3536
3537
3538
3539 -class NotationDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
3540 """An XMLSchema U{Notation Declaration<http://www.w3.org/TR/xmlschema-1/#cNotation_Declarations>} component."""
3541 __systemIdentifier = None
3544
3545 __publicIdentifier = None
3548
3549
3550 @classmethod
3560
3561
3564
3567 """An XMLSchema U{Annotation<http://www.w3.org/TR/xmlschema-1/#cAnnotation>} component."""
3568
3569 __applicationInformation = None
3572
3573 __userInformation = None
3576
3577
3579 application_information = kw.pop('application_information', None)
3580 user_information = kw.pop('user_information', None)
3581 super(Annotation, self).__init__(**kw)
3582 if (user_information is not None) and (not isinstance(user_information, list)):
3583 user_information = [ six.text_type(user_information) ]
3584 if (application_information is not None) and (not isinstance(application_information, list)):
3585 application_information = [ six.text_type(application_information) ]
3586 self.__userInformation = user_information
3587 self.__applicationInformation = application_information
3588
3589
3590
3591
3592
3593
3594
3595
3596 __attributes = None
3597
3598
3599 @classmethod
3623
3624 __RemoveMultiQuote_re = re.compile('""+')
3626 """Return the text in a form suitable for embedding in a
3627 triple-double-quoted docstring.
3628
3629 Any sequence of two or more double quotes is replaced by a sequence of
3630 single quotes that is the same length. Following this, spaces are
3631 added at the start and the end as necessary to ensure a double quote
3632 does not appear in those positions."""
3633 rv = self.text()
3634 rv = self.__RemoveMultiQuote_re.sub(lambda _mo: "'" * (_mo.end(0) - _mo.start(0)), rv)
3635 if rv.startswith('"'):
3636 rv = ' ' + rv
3637 if rv.endswith('"'):
3638 rv = rv + ' '
3639 return rv
3640
3642 if self.__userInformation is None:
3643 return ''
3644 text = []
3645
3646
3647 for dn in self.__userInformation:
3648 for cn in dn.childNodes:
3649 if Node.TEXT_NODE == cn.nodeType:
3650 text.append(cn.data)
3651 return ''.join(text)
3652
3654 """Return the catenation of all user information elements in the
3655 annotation as a single unicode string. Returns the empty string if
3656 there are no user information elements."""
3657 return self.text()
3658
3659
3660 -class SimpleTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin):
3661 """An XMLSchema U{Simple Type Definition<http://www.w3.org/TR/xmlschema-1/#Simple_Type_Definitions>} component."""
3662
3663
3664
3665
3666 __baseTypeDefinition = None
3669
3670 __memberTypes = None
3671 __itemTypeExpandedName = None
3672 __baseExpandedName = None
3673 __memberTypesExpandedNames = None
3674 __localFacets = None
3675
3676
3677
3678
3679
3680
3681 __facets = None
3685
3686
3687 __fundamentalFacets = None
3689 """A frozenset of instances of facets.FundamentallFacet."""
3690 return self.__fundamentalFacets
3691
3692 STD_empty = 0
3693 STD_extension = 0x01
3694 STD_list = 0x02
3695 STD_restriction = 0x04
3696 STD_union = 0x08
3697
3698 _STD_Map = { 'extension' : STD_extension
3699 , 'list' : STD_list
3700 , 'restriction' : STD_restriction
3701 , 'union' : STD_union }
3702
3703
3704 __final = STD_empty
3705 @classmethod
3707 """Convert a final value to a string."""
3708 tags = []
3709 if final_value & cls.STD_extension:
3710 tags.append('extension')
3711 if final_value & cls.STD_list:
3712 tags.append('list')
3713 if final_value & cls.STD_restriction:
3714 tags.append('restriction')
3715 if final_value & cls.STD_union:
3716 tags.append('union')
3717 return ' '.join(tags)
3718
3719 VARIETY_absent = 0x01
3720 VARIETY_atomic = 0x02
3721 VARIETY_list = 0x03
3722 VARIETY_union = 0x04
3723
3724
3725 _DA_empty = 'none specified'
3726 _DA_restriction = 'restriction'
3727 _DA_list = 'list'
3728 _DA_union = 'union'
3729
3732 __derivationAlternative = None
3733
3734
3735
3736 __variety = None
3739 @classmethod
3751
3752
3753 __primitiveTypeDefinition = None
3760
3761
3762 __itemTypeDefinition = None
3768
3769
3770 __memberTypeDefinitions = None
3776
3777
3806
3807
3808
3809
3810
3811 __domNode = None
3812
3813
3814
3815 __isBuiltin = False
3816
3817
3818
3819
3823
3825 """Extend base class unpickle support to retain link between
3826 this instance and the Python class that it describes.
3827
3828 This is because the pythonSupport value is a class reference,
3829 not an instance reference, so it wasn't deserialized, and its
3830 class member link was never set.
3831 """
3832 super_fn = getattr(super(SimpleTypeDefinition, self), '__setstate__', lambda _state: self.__dict__.update(_state))
3833 super_fn(state)
3834 if self.__pythonSupport is not None:
3835 self.__pythonSupport._SimpleTypeDefinition(self)
3836
3864
3866 """Override fields in this instance with those from the other.
3867
3868 This method is invoked only by Schema._addNamedComponent, and
3869 then only when a built-in type collides with a schema-defined
3870 type. Material like facets is not (currently) held in the
3871 built-in copy, so the DOM information is copied over to the
3872 built-in STD, which is subsequently re-resolved.
3873
3874 Returns self.
3875 """
3876 assert self != other
3877 assert self.isNameEquivalent(other)
3878 super(SimpleTypeDefinition, self)._updateFromOther_csc(other)
3879
3880
3881 assert other.__baseTypeDefinition is None, 'Update from resolved STD %s' % (other,)
3882 assert other.__domNode is not None
3883 self.__domNode = other.__domNode
3884
3885
3886 if other.__pythonSupport is not None:
3887
3888 self.__pythonSupport = other.__pythonSupport
3889
3890
3891 self.__variety = None
3892 return self
3893
3895 """Indicate whether this simple type is a built-in type."""
3896 return self.__isBuiltin
3897
3898 __SimpleUrTypeDefinition = None
3899 @classmethod
3936
3937 @classmethod
3972
3973 @classmethod
4005
4006 @classmethod
4038
4039 @classmethod
4066
4067 @classmethod
4069 """(Placeholder) Create a union simple type in the target namespace.
4070
4071 This function has not been implemented."""
4072 raise pyxb.IncompleteImplementationError('No support for built-in union types')
4073
4075 simple_type_child = None
4076 for cn in body.childNodes:
4077 if (Node.ELEMENT_NODE == cn.nodeType):
4078 if not xsd.nodeIsNamed(cn, 'simpleType'):
4079 if other_elts_ok:
4080 continue
4081 raise pyxb.SchemaValidationError('Context requires element to be xs:simpleType')
4082 assert not simple_type_child
4083 simple_type_child = cn
4084 if simple_type_child is None:
4085 raise pyxb.SchemaValidationError('Content requires an xs:simpleType member (or a base attribute)')
4086 return simple_type_child
4087
4088
4089
4090
4091
4092
4093
4094
4104
4111
4112 __localMemberTypes = None
4126
4137
4139 """Create facets for varieties that can take facets that are undeclared.
4140
4141 This means unions, which per section 4.1.2.3 of
4142 http://www.w3.org/TR/xmlschema-2/ can have enumeration or
4143 pattern restrictions."""
4144 if self.VARIETY_union != variety:
4145 return self
4146 self.__facets.setdefault(facets.CF_pattern)
4147 self.__facets.setdefault(facets.CF_enumeration)
4148 return self
4149
4151 """Identify the facets and properties for this stype.
4152
4153 This method simply identifies the facets that apply to this
4154 specific type, and records property values. Only
4155 explicitly-associated facets and properties are stored; others
4156 from base types will also affect this type. The information
4157 is taken from the applicationInformation children of the
4158 definition's annotation node, if any. If there is no support
4159 for the XMLSchema_hasFacetAndProperty namespace, this is a
4160 no-op.
4161
4162 Upon return, self.__facets is a map from the class for an
4163 associated fact to None, and self.__fundamentalFacets is a
4164 frozenset of instances of FundamentalFacet.
4165
4166 The return value is self.
4167 """
4168 self.__facets = { }
4169 self.__fundamentalFacets = frozenset()
4170 if self.annotation() is None:
4171 return self.__defineDefaultFacets(variety)
4172 app_info = self.annotation().applicationInformation()
4173 if app_info is None:
4174 return self.__defineDefaultFacets(variety)
4175 facet_map = { }
4176 fundamental_facets = set()
4177 seen_facets = set()
4178 for ai in app_info:
4179 for cn in ai.childNodes:
4180 if Node.ELEMENT_NODE != cn.nodeType:
4181 continue
4182 if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasFacet'):
4183 facet_name = domutils.NodeAttribute(cn, 'name')
4184 if facet_name is None:
4185 raise pyxb.SchemaValidationError('hasFacet missing name attribute in %s' % (cn,))
4186 if facet_name in seen_facets:
4187 raise pyxb.SchemaValidationError('Multiple hasFacet specifications for %s' % (facet_name,))
4188 seen_facets.add(facet_name)
4189 facet_class = facets.ConstrainingFacet.ClassForFacet(facet_name)
4190
4191 facet_map[facet_class] = None
4192 if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasProperty'):
4193 fundamental_facets.add(facets.FundamentalFacet.CreateFromDOM(cn, self))
4194 if 0 < len(facet_map):
4195 assert self.__baseTypeDefinition == self.SimpleUrTypeDefinition()
4196 self.__facets = facet_map
4197 assert isinstance(self.__facets, six.dictionary_type)
4198 if 0 < len(fundamental_facets):
4199 self.__fundamentalFacets = frozenset(fundamental_facets)
4200 return self
4201
4202
4204
4205
4206
4207
4208 local_facets = {}
4209 for fc in facets.Facet.Facets:
4210 children = domutils.LocateMatchingChildren(body, fc.Name())
4211 if 0 < len(children):
4212 fi = fc(base_type_definition=self.__baseTypeDefinition,
4213 owner_type_definition=self)
4214 if isinstance(fi, facets._LateDatatype_mixin):
4215 fi.bindValueDatatype(self)
4216 for cn in children:
4217 kw = { 'annotation': domutils.LocateUniqueChild(cn, 'annotation') }
4218 for ai in range(0, cn.attributes.length):
4219 attr = cn.attributes.item(ai)
4220
4221 kw[six.text_type(attr.localName)] = attr.value
4222 try:
4223 fi.setFromKeywords(**kw)
4224 except pyxb.PyXBException as e:
4225 raise pyxb.SchemaValidationError('Error assigning facet %s in %s: %s' % (fc.Name(), self.expandedName(), e))
4226 local_facets[fc] = fi
4227 self.__localFacets = local_facets
4228
4229
4230
4231
4232
4233
4234
4235
4236 base_facets = {}
4237
4238
4239
4240 if self.__baseTypeDefinition.isBuiltin():
4241 pstd = self.__baseTypeDefinition.pythonSupport()
4242 if pstd != datatypes.anySimpleType:
4243 base_facets.update(pstd._FacetMap())
4244 elif self.__baseTypeDefinition.facets():
4245 assert isinstance(self.__baseTypeDefinition.facets(), six.dictionary_type)
4246 base_facets.update(self.__baseTypeDefinition.facets())
4247 base_facets.update(self.facets())
4248
4249 self.__facets = self.__localFacets
4250 for fc in six.iterkeys(base_facets):
4251 self.__facets.setdefault(fc, base_facets[fc])
4252 assert isinstance(self.__facets, six.dictionary_type)
4253
4268
4269
4270
4271
4273 assert self.__variety is None
4274 if self.__baseTypeDefinition is None:
4275 assert self.__baseExpandedName is not None
4276 base_type = self.__baseExpandedName.typeDefinition()
4277 if not isinstance(base_type, SimpleTypeDefinition):
4278 raise pyxb.SchemaValidationError('Unable to locate base type %s' % (self.__baseExpandedName,))
4279 self.__baseTypeDefinition = base_type
4280
4281
4282
4283 assert self.__baseTypeDefinition != self
4284 if not self.__baseTypeDefinition.isResolved():
4285 self._queueForResolution('base type %s is not resolved' % (self.__baseTypeDefinition,), depends_on=self.__baseTypeDefinition)
4286 return self
4287 if variety is None:
4288
4289
4290 variety = self.__baseTypeDefinition.__variety
4291 assert variety is not None
4292
4293 if self.VARIETY_absent == variety:
4294
4295
4296 pass
4297 elif self.VARIETY_atomic == variety:
4298
4299
4300
4301 ptd = self
4302 while isinstance(ptd, SimpleTypeDefinition) and (self.VARIETY_atomic == ptd.__baseTypeDefinition.variety()):
4303 ptd = ptd.__baseTypeDefinition
4304
4305 self.__primitiveTypeDefinition = ptd
4306 elif self.VARIETY_list == variety:
4307 if self._DA_list == alternative:
4308 if self.__itemTypeExpandedName is not None:
4309 self.__itemTypeDefinition = self.__itemTypeExpandedName.typeDefinition()
4310 if not isinstance(self.__itemTypeDefinition, SimpleTypeDefinition):
4311 raise pyxb.SchemaValidationError('Unable to locate STD %s for items' % (self.__itemTypeExpandedName,))
4312 elif self._DA_restriction == alternative:
4313 self.__itemTypeDefinition = self.__baseTypeDefinition.__itemTypeDefinition
4314 else:
4315 raise pyxb.LogicError('completeResolution list variety with alternative %s' % (alternative,))
4316 elif self.VARIETY_union == variety:
4317 if self._DA_union == alternative:
4318
4319
4320
4321
4322 if self.__memberTypeDefinitions is None:
4323 mtd = []
4324
4325
4326 if self.__memberTypesExpandedNames is not None:
4327 for mn_en in self.__memberTypesExpandedNames:
4328
4329 std = mn_en.typeDefinition()
4330 if std is None:
4331 raise pyxb.SchemaValidationError('Unable to locate member type %s' % (mn_en,))
4332
4333 assert isinstance(std, SimpleTypeDefinition)
4334 mtd.append(std)
4335
4336 mtd.extend(self.__localMemberTypes)
4337 self.__memberTypeDefinitions = mtd
4338 assert None not in self.__memberTypeDefinitions
4339
4340
4341
4342
4343
4344
4345 mtd = []
4346 for mt in self.__memberTypeDefinitions:
4347 assert isinstance(mt, SimpleTypeDefinition)
4348 if not mt.isResolved():
4349 self._queueForResolution('member type not resolved', depends_on=mt)
4350 return self
4351 if self.VARIETY_union == mt.variety():
4352 mtd.extend(mt.memberTypeDefinitions())
4353 else:
4354 mtd.append(mt)
4355 elif self._DA_restriction == alternative:
4356 assert self.__baseTypeDefinition
4357
4358 assert self.__baseTypeDefinition.isResolved()
4359 mtd = self.__baseTypeDefinition.__memberTypeDefinitions
4360 assert mtd is not None
4361 else:
4362 raise pyxb.LogicError('completeResolution union variety with alternative %s' % (alternative,))
4363
4364 self.__memberTypeDefinitions = mtd[:]
4365 else:
4366 raise pyxb.LogicError('completeResolution with variety 0x%02x' % (variety,))
4367
4368
4369
4370 self.__processHasFacetAndProperty(variety)
4371 try:
4372 pyxb.namespace.NamespaceContext.PushContext(pyxb.namespace.NamespaceContext.GetNodeContext(body))
4373 self.__updateFacets(body)
4374 finally:
4375 pyxb.namespace.NamespaceContext.PopContext()
4376
4377 self.__derivationAlternative = alternative
4378 self.__variety = variety
4379 self.__domNode = None
4380 return self
4381
4383 """Indicate whether this simple type is fully defined.
4384
4385 Type resolution for simple types means that the corresponding
4386 schema component fields have been set. Specifically, that
4387 means variety, baseTypeDefinition, and the appropriate
4388 additional fields depending on variety. See _resolve() for
4389 more information.
4390 """
4391
4392 return (self.__variety is not None)
4393
4394
4396 """Attempt to resolve the type.
4397
4398 Type resolution for simple types means that the corresponding
4399 schema component fields have been set. Specifically, that
4400 means variety, baseTypeDefinition, and the appropriate
4401 additional fields depending on variety.
4402
4403 All built-in STDs are resolved upon creation. Schema-defined
4404 STDs are held unresolved until the schema has been completely
4405 read, so that references to later schema-defined STDs can be
4406 resolved. Resolution is performed after the entire schema has
4407 been scanned and STD instances created for all
4408 topLevelSimpleTypes.
4409
4410 If a built-in STD is also defined in a schema (which it should
4411 be for XMLSchema), the built-in STD is kept, with the
4412 schema-related information copied over from the matching
4413 schema-defined STD. The former then replaces the latter in
4414 the list of STDs to be resolved.
4415
4416 Types defined by restriction have the same variety as the type
4417 they restrict. If a simple type restriction depends on an
4418 unresolved type, this method simply queues it for resolution
4419 in a later pass and returns.
4420 """
4421 if self.__variety is not None:
4422 return self
4423 assert self.__domNode
4424 node = self.__domNode
4425
4426 kw = { 'owner' : self
4427 , 'schema' : self._schema() }
4428
4429 bad_instance = False
4430
4431
4432 candidate = domutils.LocateUniqueChild(node, 'list')
4433 if candidate:
4434 self.__initializeFromList(candidate, **kw)
4435
4436 candidate = domutils.LocateUniqueChild(node, 'restriction')
4437 if candidate:
4438 if self.__variety is None:
4439 self.__initializeFromRestriction(candidate, **kw)
4440 else:
4441 bad_instance = True
4442
4443 candidate = domutils.LocateUniqueChild(node, 'union')
4444 if candidate:
4445 if self.__variety is None:
4446 self.__initializeFromUnion(candidate, **kw)
4447 else:
4448 bad_instance = True
4449
4450 if self.__baseTypeDefinition is None:
4451 raise pyxb.SchemaValidationError('xs:simpleType must have list, union, or restriction as child')
4452
4453 if self._schema() is not None:
4454 self.__final = self._schema().finalForNode(node, self._STD_Map)
4455
4456
4457 if bad_instance:
4458 raise pyxb.SchemaValidationError('Expected exactly one of list, restriction, union as child of simpleType')
4459
4460 return self
4461
4462
4463 @classmethod
4479
4480
4481
4482
4483 __pythonSupport = None
4484
4494
4497
4502
4505
4508
4510 """Subclass ensures there is only one simple ur-type."""
4511 pass
4512
4618
4619 -class Schema (_SchemaComponent_mixin):
4620 """An XMLSchema U{Schema<http://www.w3.org/TR/xmlschema-1/#Schemas>}."""
4621
4624
4625
4626 __annotations = None
4627
4628
4629
4630 __pastProlog = False
4631
4633 """URI or path to where the schema can be found.
4634
4635 For schema created by a user, the location should be provided to the
4636 constructor using the C{schema_location} keyword. In the case of
4637 imported or included schema, the including schema's location is used
4638 as the base URI for determining the absolute URI of the included
4639 schema from its (possibly relative) location value. For files,
4640 the scheme and authority portions are generally absent, as is often
4641 the abs_path part."""
4642 return self.__location
4643 __location = None
4644
4647 __locationTag = None
4648
4651 __signature = None
4652
4655 __generationUID = None
4656
4659 __originRecord = None
4660
4662 """The targetNamespace of a componen.
4663
4664 This is None, or a reference to a Namespace in which the
4665 component is declared (either as a global or local to one of
4666 the namespace's complex type definitions). This is immutable
4667 after creation.
4668 """
4669 return self.__targetNamespace
4670 __targetNamespace = None
4671
4673 """Default namespace of the schema.
4674
4675 Will be None unless the schema has an 'xmlns' attribute. The
4676 value must currently be provided as a keyword parameter to the
4677 constructor. """
4678 return self.__defaultNamespace
4679 __defaultNamespace = None
4680
4683 __referencedNamespaces = None
4684
4685 __namespaceData = None
4686
4689 __importEIIs = None
4690
4693 __importedSchema = None
4696 __includedSchema = None
4697
4698 _QUALIFIED = "qualified"
4699 _UNQUALIFIED = "unqualified"
4700
4701
4702 __attributeMap = { pyxb.namespace.ExpandedName(None, 'attributeFormDefault') : _UNQUALIFIED
4703 , pyxb.namespace.ExpandedName(None, 'elementFormDefault') : _UNQUALIFIED
4704 , pyxb.namespace.ExpandedName(None, 'blockDefault') : ''
4705 , pyxb.namespace.ExpandedName(None, 'finalDefault') : ''
4706 , pyxb.namespace.ExpandedName(None, 'id') : None
4707 , pyxb.namespace.ExpandedName(None, 'targetNamespace') : None
4708 , pyxb.namespace.ExpandedName(None, 'version') : None
4709 , pyxb.namespace.XML.createExpandedName('lang') : None
4710 }
4711
4716
4718 """Override the schema attributes with values from the given map."""
4719 self.__attributeMap.update(attr_map)
4720 return self
4721
4723 """Return True iff the schema has an attribute with the given (nc)name."""
4724 if isinstance(attr_name, six.string_types):
4725 attr_name = pyxb.namespace.ExpandedName(None, attr_name)
4726 return attr_name in self.__attributeMap
4727
4729 """Return the schema attribute value associated with the given (nc)name.
4730
4731 @param attr_name: local name for the attribute in the schema element.
4732 @return: the value of the corresponding attribute, or C{None} if it
4733 has not been defined and has no default.
4734 @raise KeyError: C{attr_name} is not a valid attribute for a C{schema} element.
4735 """
4736 if isinstance(attr_name, six.string_types):
4737 attr_name = pyxb.namespace.ExpandedName(None, attr_name)
4738 return self.__attributeMap[attr_name]
4739
4740 __SchemaCategories = ( 'typeDefinition', 'attributeGroupDefinition', 'modelGroupDefinition',
4741 'attributeDeclaration', 'elementDeclaration', 'notationDeclaration',
4742 'identityConstraintDefinition' )
4743
4746 __uriContentArchiveDirectory = None
4747
4789
4790 __TopLevelComponentMap = {
4791 'element' : ElementDeclaration,
4792 'attribute' : AttributeDeclaration,
4793 'notation' : NotationDeclaration,
4794 'simpleType' : SimpleTypeDefinition,
4795 'complexType' : ComplexTypeDefinition,
4796 'group' : ModelGroupDefinition,
4797 'attributeGroup' : AttributeGroupDefinition
4798 }
4799
4800 @classmethod
4805
4806 @classmethod
4808 """Create a schema from a schema location.
4809
4810 Reads an XML document from the schema location and creates a schema
4811 using it. All keyword parameters are passed to L{CreateFromDOM}.
4812
4813 @keyword schema_location: A file path or a URI. If this is a relative
4814 URI and C{parent_uri} is present, the actual location will be
4815 L{normallzed<pyxb.utils.utility.NormalizeLocation>}.
4816 @keyword parent_uri: The context within which schema_location will be
4817 normalized, if necessary.
4818 @keyword absolute_schema_location: A file path or URI. This value is
4819 not normalized, and supersedes C{schema_location}.
4820 """
4821 schema_location = kw.pop('absolute_schema_location', pyxb.utils.utility.NormalizeLocation(kw.get('schema_location'), kw.get('parent_uri'), kw.get('prefix_map')))
4822 kw['location_base'] = kw['schema_location'] = schema_location
4823 assert isinstance(schema_location, six.string_types), 'Unexpected value %s type %s for schema_location' % (schema_location, type(schema_location))
4824 uri_content_archive_directory = kw.get('uri_content_archive_directory')
4825 return cls.CreateFromDocument(pyxb.utils.utility.DataFromURI(schema_location, archive_directory=uri_content_archive_directory), **kw)
4826
4827 @classmethod
4830
4831 @classmethod
4832 - def CreateFromDOM (cls, node, namespace_context=None, schema_location=None, schema_signature=None, generation_uid=None, **kw):
4833 """Take the root element of the document, and scan its attributes under
4834 the assumption it is an XMLSchema schema element. That means
4835 recognize namespace declarations and process them. Also look for
4836 and set the default namespace. All other attributes are passed up
4837 to the parent class for storage."""
4838
4839
4840
4841 including_context = kw.get('including_context')
4842
4843 root_node = node
4844 if Node.DOCUMENT_NODE == node.nodeType:
4845 root_node = root_node.documentElement
4846 if Node.ELEMENT_NODE != root_node.nodeType:
4847 raise pyxb.LogicError('Must be given a DOM node of type ELEMENT')
4848
4849 assert (namespace_context is None) or isinstance(namespace_context, pyxb.namespace.NamespaceContext)
4850 ns_ctx = pyxb.namespace.NamespaceContext.GetNodeContext(root_node,
4851 parent_context=namespace_context,
4852 including_context=including_context)
4853
4854 tns = ns_ctx.targetNamespace()
4855 if tns is None:
4856 raise pyxb.SchemaValidationError('No targetNamespace associated with content (not a schema?)')
4857 schema = cls(namespace_context=ns_ctx, schema_location=schema_location, schema_signature=schema_signature, generation_uid=generation_uid, **kw)
4858 schema.__namespaceData = ns_ctx
4859
4860 if schema.targetNamespace() != ns_ctx.targetNamespace():
4861 raise pyxb.SchemaValidationError('targetNamespace %s conflicts with %s' % (schema.targetNamespace(), ns_ctx.targetNamespace()))
4862
4863
4864 for ai in range(root_node.attributes.length):
4865 schema._setAttributeFromDOM(root_node.attributes.item(ai))
4866
4867
4868 if not xsd.nodeIsNamed(root_node, 'schema'):
4869 raise pyxb.SchemaValidationError('Root node %s of document is not an XML schema element' % (root_node.nodeName,))
4870
4871 for cn in root_node.childNodes:
4872 if Node.ELEMENT_NODE == cn.nodeType:
4873 rv = schema.__processTopLevelNode(cn)
4874 if rv is None:
4875 _log.info('Unrecognized: %s %s', cn.nodeName, cn.toxml("utf-8"))
4876 elif Node.TEXT_NODE == cn.nodeType:
4877
4878
4879 text = cn.data.strip()
4880 if text:
4881 _log.info('Ignored text: %s', text)
4882 elif Node.COMMENT_NODE == cn.nodeType:
4883 pass
4884 else:
4885
4886
4887
4888
4889
4890
4891
4892 _log.info('Ignoring non-element: %s', cn)
4893
4894
4895
4896
4897 return schema
4898
4899 _SA_All = '#all'
4900
4902 ebv = domutils.NodeAttribute(dom_node, attr)
4903 if ebv is None:
4904 ebv = self.schemaAttribute('%sDefault' % (attr,))
4905 rv = 0
4906 if ebv == self._SA_All:
4907 for v in six.itervalues(candidate_map):
4908 rv += v
4909 else:
4910 for candidate in ebv.split():
4911 rv += candidate_map.get(candidate, 0)
4912 return rv
4913
4915 """Return a bit mask indicating a set of options read from the node's "block" attribute or the schema's "blockDefault" attribute.
4916
4917 A value of '#all' means enable every options; otherwise, the attribute
4918 value should be a list of tokens, for which the corresponding value
4919 will be added to the return value.
4920
4921 @param dom_node: the node from which the "block" attribute will be retrieved
4922 @type dom_node: C{xml.dom.Node}
4923 @param candidate_map: map from strings to bitmask values
4924 """
4925 return self.__ebvForNode('block', dom_node, candidate_map)
4926
4928 """Return a bit mask indicating a set of options read from the node's
4929 "final" attribute or the schema's "finalDefault" attribute.
4930
4931 A value of '#all' means enable every options; otherwise, the attribute
4932 value should be a list of tokens, for which the corresponding value
4933 will be added to the return value.
4934
4935 @param dom_node: the node from which the "final" attribute will be retrieved
4936 @type dom_node: C{xml.dom.Node}
4937 @param candidate_map: map from strings to bitmask values
4938 """
4939 return self.__ebvForNode('final', dom_node, candidate_map)
4940
4942 """Determine the target namespace for a local attribute or element declaration.
4943
4944 Look at the node's C{form} attribute, or if none the schema's
4945 C{attributeFormDefault} or C{elementFormDefault} value. If the
4946 resulting value is C{"qualified"} and the parent schema has a
4947 non-absent target namespace, return it to use as the declaration
4948 target namespace. Otherwise, return None to indicate that the
4949 declaration has no namespace.
4950
4951 @param dom_node: The node defining an element or attribute declaration
4952 @param declaration_type: Either L{AttributeDeclaration} or L{ElementDeclaration}
4953 @return: L{pyxb.namespace.Namespace} or None
4954 """
4955
4956 form_type = domutils.NodeAttribute(dom_node, 'form')
4957 if form_type is None:
4958 if declaration_type == ElementDeclaration:
4959 form_type = self.schemaAttribute('elementFormDefault')
4960 elif declaration_type == AttributeDeclaration:
4961 form_type = self.schemaAttribute('attributeFormDefault')
4962 else:
4963 raise pyxb.LogicError('Expected ElementDeclaration or AttributeDeclaration: got %s' % (declaration_type,))
4964 tns = None
4965 if (self._QUALIFIED == form_type):
4966 tns = self.targetNamespace()
4967 if tns.isAbsentNamespace():
4968 tns = None
4969 else:
4970 if (self._UNQUALIFIED != form_type):
4971 raise pyxb.SchemaValidationError('Form type neither %s nor %s' % (self._QUALIFIED, self._UNQUALIFIED))
4972 return tns
4973
4975 """Throw a SchemaValidationException referencing the given
4976 node if we have passed the sequence point representing the end
4977 of prolog elements."""
4978
4979 if self.__pastProlog:
4980 raise pyxb.SchemaValidationError('Unexpected node %s after prolog' % (node_name,))
4981
4983 self.__requireInProlog(node.nodeName)
4984
4985 abs_uri = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), self.__location)
4986 (has_schema, schema_instance) = self.targetNamespace().lookupSchemaByLocation(abs_uri)
4987 if not has_schema:
4988 kw = { 'absolute_schema_location': abs_uri,
4989 'including_context': self.__namespaceData,
4990 'generation_uid': self.generationUID(),
4991 'uri_content_archive_directory': self._uriContentArchiveDirectory(),
4992 }
4993 try:
4994 schema_instance = self.CreateFromLocation(**kw)
4995 except pyxb.SchemaUniquenessError as e:
4996 _log.warning('Skipping apparent redundant inclusion of %s defining %s (hash matches %s)', e.schemaLocation(), e.namespace(), e.existingSchema().location())
4997 except Exception as e:
4998 _log.exception('INCLUDE %s caught', abs_uri)
4999 raise
5000 if schema_instance:
5001 if self.targetNamespace() != schema_instance.targetNamespace():
5002 raise pyxb.SchemaValidationError('Included namespace %s not consistent with including namespace %s' % (schema_instance.targetNamespace(), self.targetNamespace()))
5003 self.__includedSchema.add(schema_instance)
5004 return node
5005
5023
5027
5031
5055
5059
5061 tns = self.targetNamespace()
5062 assert tns is not None
5063 if not isinstance(nc, _NamedComponent_mixin):
5064 raise pyxb.LogicError('Attempt to add unnamed %s instance to dictionary' % (nc.__class__,))
5065 if nc.isAnonymous():
5066 raise pyxb.LogicError('Attempt to add anonymous component to dictionary: %s', (nc.__class__,))
5067 if isinstance(nc, _ScopedDeclaration_mixin):
5068 assert _ScopedDeclaration_mixin.SCOPE_global == nc.scope()
5069 if isinstance(nc, (SimpleTypeDefinition, ComplexTypeDefinition)):
5070 return self.__addTypeDefinition(nc)
5071 if isinstance(nc, AttributeDeclaration):
5072 return self.__addAttributeDeclaration(nc)
5073 if isinstance(nc, AttributeGroupDefinition):
5074 return self.__addAttributeGroupDefinition(nc)
5075 if isinstance(nc, ModelGroupDefinition):
5076 return tns.addCategoryObject('modelGroupDefinition', nc.name(), nc)
5077 if isinstance(nc, ElementDeclaration):
5078 return tns.addCategoryObject('elementDeclaration', nc.name(), nc)
5079 if isinstance(nc, NotationDeclaration):
5080 return tns.addCategoryObject('notationDeclaration', nc.name(), nc)
5081 if isinstance(nc, IdentityConstraintDefinition):
5082 return tns.addCategoryObject('identityConstraintDefinition', nc.name(), nc)
5083 assert False, 'No support to record named component of type %s' % (nc.__class__,)
5084
5104
5121
5138
5140 return 'SCH[%s]' % (self.location(),)
5141
5144 """Add to the schema the definitions of the built-in types of XMLSchema.
5145 This should only be invoked by L{pyxb.namespace} when the built-in
5146 namespaces are initialized. """
5147
5148
5149 schema = Schema(namespace_context=pyxb.namespace.XMLSchema.initialNamespaceContext(), schema_location='URN:noLocation:PyXB:XMLSchema', generation_uid=pyxb.namespace.BuiltInObjectUID, _bypass_preload=True)
5150 td = schema._addNamedComponent(ComplexTypeDefinition.UrTypeDefinition(schema, in_builtin_definition=True))
5151 assert td.isResolved()
5152
5153 td = schema._addNamedComponent(SimpleTypeDefinition.SimpleUrTypeDefinition(schema, in_builtin_definition=True))
5154 assert td.isResolved()
5155
5156 pts_std_map = {}
5157 for dtc in datatypes._PrimitiveDatatypes:
5158 name = dtc.__name__.rstrip('_')
5159 td = schema._addNamedComponent(SimpleTypeDefinition.CreatePrimitiveInstance(name, schema, dtc))
5160 assert td.isResolved()
5161 assert dtc.SimpleTypeDefinition() == td
5162 pts_std_map.setdefault(dtc, td)
5163 for dtc in datatypes._DerivedDatatypes:
5164 name = dtc.__name__.rstrip('_')
5165 parent_std = pts_std_map[dtc.XsdSuperType()]
5166 td = schema._addNamedComponent(SimpleTypeDefinition.CreateDerivedInstance(name, schema, parent_std, dtc))
5167 assert td.isResolved()
5168 assert dtc.SimpleTypeDefinition() == td
5169 pts_std_map.setdefault(dtc, td)
5170 for dtc in datatypes._ListDatatypes:
5171 list_name = dtc.__name__.rstrip('_')
5172 element_name = dtc._ItemType.__name__.rstrip('_')
5173 element_std = schema.targetNamespace().typeDefinitions().get(element_name)
5174 assert element_std is not None
5175 td = schema._addNamedComponent(SimpleTypeDefinition.CreateListInstance(list_name, schema, element_std, dtc))
5176 assert td.isResolved()
5177 global _PastAddBuiltInTypes
5178 _PastAddBuiltInTypes = True
5179
5180 return schema
5181
5182 import sys
5183 import pyxb.namespace.builtin
5184 pyxb.namespace.builtin._InitializeBuiltinNamespaces(sys.modules[__name__])
5185
5186
5187
5188
5189