1# Copyright (c) 2003, The Regents of the University of California,
2# through Lawrence Berkeley National Laboratory (subject to receipt of
3# any required approvals from the U.S. Dept. of Energy).  All rights
4# reserved.
5#
6# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
7#
8# This software is subject to the provisions of the Zope Public License,
9# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
10# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
11# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
12# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
13# FOR A PARTICULAR PURPOSE.
14
15ident = "$Id: XMLSchema.py 1434 2007-11-01 22:42:47Z boverhof $"
16
17import types, weakref, sys, warnings
18from Namespaces import SCHEMA, XMLNS, SOAP
19from Utility import DOM, DOMException, Collection, SplitQName, basejoin
20from StringIO import StringIO
21
22# If we have no threading, this should be a no-op
23try:
24    from threading import RLock
25except ImportError:
26    class RLock:
27        def acquire():
28            pass
29        def release():
30            pass
31
32#
33# Collections in XMLSchema class
34#
35TYPES = 'types'
36ATTRIBUTE_GROUPS = 'attr_groups'
37ATTRIBUTES = 'attr_decl'
38ELEMENTS = 'elements'
39MODEL_GROUPS = 'model_groups'
40BUILT_IN_NAMESPACES = [SOAP.ENC,] + SCHEMA.XSD_LIST
41
42def GetSchema(component):
43    """convience function for finding the parent XMLSchema instance.
44    """
45    parent = component
46    while not isinstance(parent, XMLSchema):
47        parent = parent._parent()
48    return parent
49
50class SchemaReader:
51    """A SchemaReader creates XMLSchema objects from urls and xml data.
52    """
53
54    namespaceToSchema = {}
55
56    def __init__(self, domReader=None, base_url=None):
57        """domReader -- class must implement DOMAdapterInterface
58           base_url -- base url string
59        """
60        self.__base_url = base_url
61        self.__readerClass = domReader
62        if not self.__readerClass:
63            self.__readerClass = DOMAdapter
64        self._includes = {}
65        self._imports = {}
66
67    def __setImports(self, schema):
68        """Add dictionary of imports to schema instance.
69           schema -- XMLSchema instance
70        """
71        for ns,val in schema.imports.items():
72            if self._imports.has_key(ns):
73                schema.addImportSchema(self._imports[ns])
74
75    def __setIncludes(self, schema):
76        """Add dictionary of includes to schema instance.
77           schema -- XMLSchema instance
78        """
79        for schemaLocation, val in schema.includes.items():
80            if self._includes.has_key(schemaLocation):
81                schema.addIncludeSchema(schemaLocation, self._imports[schemaLocation])
82
83    def addSchemaByLocation(self, location, schema):
84        """provide reader with schema document for a location.
85        """
86        self._includes[location] = schema
87
88    def addSchemaByNamespace(self, schema):
89        """provide reader with schema document for a targetNamespace.
90        """
91        self._imports[schema.targetNamespace] = schema
92
93    def loadFromNode(self, parent, element):
94        """element -- DOM node or document
95           parent -- WSDLAdapter instance
96        """
97        reader = self.__readerClass(element)
98        schema = XMLSchema(parent)
99        #HACK to keep a reference
100        schema.wsdl = parent
101        schema.setBaseUrl(self.__base_url)
102        schema.load(reader)
103        return schema
104
105    def loadFromStream(self, file, url=None):
106        """Return an XMLSchema instance loaded from a file object.
107           file -- file object
108           url -- base location for resolving imports/includes.
109        """
110        reader = self.__readerClass()
111        reader.loadDocument(file)
112        schema = XMLSchema()
113        if url is not None:
114             schema.setBaseUrl(url)
115        schema.load(reader)
116        self.__setIncludes(schema)
117        self.__setImports(schema)
118        return schema
119
120    def loadFromString(self, data):
121        """Return an XMLSchema instance loaded from an XML string.
122           data -- XML string
123        """
124        return self.loadFromStream(StringIO(data))
125
126    def loadFromURL(self, url, schema=None):
127        """Return an XMLSchema instance loaded from the given url.
128           url -- URL to dereference
129           schema -- Optional XMLSchema instance.
130        """
131        reader = self.__readerClass()
132        if self.__base_url:
133            url = basejoin(self.__base_url,url)
134
135        reader.loadFromURL(url)
136        schema = schema or XMLSchema()
137        schema.setBaseUrl(url)
138        schema.load(reader)
139        self.__setIncludes(schema)
140        self.__setImports(schema)
141        return schema
142
143    def loadFromFile(self, filename):
144        """Return an XMLSchema instance loaded from the given file.
145           filename -- name of file to open
146        """
147        if self.__base_url:
148            filename = basejoin(self.__base_url,filename)
149        file = open(filename, 'rb')
150        try:
151            schema = self.loadFromStream(file, filename)
152        finally:
153            file.close()
154
155        return schema
156
157
158class SchemaError(Exception):
159    pass
160
161class NoSchemaLocationWarning(Exception):
162    pass
163
164
165###########################
166# DOM Utility Adapters
167##########################
168class DOMAdapterInterface:
169    def hasattr(self, attr, ns=None):
170        """return true if node has attribute
171           attr -- attribute to check for
172           ns -- namespace of attribute, by default None
173        """
174        raise NotImplementedError, 'adapter method not implemented'
175
176    def getContentList(self, *contents):
177        """returns an ordered list of child nodes
178           *contents -- list of node names to return
179        """
180        raise NotImplementedError, 'adapter method not implemented'
181
182    def setAttributeDictionary(self, attributes):
183        """set attribute dictionary
184        """
185        raise NotImplementedError, 'adapter method not implemented'
186
187    def getAttributeDictionary(self):
188        """returns a dict of node's attributes
189        """
190        raise NotImplementedError, 'adapter method not implemented'
191
192    def getNamespace(self, prefix):
193        """returns namespace referenced by prefix.
194        """
195        raise NotImplementedError, 'adapter method not implemented'
196
197    def getTagName(self):
198        """returns tagName of node
199        """
200        raise NotImplementedError, 'adapter method not implemented'
201
202
203    def getParentNode(self):
204        """returns parent element in DOMAdapter or None
205        """
206        raise NotImplementedError, 'adapter method not implemented'
207
208    def loadDocument(self, file):
209        """load a Document from a file object
210           file --
211        """
212        raise NotImplementedError, 'adapter method not implemented'
213
214    def loadFromURL(self, url):
215        """load a Document from an url
216           url -- URL to dereference
217        """
218        raise NotImplementedError, 'adapter method not implemented'
219
220
221class DOMAdapter(DOMAdapterInterface):
222    """Adapter for ZSI.Utility.DOM
223    """
224    def __init__(self, node=None):
225        """Reset all instance variables.
226           element -- DOM document, node, or None
227        """
228        if hasattr(node, 'documentElement'):
229            self.__node = node.documentElement
230        else:
231            self.__node = node
232        self.__attributes = None
233
234    def getNode(self):
235        return self.__node
236
237    def hasattr(self, attr, ns=None):
238        """attr -- attribute
239           ns -- optional namespace, None means unprefixed attribute.
240        """
241        if not self.__attributes:
242            self.setAttributeDictionary()
243        if ns:
244            return self.__attributes.get(ns,{}).has_key(attr)
245        return self.__attributes.has_key(attr)
246
247    def getContentList(self, *contents):
248        nodes = []
249        ELEMENT_NODE = self.__node.ELEMENT_NODE
250        for child in DOM.getElements(self.__node, None):
251            if child.nodeType == ELEMENT_NODE and\
252               SplitQName(child.tagName)[1] in contents:
253                nodes.append(child)
254        return map(self.__class__, nodes)
255
256    def setAttributeDictionary(self):
257        self.__attributes = {}
258        for v in self.__node._attrs.values():
259            self.__attributes[v.nodeName] = v.nodeValue
260
261    def getAttributeDictionary(self):
262        if not self.__attributes:
263            self.setAttributeDictionary()
264        return self.__attributes
265
266    def getTagName(self):
267        return self.__node.tagName
268
269    def getParentNode(self):
270        if self.__node.parentNode.nodeType == self.__node.ELEMENT_NODE:
271            return DOMAdapter(self.__node.parentNode)
272        return None
273
274    def getNamespace(self, prefix):
275        """prefix -- deference namespace prefix in node's context.
276           Ascends parent nodes until found.
277        """
278        namespace = None
279        if prefix == 'xmlns':
280            namespace = DOM.findDefaultNS(prefix, self.__node)
281        else:
282            try:
283                namespace = DOM.findNamespaceURI(prefix, self.__node)
284            except DOMException, ex:
285                if prefix != 'xml':
286                    raise SchemaError, '%s namespace not declared for %s'\
287                        %(prefix, self.__node._get_tagName())
288                namespace = XMLNS.XML
289        return namespace
290
291    def loadDocument(self, file):
292        self.__node = DOM.loadDocument(file)
293        if hasattr(self.__node, 'documentElement'):
294            self.__node = self.__node.documentElement
295
296    def loadFromURL(self, url):
297        self.__node = DOM.loadFromURL(url)
298        if hasattr(self.__node, 'documentElement'):
299            self.__node = self.__node.documentElement
300
301
302class XMLBase:
303    """ These class variables are for string indentation.
304    """
305    tag = None
306    __indent = 0
307    __rlock = RLock()
308
309    def __str__(self):
310        XMLBase.__rlock.acquire()
311        XMLBase.__indent += 1
312        tmp = "<" + str(self.__class__) + '>\n'
313        for k,v in self.__dict__.items():
314            tmp += "%s* %s = %s\n" %(XMLBase.__indent*'  ', k, v)
315        XMLBase.__indent -= 1
316        XMLBase.__rlock.release()
317        return tmp
318
319
320"""Marker Interface:  can determine something about an instances properties by using
321        the provided convenience functions.
322
323"""
324class DefinitionMarker:
325    """marker for definitions
326    """
327    pass
328
329class DeclarationMarker:
330    """marker for declarations
331    """
332    pass
333
334class AttributeMarker:
335    """marker for attributes
336    """
337    pass
338
339class AttributeGroupMarker:
340    """marker for attribute groups
341    """
342    pass
343
344class WildCardMarker:
345    """marker for wildcards
346    """
347    pass
348
349class ElementMarker:
350    """marker for wildcards
351    """
352    pass
353
354class ReferenceMarker:
355    """marker for references
356    """
357    pass
358
359class ModelGroupMarker:
360    """marker for model groups
361    """
362    pass
363
364class AllMarker(ModelGroupMarker):
365    """marker for all model group
366    """
367    pass
368
369class ChoiceMarker(ModelGroupMarker):
370    """marker for choice model group
371    """
372    pass
373
374class SequenceMarker(ModelGroupMarker):
375    """marker for sequence model group
376    """
377    pass
378
379class ExtensionMarker:
380    """marker for extensions
381    """
382    pass
383
384class RestrictionMarker:
385    """marker for restrictions
386    """
387    facets = ['enumeration', 'length', 'maxExclusive', 'maxInclusive',\
388        'maxLength', 'minExclusive', 'minInclusive', 'minLength',\
389        'pattern', 'fractionDigits', 'totalDigits', 'whiteSpace']
390
391class SimpleMarker:
392    """marker for simple type information
393    """
394    pass
395
396class ListMarker:
397    """marker for simple type list
398    """
399    pass
400
401class UnionMarker:
402    """marker for simple type Union
403    """
404    pass
405
406
407class ComplexMarker:
408    """marker for complex type information
409    """
410    pass
411
412class LocalMarker:
413    """marker for complex type information
414    """
415    pass
416
417
418class MarkerInterface:
419    def isDefinition(self):
420        return isinstance(self, DefinitionMarker)
421
422    def isDeclaration(self):
423        return isinstance(self, DeclarationMarker)
424
425    def isAttribute(self):
426        return isinstance(self, AttributeMarker)
427
428    def isAttributeGroup(self):
429        return isinstance(self, AttributeGroupMarker)
430
431    def isElement(self):
432        return isinstance(self, ElementMarker)
433
434    def isReference(self):
435        return isinstance(self, ReferenceMarker)
436
437    def isWildCard(self):
438        return isinstance(self, WildCardMarker)
439
440    def isModelGroup(self):
441        return isinstance(self, ModelGroupMarker)
442
443    def isAll(self):
444        return isinstance(self, AllMarker)
445
446    def isChoice(self):
447        return isinstance(self, ChoiceMarker)
448
449    def isSequence(self):
450        return isinstance(self, SequenceMarker)
451
452    def isExtension(self):
453        return isinstance(self, ExtensionMarker)
454
455    def isRestriction(self):
456        return isinstance(self, RestrictionMarker)
457
458    def isSimple(self):
459        return isinstance(self, SimpleMarker)
460
461    def isComplex(self):
462        return isinstance(self, ComplexMarker)
463
464    def isLocal(self):
465        return isinstance(self, LocalMarker)
466
467    def isList(self):
468        return isinstance(self, ListMarker)
469
470    def isUnion(self):
471        return isinstance(self, UnionMarker)
472
473
474##########################################################
475# Schema Components
476#########################################################
477class XMLSchemaComponent(XMLBase, MarkerInterface):
478    """
479       class variables:
480           required -- list of required attributes
481           attributes -- dict of default attribute values, including None.
482               Value can be a function for runtime dependencies.
483           contents -- dict of namespace keyed content lists.
484               'xsd' content of xsd namespace.
485           xmlns_key -- key for declared xmlns namespace.
486           xmlns -- xmlns is special prefix for namespace dictionary
487           xml -- special xml prefix for xml namespace.
488    """
489    required = []
490    attributes = {}
491    contents = {}
492    xmlns_key = ''
493    xmlns = 'xmlns'
494    xml = 'xml'
495
496    def __init__(self, parent=None):
497        """parent -- parent instance
498           instance variables:
499               attributes -- dictionary of node's attributes
500        """
501        self.attributes = None
502        self._parent = parent
503        if self._parent:
504            self._parent = weakref.ref(parent)
505
506        if not self.__class__ == XMLSchemaComponent\
507           and not (type(self.__class__.required) == type(XMLSchemaComponent.required)\
508           and type(self.__class__.attributes) == type(XMLSchemaComponent.attributes)\
509           and type(self.__class__.contents) == type(XMLSchemaComponent.contents)):
510            raise RuntimeError, 'Bad type for a class variable in %s' %self.__class__
511
512    def getItemTrace(self):
513        """Returns a node trace up to the <schema> item.
514        """
515        item, path, name, ref = self, [], 'name', 'ref'
516        while not isinstance(item,XMLSchema) and not isinstance(item,WSDLToolsAdapter):
517            attr = item.getAttribute(name)
518            if not attr:
519                attr = item.getAttribute(ref)
520                if not attr:
521                    path.append('<%s>' %(item.tag))
522                else:
523                    path.append('<%s ref="%s">' %(item.tag, attr))
524            else:
525                path.append('<%s name="%s">' %(item.tag,attr))
526
527            item = item._parent()
528        try:
529            tns = item.getTargetNamespace()
530        except:
531            tns = ''
532        path.append('<%s targetNamespace="%s">' %(item.tag, tns))
533        path.reverse()
534        return ''.join(path)
535
536    def getTargetNamespace(self):
537        """return targetNamespace
538        """
539        parent = self
540        targetNamespace = 'targetNamespace'
541        tns = self.attributes.get(targetNamespace)
542        while not tns and parent and parent._parent is not None:
543            parent = parent._parent()
544            tns = parent.attributes.get(targetNamespace)
545        return tns or ''
546
547    def getAttributeDeclaration(self, attribute):
548        """attribute -- attribute with a QName value (eg. type).
549           collection -- check types collection in parent Schema instance
550        """
551        return self.getQNameAttribute(ATTRIBUTES, attribute)
552
553    def getAttributeGroup(self, attribute):
554        """attribute -- attribute with a QName value (eg. type).
555           collection -- check types collection in parent Schema instance
556        """
557        return self.getQNameAttribute(ATTRIBUTE_GROUPS, attribute)
558
559    def getTypeDefinition(self, attribute):
560        """attribute -- attribute with a QName value (eg. type).
561           collection -- check types collection in parent Schema instance
562        """
563        return self.getQNameAttribute(TYPES, attribute)
564
565    def getElementDeclaration(self, attribute):
566        """attribute -- attribute with a QName value (eg. element).
567           collection -- check elements collection in parent Schema instance.
568        """
569        return self.getQNameAttribute(ELEMENTS, attribute)
570
571    def getModelGroup(self, attribute):
572        """attribute -- attribute with a QName value (eg. ref).
573           collection -- check model_group collection in parent Schema instance.
574        """
575        return self.getQNameAttribute(MODEL_GROUPS, attribute)
576
577    def getQNameAttribute(self, collection, attribute):
578        """returns object instance representing QName --> (namespace,name),
579           or if does not exist return None.
580           attribute -- an information item attribute, with a QName value.
581           collection -- collection in parent Schema instance to search.
582        """
583        tdc = self.getAttributeQName(attribute)
584        if not tdc:
585            return
586
587        obj = self.getSchemaItem(collection, tdc.getTargetNamespace(), tdc.getName())
588        if obj:
589            return obj
590
591#        raise SchemaError, 'No schema item "%s" in collection %s' %(tdc, collection)
592        return
593
594    def getSchemaItem(self, collection, namespace, name):
595        """returns object instance representing namespace, name,
596           or if does not exist return None if built-in, else
597           raise SchemaError.
598
599           namespace -- namespace item defined in.
600           name -- name of item.
601           collection -- collection in parent Schema instance to search.
602        """
603        parent = GetSchema(self)
604        if parent.targetNamespace == namespace:
605            try:
606                obj = getattr(parent, collection)[name]
607            except KeyError, ex:
608                raise KeyError, 'targetNamespace(%s) collection(%s) has no item(%s)'\
609                    %(namespace, collection, name)
610
611            return obj
612
613        if not parent.imports.has_key(namespace):
614            if namespace in BUILT_IN_NAMESPACES:
615                # built-in just return
616                # WARNING: expecting import if "redefine" or add to built-in namespace.
617                return
618
619            raise SchemaError, 'schema "%s" does not import namespace "%s"' %(
620                parent.targetNamespace, namespace)
621
622        # Lazy Eval
623        schema = parent.imports[namespace]
624        if not isinstance(schema, XMLSchema):
625            schema = schema.getSchema()
626            if schema is not None:
627                parent.imports[namespace] = schema
628
629        if schema is None:
630            if namespace in BUILT_IN_NAMESPACES:
631                # built-in just return
632                return
633
634            raise SchemaError, 'no schema instance for imported namespace (%s).'\
635                %(namespace)
636
637        if not isinstance(schema, XMLSchema):
638            raise TypeError, 'expecting XMLSchema instance not "%r"' %schema
639
640        try:
641            obj = getattr(schema, collection)[name]
642        except KeyError, ex:
643            raise KeyError, 'targetNamespace(%s) collection(%s) has no item(%s)'\
644                %(namespace, collection, name)
645
646        return obj
647
648    def getXMLNS(self, prefix=None):
649        """deference prefix or by default xmlns, returns namespace.
650        """
651        if prefix == XMLSchemaComponent.xml:
652            return XMLNS.XML
653        parent = self
654        ns = self.attributes[XMLSchemaComponent.xmlns].get(prefix or\
655                XMLSchemaComponent.xmlns_key)
656        while not ns:
657            parent = parent._parent()
658            ns = parent.attributes[XMLSchemaComponent.xmlns].get(prefix or\
659                    XMLSchemaComponent.xmlns_key)
660            if not ns and isinstance(parent, WSDLToolsAdapter):
661                if prefix is None:
662                    return ''
663                raise SchemaError, 'unknown prefix %s' %prefix
664        return ns
665
666    def getAttribute(self, attribute):
667        """return requested attribute value or None
668        """
669        if type(attribute) in (list, tuple):
670            if len(attribute) != 2:
671                raise LookupError, 'To access attributes must use name or (namespace,name)'
672
673            ns_dict = self.attributes.get(attribute[0])
674            if ns_dict is None:
675                return None
676
677            return ns_dict.get(attribute[1])
678
679        return self.attributes.get(attribute)
680
681    def getAttributeQName(self, attribute):
682        """return requested attribute value as (namespace,name) or None
683        """
684        qname = self.getAttribute(attribute)
685        if isinstance(qname, TypeDescriptionComponent) is True:
686            return qname
687        if qname is None:
688            return None
689
690        prefix,ncname = SplitQName(qname)
691        namespace = self.getXMLNS(prefix)
692        return TypeDescriptionComponent((namespace,ncname))
693
694    def getAttributeName(self):
695        """return attribute name or None
696        """
697        return self.getAttribute('name')
698
699    def setAttributes(self, node):
700        """Sets up attribute dictionary, checks for required attributes and
701           sets default attribute values. attr is for default attribute values
702           determined at runtime.
703
704           structure of attributes dictionary
705               ['xmlns'][xmlns_key] --  xmlns namespace
706               ['xmlns'][prefix] --  declared namespace prefix
707               [namespace][prefix] -- attributes declared in a namespace
708               [attribute] -- attributes w/o prefix, default namespaces do
709                   not directly apply to attributes, ie Name can't collide
710                   with QName.
711        """
712        self.attributes = {XMLSchemaComponent.xmlns:{}}
713        for k,v in node.getAttributeDictionary().items():
714            prefix,value = SplitQName(k)
715            if value == XMLSchemaComponent.xmlns:
716                self.attributes[value][prefix or XMLSchemaComponent.xmlns_key] = v
717            elif prefix:
718                ns = node.getNamespace(prefix)
719                if not ns:
720                    raise SchemaError, 'no namespace for attribute prefix %s'\
721                        %prefix
722                if not self.attributes.has_key(ns):
723                    self.attributes[ns] = {}
724                elif self.attributes[ns].has_key(value):
725                    raise SchemaError, 'attribute %s declared multiple times in %s'\
726                        %(value, ns)
727                self.attributes[ns][value] = v
728            elif not self.attributes.has_key(value):
729                self.attributes[value] = v
730            else:
731                raise SchemaError, 'attribute %s declared multiple times' %value
732
733        if not isinstance(self, WSDLToolsAdapter):
734            self.__checkAttributes()
735        self.__setAttributeDefaults()
736
737        #set QNames
738        for k in ['type', 'element', 'base', 'ref', 'substitutionGroup', 'itemType']:
739            if self.attributes.has_key(k):
740                prefix, value = SplitQName(self.attributes.get(k))
741                self.attributes[k] = \
742                    TypeDescriptionComponent((self.getXMLNS(prefix), value))
743
744        #Union, memberTypes is a whitespace separated list of QNames
745        for k in ['memberTypes']:
746            if self.attributes.has_key(k):
747                qnames = self.attributes[k]
748                self.attributes[k] = []
749                for qname in qnames.split():
750                    prefix, value = SplitQName(qname)
751                    self.attributes['memberTypes'].append(\
752                        TypeDescriptionComponent(\
753                            (self.getXMLNS(prefix), value)))
754
755    def getContents(self, node):
756        """retrieve xsd contents
757        """
758        return node.getContentList(*self.__class__.contents['xsd'])
759
760    def __setAttributeDefaults(self):
761        """Looks for default values for unset attributes.  If
762           class variable representing attribute is None, then
763           it must be defined as an instance variable.
764        """
765        for k,v in self.__class__.attributes.items():
766            if v is not None and self.attributes.has_key(k) is False:
767                if isinstance(v, types.FunctionType):
768                    self.attributes[k] = v(self)
769                else:
770                    self.attributes[k] = v
771
772    def __checkAttributes(self):
773        """Checks that required attributes have been defined,
774           attributes w/default cannot be required.   Checks
775           all defined attributes are legal, attribute
776           references are not subject to this test.
777        """
778        for a in self.__class__.required:
779            if not self.attributes.has_key(a):
780                raise SchemaError,\
781                    'class instance %s, missing required attribute %s'\
782                    %(self.__class__, a)
783        for a,v in self.attributes.items():
784            # attribute #other, ie. not in empty namespace
785            if type(v) is dict:
786                continue
787
788            # predefined prefixes xmlns, xml
789            if a in (XMLSchemaComponent.xmlns, XMLNS.XML):
790                continue
791
792            if (a not in self.__class__.attributes.keys()) and not\
793                (self.isAttribute() and self.isReference()):
794                raise SchemaError, '%s, unknown attribute(%s,%s)' \
795                    %(self.getItemTrace(), a, self.attributes[a])
796
797
798class WSDLToolsAdapter(XMLSchemaComponent):
799    """WSDL Adapter to grab the attributes from the wsdl document node.
800    """
801    attributes = {'name':None, 'targetNamespace':None}
802    tag = 'definitions'
803
804    def __init__(self, wsdl):
805        XMLSchemaComponent.__init__(self, parent=wsdl)
806        self.setAttributes(DOMAdapter(wsdl.document))
807
808    def getImportSchemas(self):
809        """returns WSDLTools.WSDL types Collection
810        """
811        return self._parent().types
812
813
814class Notation(XMLSchemaComponent):
815    """<notation>
816       parent:
817           schema
818       attributes:
819           id -- ID
820           name -- NCName, Required
821           public -- token, Required
822           system -- anyURI
823       contents:
824           annotation?
825    """
826    required = ['name', 'public']
827    attributes = {'id':None, 'name':None, 'public':None, 'system':None}
828    contents = {'xsd':('annotation')}
829    tag = 'notation'
830
831    def __init__(self, parent):
832        XMLSchemaComponent.__init__(self, parent)
833        self.annotation = None
834
835    def fromDom(self, node):
836        self.setAttributes(node)
837        contents = self.getContents(node)
838
839        for i in contents:
840            component = SplitQName(i.getTagName())[1]
841            if component == 'annotation' and not self.annotation:
842                self.annotation = Annotation(self)
843                self.annotation.fromDom(i)
844            else:
845                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
846
847
848class Annotation(XMLSchemaComponent):
849    """<annotation>
850       parent:
851           all,any,anyAttribute,attribute,attributeGroup,choice,complexContent,
852           complexType,element,extension,field,group,import,include,key,keyref,
853           list,notation,redefine,restriction,schema,selector,simpleContent,
854           simpleType,union,unique
855       attributes:
856           id -- ID
857       contents:
858           (documentation | appinfo)*
859    """
860    attributes = {'id':None}
861    contents = {'xsd':('documentation', 'appinfo')}
862    tag = 'annotation'
863
864    def __init__(self, parent):
865        XMLSchemaComponent.__init__(self, parent)
866        self.content = None
867
868    def fromDom(self, node):
869        self.setAttributes(node)
870        contents = self.getContents(node)
871        content = []
872
873        for i in contents:
874            component = SplitQName(i.getTagName())[1]
875            if component == 'documentation':
876                #print_debug('class %s, documentation skipped' %self.__class__, 5)
877                continue
878            elif component == 'appinfo':
879                #print_debug('class %s, appinfo skipped' %self.__class__, 5)
880                continue
881            else:
882                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
883        self.content = tuple(content)
884
885
886    class Documentation(XMLSchemaComponent):
887        """<documentation>
888           parent:
889               annotation
890           attributes:
891               source, anyURI
892               xml:lang, language
893           contents:
894               mixed, any
895        """
896        attributes = {'source':None, 'xml:lang':None}
897        contents = {'xsd':('mixed', 'any')}
898        tag = 'documentation'
899
900        def __init__(self, parent):
901            XMLSchemaComponent.__init__(self, parent)
902            self.content = None
903
904        def fromDom(self, node):
905            self.setAttributes(node)
906            contents = self.getContents(node)
907            content = []
908
909            for i in contents:
910                component = SplitQName(i.getTagName())[1]
911                if component == 'mixed':
912                    #print_debug('class %s, mixed skipped' %self.__class__, 5)
913                    continue
914                elif component == 'any':
915                    #print_debug('class %s, any skipped' %self.__class__, 5)
916                    continue
917                else:
918                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
919            self.content = tuple(content)
920
921
922    class Appinfo(XMLSchemaComponent):
923        """<appinfo>
924           parent:
925               annotation
926           attributes:
927               source, anyURI
928           contents:
929               mixed, any
930        """
931        attributes = {'source':None, 'anyURI':None}
932        contents = {'xsd':('mixed', 'any')}
933        tag = 'appinfo'
934
935        def __init__(self, parent):
936            XMLSchemaComponent.__init__(self, parent)
937            self.content = None
938
939        def fromDom(self, node):
940            self.setAttributes(node)
941            contents = self.getContents(node)
942            content = []
943
944            for i in contents:
945                component = SplitQName(i.getTagName())[1]
946                if component == 'mixed':
947                    #print_debug('class %s, mixed skipped' %self.__class__, 5)
948                    continue
949                elif component == 'any':
950                    #print_debug('class %s, any skipped' %self.__class__, 5)
951                    continue
952                else:
953                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
954            self.content = tuple(content)
955
956
957class XMLSchemaFake:
958    # This is temporary, for the benefit of WSDL until the real thing works.
959    def __init__(self, element):
960        self.targetNamespace = DOM.getAttr(element, 'targetNamespace')
961        self.element = element
962
963class XMLSchema(XMLSchemaComponent):
964    """A schema is a collection of schema components derived from one
965       or more schema documents, that is, one or more <schema> element
966       information items. It represents the abstract notion of a schema
967       rather than a single schema document (or other representation).
968
969       <schema>
970       parent:
971           ROOT
972       attributes:
973           id -- ID
974           version -- token
975           xml:lang -- language
976           targetNamespace -- anyURI
977           attributeFormDefault -- 'qualified' | 'unqualified', 'unqualified'
978           elementFormDefault -- 'qualified' | 'unqualified', 'unqualified'
979           blockDefault -- '#all' | list of
980               ('substitution | 'extension' | 'restriction')
981           finalDefault -- '#all' | list of
982               ('extension' | 'restriction' | 'list' | 'union')
983
984       contents:
985           ((include | import | redefine | annotation)*,
986            (attribute, attributeGroup, complexType, element, group,
987             notation, simpleType)*, annotation*)*
988
989
990        attributes -- schema attributes
991        imports -- import statements
992        includes -- include statements
993        redefines --
994        types    -- global simpleType, complexType definitions
995        elements -- global element declarations
996        attr_decl -- global attribute declarations
997        attr_groups -- attribute Groups
998        model_groups -- model Groups
999        notations -- global notations
1000    """
1001    attributes = {'id':None,
1002        'version':None,
1003        'xml:lang':None,
1004        'targetNamespace':None,
1005        'attributeFormDefault':'unqualified',
1006        'elementFormDefault':'unqualified',
1007        'blockDefault':None,
1008        'finalDefault':None}
1009    contents = {'xsd':('include', 'import', 'redefine', 'annotation',
1010                       'attribute', 'attributeGroup', 'complexType',
1011                       'element', 'group', 'notation', 'simpleType',
1012                       'annotation')}
1013    empty_namespace = ''
1014    tag = 'schema'
1015
1016    def __init__(self, parent=None):
1017        """parent --
1018           instance variables:
1019           targetNamespace -- schema's declared targetNamespace, or empty string.
1020           _imported_schemas -- namespace keyed dict of schema dependencies, if
1021              a schema is provided instance will not resolve import statement.
1022           _included_schemas -- schemaLocation keyed dict of component schemas,
1023              if schema is provided instance will not resolve include statement.
1024           _base_url -- needed for relative URLs support, only works with URLs
1025               relative to initial document.
1026           includes -- collection of include statements
1027           imports -- collection of import statements
1028           elements -- collection of global element declarations
1029           types -- collection of global type definitions
1030           attr_decl -- collection of global attribute declarations
1031           attr_groups -- collection of global attribute group definitions
1032           model_groups -- collection of model group definitions
1033           notations -- collection of notations
1034
1035        """
1036        self.__node = None
1037        self.targetNamespace = None
1038        XMLSchemaComponent.__init__(self, parent)
1039        f = lambda k: k.attributes['name']
1040        ns = lambda k: k.attributes['namespace']
1041        sl = lambda k: k.attributes['schemaLocation']
1042        self.includes = Collection(self, key=sl)
1043        self.imports = Collection(self, key=ns)
1044        self.elements = Collection(self, key=f)
1045        self.types = Collection(self, key=f)
1046        self.attr_decl = Collection(self, key=f)
1047        self.attr_groups = Collection(self, key=f)
1048        self.model_groups = Collection(self, key=f)
1049        self.notations = Collection(self, key=f)
1050
1051        self._imported_schemas = {}
1052        self._included_schemas = {}
1053        self._base_url = None
1054
1055    def getNode(self):
1056        """
1057        Interacting with the underlying DOM tree.
1058        """
1059        return self.__node
1060
1061    def addImportSchema(self, schema):
1062        """for resolving import statements in Schema instance
1063           schema -- schema instance
1064           _imported_schemas
1065        """
1066        if not isinstance(schema, XMLSchema):
1067            raise TypeError, 'expecting a Schema instance'
1068        if schema.targetNamespace != self.targetNamespace:
1069            self._imported_schemas[schema.targetNamespace] = schema
1070        else:
1071            raise SchemaError, 'import schema bad targetNamespace'
1072
1073    def addIncludeSchema(self, schemaLocation, schema):
1074        """for resolving include statements in Schema instance
1075           schemaLocation -- schema location
1076           schema -- schema instance
1077           _included_schemas
1078        """
1079        if not isinstance(schema, XMLSchema):
1080            raise TypeError, 'expecting a Schema instance'
1081        if not schema.targetNamespace or\
1082             schema.targetNamespace == self.targetNamespace:
1083            self._included_schemas[schemaLocation] = schema
1084        else:
1085            raise SchemaError, 'include schema bad targetNamespace'
1086
1087    def setImportSchemas(self, schema_dict):
1088        """set the import schema dictionary, which is used to
1089           reference depedent schemas.
1090        """
1091        self._imported_schemas = schema_dict
1092
1093    def getImportSchemas(self):
1094        """get the import schema dictionary, which is used to
1095           reference depedent schemas.
1096        """
1097        return self._imported_schemas
1098
1099    def getSchemaNamespacesToImport(self):
1100        """returns tuple of namespaces the schema instance has declared
1101           itself to be depedent upon.
1102        """
1103        return tuple(self.includes.keys())
1104
1105    def setIncludeSchemas(self, schema_dict):
1106        """set the include schema dictionary, which is keyed with
1107           schemaLocation (uri).
1108           This is a means of providing
1109           schemas to the current schema for content inclusion.
1110        """
1111        self._included_schemas = schema_dict
1112
1113    def getIncludeSchemas(self):
1114        """get the include schema dictionary, which is keyed with
1115           schemaLocation (uri).
1116        """
1117        return self._included_schemas
1118
1119    def getBaseUrl(self):
1120        """get base url, used for normalizing all relative uri's
1121        """
1122        return self._base_url
1123
1124    def setBaseUrl(self, url):
1125        """set base url, used for normalizing all relative uri's
1126        """
1127        self._base_url = url
1128
1129    def getElementFormDefault(self):
1130        """return elementFormDefault attribute
1131        """
1132        return self.attributes.get('elementFormDefault')
1133
1134    def isElementFormDefaultQualified(self):
1135        return self.attributes.get('elementFormDefault') == 'qualified'
1136
1137    def getAttributeFormDefault(self):
1138        """return attributeFormDefault attribute
1139        """
1140        return self.attributes.get('attributeFormDefault')
1141
1142    def getBlockDefault(self):
1143        """return blockDefault attribute
1144        """
1145        return self.attributes.get('blockDefault')
1146
1147    def getFinalDefault(self):
1148        """return finalDefault attribute
1149        """
1150        return self.attributes.get('finalDefault')
1151
1152    def load(self, node, location=None):
1153        self.__node = node
1154
1155        pnode = node.getParentNode()
1156        if pnode:
1157            pname = SplitQName(pnode.getTagName())[1]
1158            if pname == 'types':
1159                attributes = {}
1160                self.setAttributes(pnode)
1161                attributes.update(self.attributes)
1162                self.setAttributes(node)
1163                for k,v in attributes['xmlns'].items():
1164                    if not self.attributes['xmlns'].has_key(k):
1165                        self.attributes['xmlns'][k] = v
1166            else:
1167                self.setAttributes(node)
1168        else:
1169            self.setAttributes(node)
1170
1171        self.targetNamespace = self.getTargetNamespace()
1172        for childNode in self.getContents(node):
1173            component = SplitQName(childNode.getTagName())[1]
1174
1175            if component == 'include':
1176                tp = self.__class__.Include(self)
1177                tp.fromDom(childNode)
1178
1179                sl = tp.attributes['schemaLocation']
1180                schema = tp.getSchema()
1181
1182                if not self.getIncludeSchemas().has_key(sl):
1183                    self.addIncludeSchema(sl, schema)
1184
1185                self.includes[sl] = tp
1186
1187                pn = childNode.getParentNode().getNode()
1188                pn.removeChild(childNode.getNode())
1189                for child in schema.getNode().getNode().childNodes:
1190                    pn.appendChild(child.cloneNode(1))
1191
1192                for collection in ['imports','elements','types',
1193                                   'attr_decl','attr_groups','model_groups',
1194                                   'notations']:
1195                    for k,v in getattr(schema,collection).items():
1196                        if not getattr(self,collection).has_key(k):
1197                            v._parent = weakref.ref(self)
1198                            getattr(self,collection)[k] = v
1199                        else:
1200                            warnings.warn("Not keeping schema component.")
1201
1202            elif component == 'import':
1203                slocd = SchemaReader.namespaceToSchema
1204                tp = self.__class__.Import(self)
1205                tp.fromDom(childNode)
1206                import_ns = tp.getAttribute('namespace') or\
1207                    self.__class__.empty_namespace
1208                schema = slocd.get(import_ns)
1209                if schema is None:
1210                    schema = XMLSchema()
1211                    slocd[import_ns] = schema
1212                    try:
1213                        tp.loadSchema(schema)
1214                    except NoSchemaLocationWarning, ex:
1215                        # Dependency declaration, hopefully implementation
1216                        # is aware of this namespace (eg. SOAP,WSDL,?)
1217                        del slocd[import_ns]
1218                        continue
1219                    except SchemaError, ex:
1220                        warnings.warn(\
1221                            '<import namespace="%s">, %s'\
1222                            %(import_ns, 'failed to load schema instance, resort to lazy eval when necessary')
1223                        )
1224                        del slocd[import_ns]
1225                        class _LazyEvalImport(str):
1226                            '''Lazy evaluation of import, replace entry in self.imports.'''
1227                            #attributes = dict(namespace=import_ns)
1228                            def getSchema(namespace):
1229                                schema = slocd.get(namespace)
1230                                if schema is None:
1231                                    parent = self._parent()
1232                                    wstypes = parent
1233                                    if isinstance(parent, WSDLToolsAdapter):
1234                                        wstypes = parent.getImportSchemas()
1235                                    schema = wstypes.get(namespace)
1236                                if isinstance(schema, XMLSchema):
1237                                    self.imports[namespace] = schema
1238                                    return schema
1239
1240                                return None
1241
1242                        self.imports[import_ns] = _LazyEvalImport(import_ns)
1243                        continue
1244                else:
1245                    tp._schema = schema
1246
1247                if self.getImportSchemas().has_key(import_ns):
1248                    warnings.warn(\
1249                        'Detected multiple imports of the namespace "%s" '\
1250                        %import_ns)
1251
1252                self.addImportSchema(schema)
1253                # spec says can have multiple imports of same namespace
1254                # but purpose of import is just dependency declaration.
1255                self.imports[import_ns] = tp
1256
1257            elif component == 'redefine':
1258                warnings.warn('redefine is ignored')
1259            elif component == 'annotation':
1260                warnings.warn('annotation is ignored')
1261            elif component == 'attribute':
1262                tp = AttributeDeclaration(self)
1263                tp.fromDom(childNode)
1264                self.attr_decl[tp.getAttribute('name')] = tp
1265            elif component == 'attributeGroup':
1266                tp = AttributeGroupDefinition(self)
1267                tp.fromDom(childNode)
1268                self.attr_groups[tp.getAttribute('name')] = tp
1269            elif component == 'element':
1270                tp = ElementDeclaration(self)
1271                tp.fromDom(childNode)
1272                self.elements[tp.getAttribute('name')] = tp
1273            elif component == 'group':
1274                tp = ModelGroupDefinition(self)
1275                tp.fromDom(childNode)
1276                self.model_groups[tp.getAttribute('name')] = tp
1277            elif component == 'notation':
1278                tp = Notation(self)
1279                tp.fromDom(childNode)
1280                self.notations[tp.getAttribute('name')] = tp
1281            elif component == 'complexType':
1282                tp = ComplexType(self)
1283                tp.fromDom(childNode)
1284                self.types[tp.getAttribute('name')] = tp
1285            elif component == 'simpleType':
1286                tp = SimpleType(self)
1287                tp.fromDom(childNode)
1288                self.types[tp.getAttribute('name')] = tp
1289            else:
1290                break
1291
1292    class Import(XMLSchemaComponent):
1293        """<import>
1294           parent:
1295               schema
1296           attributes:
1297               id -- ID
1298               namespace -- anyURI
1299               schemaLocation -- anyURI
1300           contents:
1301               annotation?
1302        """
1303        attributes = {'id':None,
1304                      'namespace':None,
1305                      'schemaLocation':None}
1306        contents = {'xsd':['annotation']}
1307        tag = 'import'
1308
1309        def __init__(self, parent):
1310            XMLSchemaComponent.__init__(self, parent)
1311            self.annotation = None
1312            self._schema = None
1313
1314        def fromDom(self, node):
1315            self.setAttributes(node)
1316            contents = self.getContents(node)
1317
1318            if self.attributes['namespace'] == self.getTargetNamespace():
1319                raise SchemaError, 'namespace of schema and import match'
1320
1321            for i in contents:
1322                component = SplitQName(i.getTagName())[1]
1323                if component == 'annotation' and not self.annotation:
1324                    self.annotation = Annotation(self)
1325                    self.annotation.fromDom(i)
1326                else:
1327                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1328
1329        def getSchema(self):
1330            """if schema is not defined, first look for a Schema class instance
1331               in parent Schema.  Else if not defined resolve schemaLocation
1332               and create a new Schema class instance, and keep a hard reference.
1333            """
1334            if not self._schema:
1335                ns = self.attributes['namespace']
1336                schema = self._parent().getImportSchemas().get(ns)
1337                if not schema and self._parent()._parent:
1338                    schema = self._parent()._parent().getImportSchemas().get(ns)
1339
1340                if not schema:
1341                    url = self.attributes.get('schemaLocation')
1342                    if not url:
1343                        raise SchemaError, 'namespace(%s) is unknown' %ns
1344                    base_url = self._parent().getBaseUrl()
1345                    reader = SchemaReader(base_url=base_url)
1346                    reader._imports = self._parent().getImportSchemas()
1347                    reader._includes = self._parent().getIncludeSchemas()
1348                    self._schema = reader.loadFromURL(url)
1349            return self._schema or schema
1350
1351        def loadSchema(self, schema):
1352            """
1353            """
1354            base_url = self._parent().getBaseUrl()
1355            reader = SchemaReader(base_url=base_url)
1356            reader._imports = self._parent().getImportSchemas()
1357            reader._includes = self._parent().getIncludeSchemas()
1358            self._schema = schema
1359
1360            if not self.attributes.has_key('schemaLocation'):
1361                raise NoSchemaLocationWarning('no schemaLocation attribute in import')
1362
1363            reader.loadFromURL(self.attributes.get('schemaLocation'), schema)
1364
1365
1366    class Include(XMLSchemaComponent):
1367        """<include schemaLocation>
1368           parent:
1369               schema
1370           attributes:
1371               id -- ID
1372               schemaLocation -- anyURI, required
1373           contents:
1374               annotation?
1375        """
1376        required = ['schemaLocation']
1377        attributes = {'id':None,
1378            'schemaLocation':None}
1379        contents = {'xsd':['annotation']}
1380        tag = 'include'
1381
1382        def __init__(self, parent):
1383            XMLSchemaComponent.__init__(self, parent)
1384            self.annotation = None
1385            self._schema = None
1386
1387        def fromDom(self, node):
1388            self.setAttributes(node)
1389            contents = self.getContents(node)
1390
1391            for i in contents:
1392                component = SplitQName(i.getTagName())[1]
1393                if component == 'annotation' and not self.annotation:
1394                    self.annotation = Annotation(self)
1395                    self.annotation.fromDom(i)
1396                else:
1397                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1398
1399        def getSchema(self):
1400            """if schema is not defined, first look for a Schema class instance
1401               in parent Schema.  Else if not defined resolve schemaLocation
1402               and create a new Schema class instance.
1403            """
1404            if not self._schema:
1405                schema = self._parent()
1406                self._schema = schema.getIncludeSchemas().get(\
1407                                   self.attributes['schemaLocation']
1408                                   )
1409                if not self._schema:
1410                    url = self.attributes['schemaLocation']
1411                    reader = SchemaReader(base_url=schema.getBaseUrl())
1412                    reader._imports = schema.getImportSchemas()
1413                    reader._includes = schema.getIncludeSchemas()
1414
1415                    # create schema before loading so chameleon include
1416                    # will evalute targetNamespace correctly.
1417                    self._schema = XMLSchema(schema)
1418                    reader.loadFromURL(url, self._schema)
1419
1420            return self._schema
1421
1422
1423class AttributeDeclaration(XMLSchemaComponent,\
1424                           AttributeMarker,\
1425                           DeclarationMarker):
1426    """<attribute name>
1427       parent:
1428           schema
1429       attributes:
1430           id -- ID
1431           name -- NCName, required
1432           type -- QName
1433           default -- string
1434           fixed -- string
1435       contents:
1436           annotation?, simpleType?
1437    """
1438    required = ['name']
1439    attributes = {'id':None,
1440        'name':None,
1441        'type':None,
1442        'default':None,
1443        'fixed':None}
1444    contents = {'xsd':['annotation','simpleType']}
1445    tag = 'attribute'
1446
1447    def __init__(self, parent):
1448        XMLSchemaComponent.__init__(self, parent)
1449        self.annotation = None
1450        self.content = None
1451
1452    def fromDom(self, node):
1453        """ No list or union support
1454        """
1455        self.setAttributes(node)
1456        contents = self.getContents(node)
1457
1458        for i in contents:
1459            component = SplitQName(i.getTagName())[1]
1460            if component == 'annotation' and not self.annotation:
1461                self.annotation = Annotation(self)
1462                self.annotation.fromDom(i)
1463            elif component == 'simpleType':
1464                self.content = AnonymousSimpleType(self)
1465                self.content.fromDom(i)
1466            else:
1467                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1468
1469
1470class LocalAttributeDeclaration(AttributeDeclaration,\
1471                                AttributeMarker,\
1472                                LocalMarker,\
1473                                DeclarationMarker):
1474    """<attribute name>
1475       parent:
1476           complexType, restriction, extension, attributeGroup
1477       attributes:
1478           id -- ID
1479           name -- NCName,  required
1480           type -- QName
1481           form -- ('qualified' | 'unqualified'), schema.attributeFormDefault
1482           use -- ('optional' | 'prohibited' | 'required'), optional
1483           default -- string
1484           fixed -- string
1485       contents:
1486           annotation?, simpleType?
1487    """
1488    required = ['name']
1489    attributes = {'id':None,
1490        'name':None,
1491        'type':None,
1492        'form':lambda self: GetSchema(self).getAttributeFormDefault(),
1493        'use':'optional',
1494        'default':None,
1495        'fixed':None}
1496    contents = {'xsd':['annotation','simpleType']}
1497
1498    def __init__(self, parent):
1499        AttributeDeclaration.__init__(self, parent)
1500        self.annotation = None
1501        self.content = None
1502
1503    def fromDom(self, node):
1504        self.setAttributes(node)
1505        contents = self.getContents(node)
1506
1507        for i in contents:
1508            component = SplitQName(i.getTagName())[1]
1509            if component == 'annotation' and not self.annotation:
1510                self.annotation = Annotation(self)
1511                self.annotation.fromDom(i)
1512            elif component == 'simpleType':
1513                self.content = AnonymousSimpleType(self)
1514                self.content.fromDom(i)
1515            else:
1516                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1517
1518
1519class AttributeWildCard(XMLSchemaComponent,\
1520                        AttributeMarker,\
1521                        DeclarationMarker,\
1522                        WildCardMarker):
1523    """<anyAttribute>
1524       parents:
1525           complexType, restriction, extension, attributeGroup
1526       attributes:
1527           id -- ID
1528           namespace -- '##any' | '##other' |
1529                        (anyURI* | '##targetNamespace' | '##local'), ##any
1530           processContents -- 'lax' | 'skip' | 'strict', strict
1531       contents:
1532           annotation?
1533    """
1534    attributes = {'id':None,
1535        'namespace':'##any',
1536        'processContents':'strict'}
1537    contents = {'xsd':['annotation']}
1538    tag = 'anyAttribute'
1539
1540    def __init__(self, parent):
1541        XMLSchemaComponent.__init__(self, parent)
1542        self.annotation = None
1543
1544    def fromDom(self, node):
1545        self.setAttributes(node)
1546        contents = self.getContents(node)
1547
1548        for i in contents:
1549            component = SplitQName(i.getTagName())[1]
1550            if component == 'annotation' and not self.annotation:
1551                self.annotation = Annotation(self)
1552                self.annotation.fromDom(i)
1553            else:
1554                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1555
1556
1557class AttributeReference(XMLSchemaComponent,\
1558                         AttributeMarker,\
1559                         ReferenceMarker):
1560    """<attribute ref>
1561       parents:
1562           complexType, restriction, extension, attributeGroup
1563       attributes:
1564           id -- ID
1565           ref -- QName, required
1566           use -- ('optional' | 'prohibited' | 'required'), optional
1567           default -- string
1568           fixed -- string
1569       contents:
1570           annotation?
1571    """
1572    required = ['ref']
1573    attributes = {'id':None,
1574        'ref':None,
1575        'use':'optional',
1576        'default':None,
1577        'fixed':None}
1578    contents = {'xsd':['annotation']}
1579    tag = 'attribute'
1580
1581    def __init__(self, parent):
1582        XMLSchemaComponent.__init__(self, parent)
1583        self.annotation = None
1584
1585    def getAttributeDeclaration(self, attribute='ref'):
1586        return XMLSchemaComponent.getAttributeDeclaration(self, attribute)
1587
1588    def fromDom(self, node):
1589        self.setAttributes(node)
1590        contents = self.getContents(node)
1591
1592        for i in contents:
1593            component = SplitQName(i.getTagName())[1]
1594            if component == 'annotation' and not self.annotation:
1595                self.annotation = Annotation(self)
1596                self.annotation.fromDom(i)
1597            else:
1598                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1599
1600
1601class AttributeGroupDefinition(XMLSchemaComponent,\
1602                               AttributeGroupMarker,\
1603                               DefinitionMarker):
1604    """<attributeGroup name>
1605       parents:
1606           schema, redefine
1607       attributes:
1608           id -- ID
1609           name -- NCName,  required
1610       contents:
1611           annotation?, (attribute | attributeGroup)*, anyAttribute?
1612    """
1613    required = ['name']
1614    attributes = {'id':None,
1615        'name':None}
1616    contents = {'xsd':['annotation', 'attribute', 'attributeGroup', 'anyAttribute']}
1617    tag = 'attributeGroup'
1618
1619    def __init__(self, parent):
1620        XMLSchemaComponent.__init__(self, parent)
1621        self.annotation = None
1622        self.attr_content = None
1623
1624    def getAttributeContent(self):
1625        return self.attr_content
1626
1627    def fromDom(self, node):
1628        self.setAttributes(node)
1629        contents = self.getContents(node)
1630        content = []
1631
1632        for indx in range(len(contents)):
1633            component = SplitQName(contents[indx].getTagName())[1]
1634            if (component == 'annotation') and (not indx):
1635                self.annotation = Annotation(self)
1636                self.annotation.fromDom(contents[indx])
1637            elif component == 'attribute':
1638                if contents[indx].hasattr('name'):
1639                    content.append(LocalAttributeDeclaration(self))
1640                elif contents[indx].hasattr('ref'):
1641                    content.append(AttributeReference(self))
1642                else:
1643                    raise SchemaError, 'Unknown attribute type'
1644                content[-1].fromDom(contents[indx])
1645            elif component == 'attributeGroup':
1646                content.append(AttributeGroupReference(self))
1647                content[-1].fromDom(contents[indx])
1648            elif component == 'anyAttribute':
1649                if len(contents) != indx+1:
1650                    raise SchemaError, 'anyAttribute is out of order in %s' %self.getItemTrace()
1651                content.append(AttributeWildCard(self))
1652                content[-1].fromDom(contents[indx])
1653            else:
1654                raise SchemaError, 'Unknown component (%s)' %(contents[indx].getTagName())
1655
1656        self.attr_content = tuple(content)
1657
1658class AttributeGroupReference(XMLSchemaComponent,\
1659                              AttributeGroupMarker,\
1660                              ReferenceMarker):
1661    """<attributeGroup ref>
1662       parents:
1663           complexType, restriction, extension, attributeGroup
1664       attributes:
1665           id -- ID
1666           ref -- QName, required
1667       contents:
1668           annotation?
1669    """
1670    required = ['ref']
1671    attributes = {'id':None,
1672        'ref':None}
1673    contents = {'xsd':['annotation']}
1674    tag = 'attributeGroup'
1675
1676    def __init__(self, parent):
1677        XMLSchemaComponent.__init__(self, parent)
1678        self.annotation = None
1679
1680    def getAttributeGroup(self, attribute='ref'):
1681        """attribute -- attribute with a QName value (eg. type).
1682           collection -- check types collection in parent Schema instance
1683        """
1684        return XMLSchemaComponent.getAttributeGroup(self, attribute)
1685
1686    def fromDom(self, node):
1687        self.setAttributes(node)
1688        contents = self.getContents(node)
1689
1690        for i in contents:
1691            component = SplitQName(i.getTagName())[1]
1692            if component == 'annotation' and not self.annotation:
1693                self.annotation = Annotation(self)
1694                self.annotation.fromDom(i)
1695            else:
1696                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1697
1698
1699
1700######################################################
1701# Elements
1702#####################################################
1703class IdentityConstrants(XMLSchemaComponent):
1704    """Allow one to uniquely identify nodes in a document and ensure the
1705       integrity of references between them.
1706
1707       attributes -- dictionary of attributes
1708       selector -- XPath to selected nodes
1709       fields -- list of XPath to key field
1710    """
1711    def __init__(self, parent):
1712        XMLSchemaComponent.__init__(self, parent)
1713        self.selector = None
1714        self.fields = None
1715        self.annotation = None
1716
1717    def fromDom(self, node):
1718        self.setAttributes(node)
1719        contents = self.getContents(node)
1720        fields = []
1721
1722        for i in contents:
1723            component = SplitQName(i.getTagName())[1]
1724            if component in self.__class__.contents['xsd']:
1725                if component == 'annotation' and not self.annotation:
1726                    self.annotation = Annotation(self)
1727                    self.annotation.fromDom(i)
1728                elif component == 'selector':
1729                    self.selector = self.Selector(self)
1730                    self.selector.fromDom(i)
1731                    continue
1732                elif component == 'field':
1733                    fields.append(self.Field(self))
1734                    fields[-1].fromDom(i)
1735                    continue
1736                else:
1737                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1738            else:
1739                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1740            self.fields = tuple(fields)
1741
1742
1743    class Constraint(XMLSchemaComponent):
1744        def __init__(self, parent):
1745            XMLSchemaComponent.__init__(self, parent)
1746            self.annotation = None
1747
1748        def fromDom(self, node):
1749            self.setAttributes(node)
1750            contents = self.getContents(node)
1751
1752            for i in contents:
1753                component = SplitQName(i.getTagName())[1]
1754                if component in self.__class__.contents['xsd']:
1755                    if component == 'annotation' and not self.annotation:
1756                        self.annotation = Annotation(self)
1757                        self.annotation.fromDom(i)
1758                    else:
1759                        raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1760                else:
1761                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1762
1763    class Selector(Constraint):
1764        """<selector xpath>
1765           parent:
1766               unique, key, keyref
1767           attributes:
1768               id -- ID
1769               xpath -- XPath subset,  required
1770           contents:
1771               annotation?
1772        """
1773        required = ['xpath']
1774        attributes = {'id':None,
1775            'xpath':None}
1776        contents = {'xsd':['annotation']}
1777        tag = 'selector'
1778
1779    class Field(Constraint):
1780        """<field xpath>
1781           parent:
1782               unique, key, keyref
1783           attributes:
1784               id -- ID
1785               xpath -- XPath subset,  required
1786           contents:
1787               annotation?
1788        """
1789        required = ['xpath']
1790        attributes = {'id':None,
1791            'xpath':None}
1792        contents = {'xsd':['annotation']}
1793        tag = 'field'
1794
1795
1796class Unique(IdentityConstrants):
1797    """<unique name> Enforce fields are unique w/i a specified scope.
1798
1799       parent:
1800           element
1801       attributes:
1802           id -- ID
1803           name -- NCName,  required
1804       contents:
1805           annotation?, selector, field+
1806    """
1807    required = ['name']
1808    attributes = {'id':None,
1809        'name':None}
1810    contents = {'xsd':['annotation', 'selector', 'field']}
1811    tag = 'unique'
1812
1813
1814class Key(IdentityConstrants):
1815    """<key name> Enforce fields are unique w/i a specified scope, and all
1816           field values are present w/i document.  Fields cannot
1817           be nillable.
1818
1819       parent:
1820           element
1821       attributes:
1822           id -- ID
1823           name -- NCName,  required
1824       contents:
1825           annotation?, selector, field+
1826    """
1827    required = ['name']
1828    attributes = {'id':None,
1829        'name':None}
1830    contents = {'xsd':['annotation', 'selector', 'field']}
1831    tag = 'key'
1832
1833
1834class KeyRef(IdentityConstrants):
1835    """<keyref name refer> Ensure a match between two sets of values in an
1836           instance.
1837       parent:
1838           element
1839       attributes:
1840           id -- ID
1841           name -- NCName,  required
1842           refer -- QName,  required
1843       contents:
1844           annotation?, selector, field+
1845    """
1846    required = ['name', 'refer']
1847    attributes = {'id':None,
1848        'name':None,
1849        'refer':None}
1850    contents = {'xsd':['annotation', 'selector', 'field']}
1851    tag = 'keyref'
1852
1853
1854class ElementDeclaration(XMLSchemaComponent,\
1855                         ElementMarker,\
1856                         DeclarationMarker):
1857    """<element name>
1858       parents:
1859           schema
1860       attributes:
1861           id -- ID
1862           name -- NCName,  required
1863           type -- QName
1864           default -- string
1865           fixed -- string
1866           nillable -- boolean,  false
1867           abstract -- boolean,  false
1868           substitutionGroup -- QName
1869           block -- ('#all' | ('substition' | 'extension' | 'restriction')*),
1870               schema.blockDefault
1871           final -- ('#all' | ('extension' | 'restriction')*),
1872               schema.finalDefault
1873       contents:
1874           annotation?, (simpleType,complexType)?, (key | keyref | unique)*
1875
1876    """
1877    required = ['name']
1878    attributes = {'id':None,
1879        'name':None,
1880        'type':None,
1881        'default':None,
1882        'fixed':None,
1883        'nillable':0,
1884        'abstract':0,
1885        'substitutionGroup':None,
1886        'block':lambda self: self._parent().getBlockDefault(),
1887        'final':lambda self: self._parent().getFinalDefault()}
1888    contents = {'xsd':['annotation', 'simpleType', 'complexType', 'key',\
1889        'keyref', 'unique']}
1890    tag = 'element'
1891
1892    def __init__(self, parent):
1893        XMLSchemaComponent.__init__(self, parent)
1894        self.annotation = None
1895        self.content = None
1896        self.constraints = ()
1897
1898    def isQualified(self):
1899        """Global elements are always qualified.
1900        """
1901        return True
1902
1903    def getAttribute(self, attribute):
1904        """return attribute.
1905        If attribute is type and it's None, and no simple or complex content,
1906        return the default type "xsd:anyType"
1907        """
1908        value = XMLSchemaComponent.getAttribute(self, attribute)
1909        if attribute != 'type' or value is not None:
1910            return value
1911
1912        if self.content is not None:
1913            return None
1914
1915        parent = self
1916        while 1:
1917            nsdict = parent.attributes[XMLSchemaComponent.xmlns]
1918            for k,v in nsdict.items():
1919                if v not in SCHEMA.XSD_LIST: continue
1920                return TypeDescriptionComponent((v, 'anyType'))
1921
1922            if isinstance(parent, WSDLToolsAdapter)\
1923                or not hasattr(parent, '_parent'):
1924                break
1925
1926            parent = parent._parent()
1927
1928        raise SchemaError, 'failed to locate the XSD namespace'
1929
1930    def getElementDeclaration(self, attribute):
1931        raise Warning, 'invalid operation for <%s>' %self.tag
1932
1933    def getTypeDefinition(self, attribute=None):
1934        """If attribute is None, "type" is assumed, return the corresponding
1935        representation of the global type definition (TypeDefinition),
1936        or the local definition if don't find "type".  To maintain backwards
1937        compat, if attribute is provided call base class method.
1938        """
1939        if attribute:
1940            return XMLSchemaComponent.getTypeDefinition(self, attribute)
1941        gt = XMLSchemaComponent.getTypeDefinition(self, 'type')
1942        if gt:
1943            return gt
1944        return self.content
1945
1946    def getConstraints(self):
1947        return self._constraints
1948    def setConstraints(self, constraints):
1949        self._constraints = tuple(constraints)
1950    constraints = property(getConstraints, setConstraints, None, "tuple of key, keyref, unique constraints")
1951
1952    def fromDom(self, node):
1953        self.setAttributes(node)
1954        contents = self.getContents(node)
1955        constraints = []
1956        for i in contents:
1957            component = SplitQName(i.getTagName())[1]
1958            if component in self.__class__.contents['xsd']:
1959                if component == 'annotation' and not self.annotation:
1960                    self.annotation = Annotation(self)
1961                    self.annotation.fromDom(i)
1962                elif component == 'simpleType' and not self.content:
1963                    self.content = AnonymousSimpleType(self)
1964                    self.content.fromDom(i)
1965                elif component == 'complexType' and not self.content:
1966                    self.content = LocalComplexType(self)
1967                    self.content.fromDom(i)
1968                elif component == 'key':
1969                    constraints.append(Key(self))
1970                    constraints[-1].fromDom(i)
1971                elif component == 'keyref':
1972                    constraints.append(KeyRef(self))
1973                    constraints[-1].fromDom(i)
1974                elif component == 'unique':
1975                    constraints.append(Unique(self))
1976                    constraints[-1].fromDom(i)
1977                else:
1978                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1979            else:
1980                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
1981
1982        self.constraints = constraints
1983
1984
1985class LocalElementDeclaration(ElementDeclaration,\
1986                              LocalMarker):
1987    """<element>
1988       parents:
1989           all, choice, sequence
1990       attributes:
1991           id -- ID
1992           name -- NCName,  required
1993           form -- ('qualified' | 'unqualified'), schema.elementFormDefault
1994           type -- QName
1995           minOccurs -- Whole Number, 1
1996           maxOccurs -- (Whole Number | 'unbounded'), 1
1997           default -- string
1998           fixed -- string
1999           nillable -- boolean,  false
2000           block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault
2001       contents:
2002           annotation?, (simpleType,complexType)?, (key | keyref | unique)*
2003    """
2004    required = ['name']
2005    attributes = {'id':None,
2006        'name':None,
2007        'form':lambda self: GetSchema(self).getElementFormDefault(),
2008        'type':None,
2009        'minOccurs':'1',
2010        'maxOccurs':'1',
2011        'default':None,
2012        'fixed':None,
2013        'nillable':0,
2014        'abstract':0,
2015        'block':lambda self: GetSchema(self).getBlockDefault()}
2016    contents = {'xsd':['annotation', 'simpleType', 'complexType', 'key',\
2017        'keyref', 'unique']}
2018
2019    def isQualified(self):
2020        """
2021Local elements can be qualified or unqualifed according
2022        to the attribute form, or the elementFormDefault.  By default
2023        local elements are unqualified.
2024        """
2025        form = self.getAttribute('form')
2026        if form == 'qualified':
2027            return True
2028        if form == 'unqualified':
2029            return False
2030        raise SchemaError, 'Bad form (%s) for element: %s' %(form, self.getItemTrace())
2031
2032
2033class ElementReference(XMLSchemaComponent,\
2034                       ElementMarker,\
2035                       ReferenceMarker):
2036    """<element ref>
2037       parents:
2038           all, choice, sequence
2039       attributes:
2040           id -- ID
2041           ref -- QName, required
2042           minOccurs -- Whole Number, 1
2043           maxOccurs -- (Whole Number | 'unbounded'), 1
2044       contents:
2045           annotation?
2046    """
2047    required = ['ref']
2048    attributes = {'id':None,
2049        'ref':None,
2050        'minOccurs':'1',
2051        'maxOccurs':'1'}
2052    contents = {'xsd':['annotation']}
2053    tag = 'element'
2054
2055    def __init__(self, parent):
2056        XMLSchemaComponent.__init__(self, parent)
2057        self.annotation = None
2058
2059    def getElementDeclaration(self, attribute=None):
2060        """If attribute is None, "ref" is assumed, return the corresponding
2061        representation of the global element declaration (ElementDeclaration),
2062        To maintain backwards compat, if attribute is provided call base class method.
2063        """
2064        if attribute:
2065            return XMLSchemaComponent.getElementDeclaration(self, attribute)
2066        return XMLSchemaComponent.getElementDeclaration(self, 'ref')
2067
2068    def fromDom(self, node):
2069        self.annotation = None
2070        self.setAttributes(node)
2071        for i in self.getContents(node):
2072            component = SplitQName(i.getTagName())[1]
2073            if component in self.__class__.contents['xsd']:
2074                if component == 'annotation' and not self.annotation:
2075                    self.annotation = Annotation(self)
2076                    self.annotation.fromDom(i)
2077                else:
2078                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2079
2080
2081class ElementWildCard(LocalElementDeclaration, WildCardMarker):
2082    """<any>
2083       parents:
2084           choice, sequence
2085       attributes:
2086           id -- ID
2087           minOccurs -- Whole Number, 1
2088           maxOccurs -- (Whole Number | 'unbounded'), 1
2089           namespace -- '##any' | '##other' |
2090                        (anyURI* | '##targetNamespace' | '##local'), ##any
2091           processContents -- 'lax' | 'skip' | 'strict', strict
2092       contents:
2093           annotation?
2094    """
2095    required = []
2096    attributes = {'id':None,
2097        'minOccurs':'1',
2098        'maxOccurs':'1',
2099        'namespace':'##any',
2100        'processContents':'strict'}
2101    contents = {'xsd':['annotation']}
2102    tag = 'any'
2103
2104    def __init__(self, parent):
2105        XMLSchemaComponent.__init__(self, parent)
2106        self.annotation = None
2107
2108    def isQualified(self):
2109        """
2110        Global elements are always qualified, but if processContents
2111        are not strict could have dynamically generated local elements.
2112        """
2113        return GetSchema(self).isElementFormDefaultQualified()
2114
2115    def getAttribute(self, attribute):
2116        """return attribute.
2117        """
2118        return XMLSchemaComponent.getAttribute(self, attribute)
2119
2120    def getTypeDefinition(self, attribute):
2121        raise Warning, 'invalid operation for <%s>' % self.tag
2122
2123    def fromDom(self, node):
2124        self.annotation = None
2125        self.setAttributes(node)
2126        for i in self.getContents(node):
2127            component = SplitQName(i.getTagName())[1]
2128            if component in self.__class__.contents['xsd']:
2129                if component == 'annotation' and not self.annotation:
2130                    self.annotation = Annotation(self)
2131                    self.annotation.fromDom(i)
2132                else:
2133                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2134
2135
2136######################################################
2137# Model Groups
2138#####################################################
2139class Sequence(XMLSchemaComponent,\
2140               SequenceMarker):
2141    """<sequence>
2142       parents:
2143           complexType, extension, restriction, group, choice, sequence
2144       attributes:
2145           id -- ID
2146           minOccurs -- Whole Number, 1
2147           maxOccurs -- (Whole Number | 'unbounded'), 1
2148
2149       contents:
2150           annotation?, (element | group | choice | sequence | any)*
2151    """
2152    attributes = {'id':None,
2153        'minOccurs':'1',
2154        'maxOccurs':'1'}
2155    contents = {'xsd':['annotation', 'element', 'group', 'choice', 'sequence',\
2156         'any']}
2157    tag = 'sequence'
2158
2159    def __init__(self, parent):
2160        XMLSchemaComponent.__init__(self, parent)
2161        self.annotation = None
2162        self.content = None
2163
2164    def fromDom(self, node):
2165        self.setAttributes(node)
2166        contents = self.getContents(node)
2167        content = []
2168
2169        for i in contents:
2170            component = SplitQName(i.getTagName())[1]
2171            if component in self.__class__.contents['xsd']:
2172                if component == 'annotation' and not self.annotation:
2173                    self.annotation = Annotation(self)
2174                    self.annotation.fromDom(i)
2175                    continue
2176                elif component == 'element':
2177                    if i.hasattr('ref'):
2178                        content.append(ElementReference(self))
2179                    else:
2180                        content.append(LocalElementDeclaration(self))
2181                elif component == 'group':
2182                    content.append(ModelGroupReference(self))
2183                elif component == 'choice':
2184                    content.append(Choice(self))
2185                elif component == 'sequence':
2186                    content.append(Sequence(self))
2187                elif component == 'any':
2188                    content.append(ElementWildCard(self))
2189                else:
2190                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2191                content[-1].fromDom(i)
2192            else:
2193                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2194        self.content = tuple(content)
2195
2196
2197class All(XMLSchemaComponent,\
2198          AllMarker):
2199    """<all>
2200       parents:
2201           complexType, extension, restriction, group
2202       attributes:
2203           id -- ID
2204           minOccurs -- '0' | '1', 1
2205           maxOccurs -- '1', 1
2206
2207       contents:
2208           annotation?, element*
2209    """
2210    attributes = {'id':None,
2211        'minOccurs':'1',
2212        'maxOccurs':'1'}
2213    contents = {'xsd':['annotation', 'element']}
2214    tag = 'all'
2215
2216    def __init__(self, parent):
2217        XMLSchemaComponent.__init__(self, parent)
2218        self.annotation = None
2219        self.content = None
2220
2221    def fromDom(self, node):
2222        self.setAttributes(node)
2223        contents = self.getContents(node)
2224        content = []
2225
2226        for i in contents:
2227            component = SplitQName(i.getTagName())[1]
2228            if component in self.__class__.contents['xsd']:
2229                if component == 'annotation' and not self.annotation:
2230                    self.annotation = Annotation(self)
2231                    self.annotation.fromDom(i)
2232                    continue
2233                elif component == 'element':
2234                    if i.hasattr('ref'):
2235                        content.append(ElementReference(self))
2236                    else:
2237                        content.append(LocalElementDeclaration(self))
2238                else:
2239                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2240                content[-1].fromDom(i)
2241            else:
2242                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2243        self.content = tuple(content)
2244
2245
2246class Choice(XMLSchemaComponent,\
2247             ChoiceMarker):
2248    """<choice>
2249       parents:
2250           complexType, extension, restriction, group, choice, sequence
2251       attributes:
2252           id -- ID
2253           minOccurs -- Whole Number, 1
2254           maxOccurs -- (Whole Number | 'unbounded'), 1
2255
2256       contents:
2257           annotation?, (element | group | choice | sequence | any)*
2258    """
2259    attributes = {'id':None,
2260        'minOccurs':'1',
2261        'maxOccurs':'1'}
2262    contents = {'xsd':['annotation', 'element', 'group', 'choice', 'sequence',\
2263         'any']}
2264    tag = 'choice'
2265
2266    def __init__(self, parent):
2267        XMLSchemaComponent.__init__(self, parent)
2268        self.annotation = None
2269        self.content = None
2270
2271    def fromDom(self, node):
2272        self.setAttributes(node)
2273        contents = self.getContents(node)
2274        content = []
2275
2276        for i in contents:
2277            component = SplitQName(i.getTagName())[1]
2278            if component in self.__class__.contents['xsd']:
2279                if component == 'annotation' and not self.annotation:
2280                    self.annotation = Annotation(self)
2281                    self.annotation.fromDom(i)
2282                    continue
2283                elif component == 'element':
2284                    if i.hasattr('ref'):
2285                        content.append(ElementReference(self))
2286                    else:
2287                        content.append(LocalElementDeclaration(self))
2288                elif component == 'group':
2289                    content.append(ModelGroupReference(self))
2290                elif component == 'choice':
2291                    content.append(Choice(self))
2292                elif component == 'sequence':
2293                    content.append(Sequence(self))
2294                elif component == 'any':
2295                    content.append(ElementWildCard(self))
2296                else:
2297                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2298                content[-1].fromDom(i)
2299            else:
2300                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2301        self.content = tuple(content)
2302
2303
2304class ModelGroupDefinition(XMLSchemaComponent,\
2305                           ModelGroupMarker,\
2306                           DefinitionMarker):
2307    """<group name>
2308       parents:
2309           redefine, schema
2310       attributes:
2311           id -- ID
2312           name -- NCName,  required
2313
2314       contents:
2315           annotation?, (all | choice | sequence)?
2316    """
2317    required = ['name']
2318    attributes = {'id':None,
2319        'name':None}
2320    contents = {'xsd':['annotation', 'all', 'choice', 'sequence']}
2321    tag = 'group'
2322
2323    def __init__(self, parent):
2324        XMLSchemaComponent.__init__(self, parent)
2325        self.annotation = None
2326        self.content = None
2327
2328    def fromDom(self, node):
2329        self.setAttributes(node)
2330        contents = self.getContents(node)
2331
2332        for i in contents:
2333            component = SplitQName(i.getTagName())[1]
2334            if component in self.__class__.contents['xsd']:
2335                if component == 'annotation' and not self.annotation:
2336                    self.annotation = Annotation(self)
2337                    self.annotation.fromDom(i)
2338                    continue
2339                elif component == 'all' and not self.content:
2340                    self.content = All(self)
2341                elif component == 'choice' and not self.content:
2342                    self.content = Choice(self)
2343                elif component == 'sequence' and not self.content:
2344                    self.content = Sequence(self)
2345                else:
2346                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2347                self.content.fromDom(i)
2348            else:
2349                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2350
2351
2352class ModelGroupReference(XMLSchemaComponent,\
2353                          ModelGroupMarker,\
2354                          ReferenceMarker):
2355    """<group ref>
2356       parents:
2357           choice, complexType, extension, restriction, sequence
2358       attributes:
2359           id -- ID
2360           ref -- NCName,  required
2361           minOccurs -- Whole Number, 1
2362           maxOccurs -- (Whole Number | 'unbounded'), 1
2363
2364       contents:
2365           annotation?
2366    """
2367    required = ['ref']
2368    attributes = {'id':None,
2369        'ref':None,
2370        'minOccurs':'1',
2371        'maxOccurs':'1'}
2372    contents = {'xsd':['annotation']}
2373    tag = 'group'
2374
2375    def __init__(self, parent):
2376        XMLSchemaComponent.__init__(self, parent)
2377        self.annotation = None
2378
2379    def getModelGroupReference(self):
2380        return self.getModelGroup('ref')
2381
2382    def fromDom(self, node):
2383        self.setAttributes(node)
2384        contents = self.getContents(node)
2385
2386        for i in contents:
2387            component = SplitQName(i.getTagName())[1]
2388            if component in self.__class__.contents['xsd']:
2389                if component == 'annotation' and not self.annotation:
2390                    self.annotation = Annotation(self)
2391                    self.annotation.fromDom(i)
2392                else:
2393                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2394            else:
2395                raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2396
2397
2398
2399class ComplexType(XMLSchemaComponent,\
2400                  DefinitionMarker,\
2401                  ComplexMarker):
2402    """<complexType name>
2403       parents:
2404           redefine, schema
2405       attributes:
2406           id -- ID
2407           name -- NCName,  required
2408           mixed -- boolean, false
2409           abstract -- boolean,  false
2410           block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault
2411           final -- ('#all' | ('extension' | 'restriction')*), schema.finalDefault
2412
2413       contents:
2414           annotation?, (simpleContent | complexContent |
2415           ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
2416    """
2417    required = ['name']
2418    attributes = {'id':None,
2419        'name':None,
2420        'mixed':0,
2421        'abstract':0,
2422        'block':lambda self: self._parent().getBlockDefault(),
2423        'final':lambda self: self._parent().getFinalDefault()}
2424    contents = {'xsd':['annotation', 'simpleContent', 'complexContent',\
2425        'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',\
2426        'anyAttribute', 'any']}
2427    tag = 'complexType'
2428
2429    def __init__(self, parent):
2430        XMLSchemaComponent.__init__(self, parent)
2431        self.annotation = None
2432        self.content = None
2433        self.attr_content = None
2434
2435    def isMixed(self):
2436        m = self.getAttribute('mixed')
2437        if m == 0 or m == False:
2438            return False
2439        if isinstance(m, basestring) is True:
2440            if m in ('false', '0'):
2441                return False
2442            if m in ('true', '1'):
2443                return True
2444
2445        raise SchemaError, 'invalid value for attribute mixed(%s): %s'\
2446            %(m, self.getItemTrace())
2447
2448    def getAttributeContent(self):
2449        return self.attr_content
2450
2451    def getElementDeclaration(self, attribute):
2452        raise Warning, 'invalid operation for <%s>' %self.tag
2453
2454    def getTypeDefinition(self, attribute):
2455        raise Warning, 'invalid operation for <%s>' %self.tag
2456
2457    def fromDom(self, node):
2458        self.setAttributes(node)
2459        contents = self.getContents(node)
2460
2461        indx = 0
2462        num = len(contents)
2463        if not num:
2464            return
2465
2466        component = SplitQName(contents[indx].getTagName())[1]
2467        if component == 'annotation':
2468            self.annotation = Annotation(self)
2469            self.annotation.fromDom(contents[indx])
2470            indx += 1
2471            component = SplitQName(contents[indx].getTagName())[1]
2472
2473        self.content = None
2474        if component == 'simpleContent':
2475            self.content = self.__class__.SimpleContent(self)
2476            self.content.fromDom(contents[indx])
2477        elif component == 'complexContent':
2478            self.content = self.__class__.ComplexContent(self)
2479            self.content.fromDom(contents[indx])
2480        else:
2481            if component == 'all':
2482                self.content = All(self)
2483            elif component == 'choice':
2484                self.content = Choice(self)
2485            elif component == 'sequence':
2486                self.content = Sequence(self)
2487            elif component == 'group':
2488                self.content = ModelGroupReference(self)
2489
2490            if self.content:
2491                self.content.fromDom(contents[indx])
2492                indx += 1
2493
2494            self.attr_content = []
2495            while indx < num:
2496                component = SplitQName(contents[indx].getTagName())[1]
2497                if component == 'attribute':
2498                    if contents[indx].hasattr('ref'):
2499                        self.attr_content.append(AttributeReference(self))
2500                    else:
2501                        self.attr_content.append(LocalAttributeDeclaration(self))
2502                elif component == 'attributeGroup':
2503                    self.attr_content.append(AttributeGroupReference(self))
2504                elif component == 'anyAttribute':
2505                    self.attr_content.append(AttributeWildCard(self))
2506                else:
2507                    raise SchemaError, 'Unknown component (%s): %s' \
2508                        %(contents[indx].getTagName(),self.getItemTrace())
2509                self.attr_content[-1].fromDom(contents[indx])
2510                indx += 1
2511
2512    class _DerivedType(XMLSchemaComponent):
2513        def __init__(self, parent):
2514            XMLSchemaComponent.__init__(self, parent)
2515            self.annotation = None
2516            # XXX remove attribute derivation, inconsistent
2517            self.derivation = None
2518            self.content = None
2519
2520        def fromDom(self, node):
2521            self.setAttributes(node)
2522            contents = self.getContents(node)
2523
2524            for i in contents:
2525                component = SplitQName(i.getTagName())[1]
2526                if component in self.__class__.contents['xsd']:
2527                    if component == 'annotation' and not self.annotation:
2528                        self.annotation = Annotation(self)
2529                        self.annotation.fromDom(i)
2530                        continue
2531                    elif component == 'restriction' and not self.derivation:
2532                        self.derivation = self.__class__.Restriction(self)
2533                    elif component == 'extension' and not self.derivation:
2534                        self.derivation = self.__class__.Extension(self)
2535                    else:
2536                        raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2537                else:
2538                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2539                self.derivation.fromDom(i)
2540            self.content = self.derivation
2541
2542    class ComplexContent(_DerivedType,\
2543                         ComplexMarker):
2544        """<complexContent>
2545           parents:
2546               complexType
2547           attributes:
2548               id -- ID
2549               mixed -- boolean, false
2550
2551           contents:
2552               annotation?, (restriction | extension)
2553        """
2554        attributes = {'id':None,
2555            'mixed':0}
2556        contents = {'xsd':['annotation', 'restriction', 'extension']}
2557        tag = 'complexContent'
2558
2559        def isMixed(self):
2560            m = self.getAttribute('mixed')
2561            if m == 0 or m == False:
2562                return False
2563            if isinstance(m, basestring) is True:
2564                if m in ('false', '0'):
2565                    return False
2566                if m in ('true', '1'):
2567                    return True
2568            raise SchemaError, 'invalid value for attribute mixed(%s): %s'\
2569                %(m, self.getItemTrace())
2570
2571        class _DerivationBase(XMLSchemaComponent):
2572            """<extension>,<restriction>
2573               parents:
2574                   complexContent
2575               attributes:
2576                   id -- ID
2577                   base -- QName, required
2578
2579               contents:
2580                   annotation?, (group | all | choice | sequence)?,
2581                       (attribute | attributeGroup)*, anyAttribute?
2582            """
2583            required = ['base']
2584            attributes = {'id':None,
2585                'base':None }
2586            contents = {'xsd':['annotation', 'group', 'all', 'choice',\
2587                'sequence', 'attribute', 'attributeGroup', 'anyAttribute']}
2588
2589            def __init__(self, parent):
2590                XMLSchemaComponent.__init__(self, parent)
2591                self.annotation = None
2592                self.content = None
2593                self.attr_content = None
2594
2595            def getAttributeContent(self):
2596                return self.attr_content
2597
2598            def fromDom(self, node):
2599                self.setAttributes(node)
2600                contents = self.getContents(node)
2601
2602                indx = 0
2603                num = len(contents)
2604                #XXX ugly
2605                if not num:
2606                    return
2607                component = SplitQName(contents[indx].getTagName())[1]
2608                if component == 'annotation':
2609                    self.annotation = Annotation(self)
2610                    self.annotation.fromDom(contents[indx])
2611                    indx += 1
2612                    component = SplitQName(contents[indx].getTagName())[1]
2613
2614                if component == 'all':
2615                    self.content = All(self)
2616                    self.content.fromDom(contents[indx])
2617                    indx += 1
2618                elif component == 'choice':
2619                    self.content = Choice(self)
2620                    self.content.fromDom(contents[indx])
2621                    indx += 1
2622                elif component == 'sequence':
2623                    self.content = Sequence(self)
2624                    self.content.fromDom(contents[indx])
2625                    indx += 1
2626                elif component == 'group':
2627                    self.content = ModelGroupReference(self)
2628                    self.content.fromDom(contents[indx])
2629                    indx += 1
2630                else:
2631                    self.content = None
2632
2633                self.attr_content = []
2634                while indx < num:
2635                    component = SplitQName(contents[indx].getTagName())[1]
2636                    if component == 'attribute':
2637                        if contents[indx].hasattr('ref'):
2638                            self.attr_content.append(AttributeReference(self))
2639                        else:
2640                            self.attr_content.append(LocalAttributeDeclaration(self))
2641                    elif component == 'attributeGroup':
2642                        if contents[indx].hasattr('ref'):
2643                            self.attr_content.append(AttributeGroupReference(self))
2644                        else:
2645                            self.attr_content.append(AttributeGroupDefinition(self))
2646                    elif component == 'anyAttribute':
2647                        self.attr_content.append(AttributeWildCard(self))
2648                    else:
2649                        raise SchemaError, 'Unknown component (%s)' %(contents[indx].getTagName())
2650                    self.attr_content[-1].fromDom(contents[indx])
2651                    indx += 1
2652
2653        class Extension(_DerivationBase,
2654                        ExtensionMarker):
2655            """<extension base>
2656               parents:
2657                   complexContent
2658               attributes:
2659                   id -- ID
2660                   base -- QName, required
2661
2662               contents:
2663                   annotation?, (group | all | choice | sequence)?,
2664                       (attribute | attributeGroup)*, anyAttribute?
2665            """
2666            tag = 'extension'
2667
2668        class Restriction(_DerivationBase,\
2669                          RestrictionMarker):
2670            """<restriction base>
2671               parents:
2672                   complexContent
2673               attributes:
2674                   id -- ID
2675                   base -- QName, required
2676
2677               contents:
2678                   annotation?, (group | all | choice | sequence)?,
2679                       (attribute | attributeGroup)*, anyAttribute?
2680            """
2681            tag = 'restriction'
2682
2683
2684    class SimpleContent(_DerivedType,\
2685                        SimpleMarker):
2686        """<simpleContent>
2687           parents:
2688               complexType
2689           attributes:
2690               id -- ID
2691
2692           contents:
2693               annotation?, (restriction | extension)
2694        """
2695        attributes = {'id':None}
2696        contents = {'xsd':['annotation', 'restriction', 'extension']}
2697        tag = 'simpleContent'
2698
2699        class Extension(XMLSchemaComponent,\
2700                        ExtensionMarker):
2701            """<extension base>
2702               parents:
2703                   simpleContent
2704               attributes:
2705                   id -- ID
2706                   base -- QName, required
2707
2708               contents:
2709                   annotation?, (attribute | attributeGroup)*, anyAttribute?
2710            """
2711            required = ['base']
2712            attributes = {'id':None,
2713                'base':None }
2714            contents = {'xsd':['annotation', 'attribute', 'attributeGroup',
2715                'anyAttribute']}
2716            tag = 'extension'
2717
2718            def __init__(self, parent):
2719                XMLSchemaComponent.__init__(self, parent)
2720                self.annotation = None
2721                self.attr_content = None
2722
2723            def getAttributeContent(self):
2724                return self.attr_content
2725
2726            def fromDom(self, node):
2727                self.setAttributes(node)
2728                contents = self.getContents(node)
2729
2730                indx = 0
2731                num = len(contents)
2732
2733                if num:
2734                    component = SplitQName(contents[indx].getTagName())[1]
2735                    if component == 'annotation':
2736                        self.annotation = Annotation(self)
2737                        self.annotation.fromDom(contents[indx])
2738                        indx += 1
2739                        component = SplitQName(contents[indx].getTagName())[1]
2740
2741                content = []
2742                while indx < num:
2743                    component = SplitQName(contents[indx].getTagName())[1]
2744                    if component == 'attribute':
2745                        if contents[indx].hasattr('ref'):
2746                            content.append(AttributeReference(self))
2747                        else:
2748                            content.append(LocalAttributeDeclaration(self))
2749                    elif component == 'attributeGroup':
2750                        content.append(AttributeGroupReference(self))
2751                    elif component == 'anyAttribute':
2752                        content.append(AttributeWildCard(self))
2753                    else:
2754                        raise SchemaError, 'Unknown component (%s)'\
2755                            %(contents[indx].getTagName())
2756                    content[-1].fromDom(contents[indx])
2757                    indx += 1
2758                self.attr_content = tuple(content)
2759
2760
2761        class Restriction(XMLSchemaComponent,\
2762                          RestrictionMarker):
2763            """<restriction base>
2764               parents:
2765                   simpleContent
2766               attributes:
2767                   id -- ID
2768                   base -- QName, required
2769
2770               contents:
2771                   annotation?, simpleType?, (enumeration | length |
2772                   maxExclusive | maxInclusive | maxLength | minExclusive |
2773                   minInclusive | minLength | pattern | fractionDigits |
2774                   totalDigits | whiteSpace)*, (attribute | attributeGroup)*,
2775                   anyAttribute?
2776            """
2777            required = ['base']
2778            attributes = {'id':None,
2779                'base':None }
2780            contents = {'xsd':['annotation', 'simpleType', 'attribute',\
2781                'attributeGroup', 'anyAttribute'] + RestrictionMarker.facets}
2782            tag = 'restriction'
2783
2784            def __init__(self, parent):
2785                XMLSchemaComponent.__init__(self, parent)
2786                self.annotation = None
2787                self.content = None
2788                self.attr_content = None
2789
2790            def getAttributeContent(self):
2791                return self.attr_content
2792
2793            def fromDom(self, node):
2794                self.content = []
2795                self.setAttributes(node)
2796                contents = self.getContents(node)
2797
2798                indx = 0
2799                num = len(contents)
2800                component = SplitQName(contents[indx].getTagName())[1]
2801                if component == 'annotation':
2802                    self.annotation = Annotation(self)
2803                    self.annotation.fromDom(contents[indx])
2804                    indx += 1
2805                    component = SplitQName(contents[indx].getTagName())[1]
2806
2807                content = []
2808                while indx < num:
2809                    component = SplitQName(contents[indx].getTagName())[1]
2810                    if component == 'attribute':
2811                        if contents[indx].hasattr('ref'):
2812                            content.append(AttributeReference(self))
2813                        else:
2814                            content.append(LocalAttributeDeclaration(self))
2815                    elif component == 'attributeGroup':
2816                        content.append(AttributeGroupReference(self))
2817                    elif component == 'anyAttribute':
2818                        content.append(AttributeWildCard(self))
2819                    elif component == 'simpleType':
2820                        self.content.append(AnonymousSimpleType(self))
2821                        self.content[-1].fromDom(contents[indx])
2822                    else:
2823                        raise SchemaError, 'Unknown component (%s)'\
2824                            %(contents[indx].getTagName())
2825                    content[-1].fromDom(contents[indx])
2826                    indx += 1
2827                self.attr_content = tuple(content)
2828
2829
2830class LocalComplexType(ComplexType,\
2831                       LocalMarker):
2832    """<complexType>
2833       parents:
2834           element
2835       attributes:
2836           id -- ID
2837           mixed -- boolean, false
2838
2839       contents:
2840           annotation?, (simpleContent | complexContent |
2841           ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
2842    """
2843    required = []
2844    attributes = {'id':None,
2845        'mixed':0}
2846    tag = 'complexType'
2847
2848
2849class SimpleType(XMLSchemaComponent,\
2850                 DefinitionMarker,\
2851                 SimpleMarker):
2852    """<simpleType name>
2853       parents:
2854           redefine, schema
2855       attributes:
2856           id -- ID
2857           name -- NCName, required
2858           final -- ('#all' | ('extension' | 'restriction' | 'list' | 'union')*),
2859               schema.finalDefault
2860
2861       contents:
2862           annotation?, (restriction | list | union)
2863    """
2864    required = ['name']
2865    attributes = {'id':None,
2866        'name':None,
2867        'final':lambda self: self._parent().getFinalDefault()}
2868    contents = {'xsd':['annotation', 'restriction', 'list', 'union']}
2869    tag = 'simpleType'
2870
2871    def __init__(self, parent):
2872        XMLSchemaComponent.__init__(self, parent)
2873        self.annotation = None
2874        self.content = None
2875
2876    def getElementDeclaration(self, attribute):
2877        raise Warning, 'invalid operation for <%s>' %self.tag
2878
2879    def getTypeDefinition(self, attribute):
2880        raise Warning, 'invalid operation for <%s>' %self.tag
2881
2882    def fromDom(self, node):
2883        self.setAttributes(node)
2884        contents = self.getContents(node)
2885        for child in contents:
2886            component = SplitQName(child.getTagName())[1]
2887            if component == 'annotation':
2888                self.annotation = Annotation(self)
2889                self.annotation.fromDom(child)
2890                continue
2891            break
2892        else:
2893            return
2894        if component == 'restriction':
2895            self.content = self.__class__.Restriction(self)
2896        elif component == 'list':
2897            self.content = self.__class__.List(self)
2898        elif component == 'union':
2899            self.content = self.__class__.Union(self)
2900        else:
2901            raise SchemaError, 'Unknown component (%s)' %(component)
2902        self.content.fromDom(child)
2903
2904    class Restriction(XMLSchemaComponent,\
2905                      RestrictionMarker):
2906        """<restriction base>
2907           parents:
2908               simpleType
2909           attributes:
2910               id -- ID
2911               base -- QName, required or simpleType child
2912
2913           contents:
2914               annotation?, simpleType?, (enumeration | length |
2915               maxExclusive | maxInclusive | maxLength | minExclusive |
2916               minInclusive | minLength | pattern | fractionDigits |
2917               totalDigits | whiteSpace)*
2918        """
2919        attributes = {'id':None,
2920            'base':None }
2921        contents = {'xsd':['annotation', 'simpleType']+RestrictionMarker.facets}
2922        tag = 'restriction'
2923
2924        def __init__(self, parent):
2925            XMLSchemaComponent.__init__(self, parent)
2926            self.annotation = None
2927            self.content = None
2928            self.facets = None
2929
2930        def getAttributeBase(self):
2931            return XMLSchemaComponent.getAttribute(self, 'base')
2932
2933        def getTypeDefinition(self, attribute='base'):
2934            return XMLSchemaComponent.getTypeDefinition(self, attribute)
2935
2936        def getSimpleTypeContent(self):
2937            for el in self.content:
2938                if el.isSimple(): return el
2939            return None
2940
2941        def fromDom(self, node):
2942            self.facets = []
2943            self.setAttributes(node)
2944            contents = self.getContents(node)
2945            content = []
2946
2947            for indx in range(len(contents)):
2948                component = SplitQName(contents[indx].getTagName())[1]
2949                if (component == 'annotation') and (not indx):
2950                    self.annotation = Annotation(self)
2951                    self.annotation.fromDom(contents[indx])
2952                    continue
2953                elif (component == 'simpleType') and (not indx or indx == 1):
2954                    content.append(AnonymousSimpleType(self))
2955                    content[-1].fromDom(contents[indx])
2956                elif component in RestrictionMarker.facets:
2957                    self.facets.append(contents[indx])
2958                else:
2959                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
2960            self.content = tuple(content)
2961
2962
2963    class Union(XMLSchemaComponent,
2964                UnionMarker):
2965        """<union>
2966           parents:
2967               simpleType
2968           attributes:
2969               id -- ID
2970               memberTypes -- list of QNames, required or simpleType child.
2971
2972           contents:
2973               annotation?, simpleType*
2974        """
2975        attributes = {'id':None,
2976            'memberTypes':None }
2977        contents = {'xsd':['annotation', 'simpleType']}
2978        tag = 'union'
2979
2980        def __init__(self, parent):
2981            XMLSchemaComponent.__init__(self, parent)
2982            self.annotation = None
2983            self.content = None
2984
2985        def fromDom(self, node):
2986            self.setAttributes(node)
2987            contents = self.getContents(node)
2988            content = []
2989
2990            for indx in range(len(contents)):
2991                component = SplitQName(contents[indx].getTagName())[1]
2992                if (component == 'annotation') and (not indx):
2993                    self.annotation = Annotation(self)
2994                    self.annotation.fromDom(contents[indx])
2995                elif (component == 'simpleType'):
2996                    content.append(AnonymousSimpleType(self))
2997                    content[-1].fromDom(contents[indx])
2998                else:
2999                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
3000            self.content = tuple(content)
3001
3002    class List(XMLSchemaComponent,
3003               ListMarker):
3004        """<list>
3005           parents:
3006               simpleType
3007           attributes:
3008               id -- ID
3009               itemType -- QName, required or simpleType child.
3010
3011           contents:
3012               annotation?, simpleType?
3013        """
3014        attributes = {'id':None,
3015            'itemType':None }
3016        contents = {'xsd':['annotation', 'simpleType']}
3017        tag = 'list'
3018
3019        def __init__(self, parent):
3020            XMLSchemaComponent.__init__(self, parent)
3021            self.annotation = None
3022            self.content = None
3023
3024        def getItemType(self):
3025            return self.attributes.get('itemType')
3026
3027        def getTypeDefinition(self, attribute='itemType'):
3028            """
3029            return the type refered to by itemType attribute or
3030            the simpleType content.  If returns None, then the
3031            type refered to by itemType is primitive.
3032            """
3033            tp = XMLSchemaComponent.getTypeDefinition(self, attribute)
3034            return tp or self.content
3035
3036        def fromDom(self, node):
3037            self.annotation = None
3038            self.content = None
3039            self.setAttributes(node)
3040            contents = self.getContents(node)
3041            for indx in range(len(contents)):
3042                component = SplitQName(contents[indx].getTagName())[1]
3043                if (component == 'annotation') and (not indx):
3044                    self.annotation = Annotation(self)
3045                    self.annotation.fromDom(contents[indx])
3046                elif (component == 'simpleType'):
3047                    self.content = AnonymousSimpleType(self)
3048                    self.content.fromDom(contents[indx])
3049                    break
3050                else:
3051                    raise SchemaError, 'Unknown component (%s)' %(i.getTagName())
3052
3053
3054class AnonymousSimpleType(SimpleType,\
3055                          SimpleMarker,\
3056                          LocalMarker):
3057    """<simpleType>
3058       parents:
3059           attribute, element, list, restriction, union
3060       attributes:
3061           id -- ID
3062
3063       contents:
3064           annotation?, (restriction | list | union)
3065    """
3066    required = []
3067    attributes = {'id':None}
3068    tag = 'simpleType'
3069
3070
3071class Redefine:
3072    """<redefine>
3073       parents:
3074       attributes:
3075
3076       contents:
3077    """
3078    tag = 'redefine'
3079
3080
3081###########################
3082###########################
3083
3084
3085if sys.version_info[:2] >= (2, 2):
3086    tupleClass = tuple
3087else:
3088    import UserTuple
3089    tupleClass = UserTuple.UserTuple
3090
3091class TypeDescriptionComponent(tupleClass):
3092    """Tuple of length 2, consisting of
3093       a namespace and unprefixed name.
3094    """
3095    def __init__(self, args):
3096        """args -- (namespace, name)
3097           Remove the name's prefix, irrelevant.
3098        """
3099        if len(args) != 2:
3100            raise TypeError, 'expecting tuple (namespace, name), got %s' %args
3101        elif args[1].find(':') >= 0:
3102            args = (args[0], SplitQName(args[1])[1])
3103        tuple.__init__(self, args)
3104        return
3105
3106    def getTargetNamespace(self):
3107        return self[0]
3108
3109    def getName(self):
3110        return self[1]
3111
3112
3113