|
- #!/usr/bin/env python
- # Copyright (c) 2003, The Regents of the University of California,
- # through Lawrence Berkeley National Laboratory (subject to receipt of
- # any required approvals from the U.S. Dept. of Energy). All rights
- # reserved.
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
- #
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE.
-
- ident = "$Id$"
-
- import types
- import weakref
- import sys
- import warnings
- import logging
- from Namespaces import SCHEMA, XMLNS, SOAP, APACHE
- from Utility import DOM, DOMException, Collection, SplitQName, basejoin
- from StringIO import StringIO
-
- # If we have no threading, this should be a no-op
- try:
- from threading import RLock
- except ImportError:
- class RLock:
- def acquire():
- pass
-
- def release():
- pass
-
- #
- # Collections in XMLSchema class
- #
- TYPES = 'types'
- ATTRIBUTE_GROUPS = 'attr_groups'
- ATTRIBUTES = 'attr_decl'
- ELEMENTS = 'elements'
- MODEL_GROUPS = 'model_groups'
- BUILT_IN_NAMESPACES = [SOAP.ENC, ] + SCHEMA.XSD_LIST + [APACHE.AXIS_NS]
-
-
- def GetSchema(component):
- """convience function for finding the parent XMLSchema instance.
- """
- parent = component
- while not isinstance(parent, XMLSchema):
- parent = parent._parent()
- return parent
-
-
- class SchemaReader:
- """A SchemaReader creates XMLSchema objects from urls and xml data.
- """
-
- namespaceToSchema = {}
-
- def __init__(self, domReader=None, base_url=None):
- """domReader -- class must implement DOMAdapterInterface
- base_url -- base url string
- """
- self.__base_url = base_url
- self.__readerClass = domReader
- if not self.__readerClass:
- self.__readerClass = DOMAdapter
- self._includes = {}
- self._imports = {}
-
- def __setImports(self, schema):
- """Add dictionary of imports to schema instance.
- schema -- XMLSchema instance
- """
- for ns, val in schema.imports.items():
- if ns in self._imports:
- schema.addImportSchema(self._imports[ns])
-
- def __setIncludes(self, schema):
- """Add dictionary of includes to schema instance.
- schema -- XMLSchema instance
- """
- for schemaLocation, val in schema.includes.items():
- if schemaLocation in self._includes:
- schema.addIncludeSchema(schemaLocation, self._imports[schemaLocation])
-
- def addSchemaByLocation(self, location, schema):
- """provide reader with schema document for a location.
- """
- self._includes[location] = schema
-
- def addSchemaByNamespace(self, schema):
- """provide reader with schema document for a targetNamespace.
- """
- self._imports[schema.targetNamespace] = schema
-
- def loadFromNode(self, parent, element):
- """element -- DOM node or document
- parent -- WSDLAdapter instance
- """
- reader = self.__readerClass(element)
- schema = XMLSchema(parent)
- #HACK to keep a reference
- schema.wsdl = parent
- schema.setBaseUrl(self.__base_url)
- schema.load(reader)
- return schema
-
- def loadFromStream(self, file, url=None):
- """Return an XMLSchema instance loaded from a file object.
- file -- file object
- url -- base location for resolving imports/includes.
- """
- reader = self.__readerClass()
- reader.loadDocument(file)
- schema = XMLSchema()
- if url is not None:
- schema.setBaseUrl(url)
- schema.load(reader)
- self.__setIncludes(schema)
- self.__setImports(schema)
- return schema
-
- def loadFromString(self, data):
- """Return an XMLSchema instance loaded from an XML string.
- data -- XML string
- """
- return self.loadFromStream(StringIO(data))
-
- def loadFromURL(self, url, schema=None):
- """Return an XMLSchema instance loaded from the given url.
- url -- URL to dereference
- schema -- Optional XMLSchema instance.
- """
- reader = self.__readerClass()
- if self.__base_url:
- url = basejoin(self.__base_url, url)
-
- reader.loadFromURL(url)
- schema = schema or XMLSchema()
- schema.setBaseUrl(url)
- schema.load(reader)
- self.__setIncludes(schema)
- self.__setImports(schema)
- return schema
-
- def loadFromFile(self, filename):
- """Return an XMLSchema instance loaded from the given file.
- filename -- name of file to open
- """
- if self.__base_url:
- filename = basejoin(self.__base_url, filename)
- file = open(filename, 'rb')
- try:
- schema = self.loadFromStream(file, filename)
- finally:
- file.close()
-
- return schema
-
-
- class SchemaError(Exception):
- pass
-
-
- class NoSchemaLocationWarning(Exception):
- pass
-
-
- ###########################
- # DOM Utility Adapters
- ##########################
- class DOMAdapterInterface:
- def hasattr(self, attr, ns=None):
- """return true if node has attribute
- attr -- attribute to check for
- ns -- namespace of attribute, by default None
- """
- raise NotImplementedError('adapter method not implemented')
-
- def getContentList(self, *contents):
- """returns an ordered list of child nodes
- *contents -- list of node names to return
- """
- raise NotImplementedError('adapter method not implemented')
-
- def setAttributeDictionary(self, attributes):
- """set attribute dictionary
- """
- raise NotImplementedError('adapter method not implemented')
-
- def getAttributeDictionary(self):
- """returns a dict of node's attributes
- """
- raise NotImplementedError('adapter method not implemented')
-
- def getNamespace(self, prefix):
- """returns namespace referenced by prefix.
- """
- raise NotImplementedError('adapter method not implemented')
-
- def getTagName(self):
- """returns tagName of node
- """
- raise NotImplementedError('adapter method not implemented')
-
- def getParentNode(self):
- """returns parent element in DOMAdapter or None
- """
- raise NotImplementedError('adapter method not implemented')
-
- def loadDocument(self, file):
- """load a Document from a file object
- file --
- """
- raise NotImplementedError('adapter method not implemented')
-
- def loadFromURL(self, url):
- """load a Document from an url
- url -- URL to dereference
- """
- raise NotImplementedError('adapter method not implemented')
-
-
- class DOMAdapter(DOMAdapterInterface):
- """Adapter for ZSI.Utility.DOM
- """
- def __init__(self, node=None):
- """Reset all instance variables.
- element -- DOM document, node, or None
- """
- if hasattr(node, 'documentElement'):
- self.__node = node.documentElement
- else:
- self.__node = node
- self.__attributes = None
-
- def getNode(self):
- return self.__node
-
- def hasattr(self, attr, ns=None):
- """attr -- attribute
- ns -- optional namespace, None means unprefixed attribute.
- """
- if not self.__attributes:
- self.setAttributeDictionary()
- if ns:
- return attr in self.__attributes.get(ns, {})
- return attr in self.__attributes
-
- def getContentList(self, *contents):
- nodes = []
- ELEMENT_NODE = self.__node.ELEMENT_NODE
- for child in DOM.getElements(self.__node, None):
- if child.nodeType == ELEMENT_NODE and\
- SplitQName(child.tagName)[1] in contents:
- nodes.append(child)
- return map(self.__class__, nodes)
-
- def setAttributeDictionary(self):
- self.__attributes = {}
- for v in self.__node._attrs.values():
- self.__attributes[v.nodeName] = v.nodeValue
-
- def getAttributeDictionary(self):
- if not self.__attributes:
- self.setAttributeDictionary()
- return self.__attributes
-
- def getTagName(self):
- return self.__node.tagName
-
- def getParentNode(self):
- if self.__node.parentNode.nodeType == self.__node.ELEMENT_NODE:
- return DOMAdapter(self.__node.parentNode)
- return None
-
- def getNamespace(self, prefix):
- """prefix -- deference namespace prefix in node's context.
- Ascends parent nodes until found.
- """
- namespace = None
- if prefix == 'xmlns':
- namespace = DOM.findDefaultNS(prefix, self.__node)
- else:
- try:
- namespace = DOM.findNamespaceURI(prefix, self.__node)
- except DOMException, ex:
- if prefix != 'xml':
- raise SchemaError('%s namespace not declared for %s' % (prefix, self.__node._get_tagName()))
- namespace = XMLNS.XML
- return namespace
-
- def loadDocument(self, file):
- self.__node = DOM.loadDocument(file)
- if hasattr(self.__node, 'documentElement'):
- self.__node = self.__node.documentElement
-
- def loadFromURL(self, url):
- self.__node = DOM.loadFromURL(url)
- if hasattr(self.__node, 'documentElement'):
- self.__node = self.__node.documentElement
-
-
- class XMLBase:
- """ These class variables are for string indentation.
- """
- tag = None
- __indent = 0
- __rlock = RLock()
-
- def __str__(self):
- XMLBase.__rlock.acquire()
- XMLBase.__indent += 1
- tmp = "<" + str(self.__class__) + '>\n'
- for k, v in self.__dict__.items():
- tmp += "%s* %s = %s\n" % (XMLBase.__indent * ' ', k, v)
- XMLBase.__indent -= 1
- XMLBase.__rlock.release()
- return tmp
-
-
- """Marker Interface: can determine something about an instances properties by using
- the provided convenience functions.
-
- """
-
-
- class DefinitionMarker:
- """marker for definitions
- """
- pass
-
-
- class DeclarationMarker:
- """marker for declarations
- """
- pass
-
-
- class AttributeMarker:
- """marker for attributes
- """
- pass
-
-
- class AttributeGroupMarker:
- """marker for attribute groups
- """
- pass
-
-
- class WildCardMarker:
- """marker for wildcards
- """
- pass
-
-
- class ElementMarker:
- """marker for wildcards
- """
- pass
-
-
- class ReferenceMarker:
- """marker for references
- """
- pass
-
-
- class ModelGroupMarker:
- """marker for model groups
- """
- pass
-
-
- class AllMarker(ModelGroupMarker):
- """marker for all model group
- """
- pass
-
-
- class ChoiceMarker(ModelGroupMarker):
- """marker for choice model group
- """
- pass
-
-
- class SequenceMarker(ModelGroupMarker):
- """marker for sequence model group
- """
- pass
-
-
- class ExtensionMarker:
- """marker for extensions
- """
- pass
-
-
- class RestrictionMarker:
- """marker for restrictions
- """
- facets = ['enumeration', 'length', 'maxExclusive', 'maxInclusive',\
- 'maxLength', 'minExclusive', 'minInclusive', 'minLength',\
- 'pattern', 'fractionDigits', 'totalDigits', 'whiteSpace']
-
-
- class SimpleMarker:
- """marker for simple type information
- """
- pass
-
-
- class ListMarker:
- """marker for simple type list
- """
- pass
-
-
- class UnionMarker:
- """marker for simple type Union
- """
- pass
-
-
- class ComplexMarker:
- """marker for complex type information
- """
- pass
-
-
- class LocalMarker:
- """marker for complex type information
- """
- pass
-
-
- class MarkerInterface:
- def isDefinition(self):
- return isinstance(self, DefinitionMarker)
-
- def isDeclaration(self):
- return isinstance(self, DeclarationMarker)
-
- def isAttribute(self):
- return isinstance(self, AttributeMarker)
-
- def isAttributeGroup(self):
- return isinstance(self, AttributeGroupMarker)
-
- def isElement(self):
- return isinstance(self, ElementMarker)
-
- def isReference(self):
- return isinstance(self, ReferenceMarker)
-
- def isWildCard(self):
- return isinstance(self, WildCardMarker)
-
- def isModelGroup(self):
- return isinstance(self, ModelGroupMarker)
-
- def isAll(self):
- return isinstance(self, AllMarker)
-
- def isChoice(self):
- return isinstance(self, ChoiceMarker)
-
- def isSequence(self):
- return isinstance(self, SequenceMarker)
-
- def isExtension(self):
- return isinstance(self, ExtensionMarker)
-
- def isRestriction(self):
- return isinstance(self, RestrictionMarker)
-
- def isSimple(self):
- return isinstance(self, SimpleMarker)
-
- def isComplex(self):
- return isinstance(self, ComplexMarker)
-
- def isLocal(self):
- return isinstance(self, LocalMarker)
-
- def isList(self):
- return isinstance(self, ListMarker)
-
- def isUnion(self):
- return isinstance(self, UnionMarker)
-
-
- ##########################################################
- # Schema Components
- #########################################################
- class XMLSchemaComponent(XMLBase, MarkerInterface):
- """
- class variables:
- required -- list of required attributes
- attributes -- dict of default attribute values, including None.
- Value can be a function for runtime dependencies.
- contents -- dict of namespace keyed content lists.
- 'xsd' content of xsd namespace.
- xmlns_key -- key for declared xmlns namespace.
- xmlns -- xmlns is special prefix for namespace dictionary
- xml -- special xml prefix for xml namespace.
- """
- required = []
- attributes = {}
- contents = {}
- xmlns_key = ''
- xmlns = 'xmlns'
- xml = 'xml'
-
- def __init__(self, parent=None):
- """parent -- parent instance
- instance variables:
- attributes -- dictionary of node's attributes
- """
- self.attributes = None
- self._parent = parent
- if self._parent:
- self._parent = weakref.ref(parent)
-
- if not self.__class__ == XMLSchemaComponent\
- and not (type(self.__class__.required) == type(XMLSchemaComponent.required)\
- and type(self.__class__.attributes) == type(XMLSchemaComponent.attributes)\
- and type(self.__class__.contents) == type(XMLSchemaComponent.contents)):
- raise RuntimeError('Bad type for a class variable in %s' % self.__class__)
-
- def getItemTrace(self):
- """Returns a node trace up to the <schema> item.
- """
- item, path, name, ref = self, [], 'name', 'ref'
- while not isinstance(item, XMLSchema) and not isinstance(item, WSDLToolsAdapter):
- attr = item.getAttribute(name)
- if not attr:
- attr = item.getAttribute(ref)
- if not attr:
- path.append('<%s>' % (item.tag))
- else:
- path.append('<%s ref="%s">' % (item.tag, attr))
- else:
- path.append('<%s name="%s">' % (item.tag, attr))
-
- item = item._parent()
- try:
- tns = item.getTargetNamespace()
- except:
- tns = ''
- path.append('<%s targetNamespace="%s">' % (item.tag, tns))
- path.reverse()
- return ''.join(path)
-
- def getTargetNamespace(self):
- """return targetNamespace
- """
- parent = self
- targetNamespace = 'targetNamespace'
- tns = self.attributes.get(targetNamespace)
- while not tns and parent and parent._parent is not None:
- parent = parent._parent()
- tns = parent.attributes.get(targetNamespace)
- return tns or ''
-
- def getAttributeDeclaration(self, attribute):
- """attribute -- attribute with a QName value (eg. type).
- collection -- check types collection in parent Schema instance
- """
- return self.getQNameAttribute(ATTRIBUTES, attribute)
-
- def getAttributeGroup(self, attribute):
- """attribute -- attribute with a QName value (eg. type).
- collection -- check types collection in parent Schema instance
- """
- return self.getQNameAttribute(ATTRIBUTE_GROUPS, attribute)
-
- def getTypeDefinition(self, attribute):
- """attribute -- attribute with a QName value (eg. type).
- collection -- check types collection in parent Schema instance
- """
- return self.getQNameAttribute(TYPES, attribute)
-
- def getElementDeclaration(self, attribute):
- """attribute -- attribute with a QName value (eg. element).
- collection -- check elements collection in parent Schema instance.
- """
- return self.getQNameAttribute(ELEMENTS, attribute)
-
- def getModelGroup(self, attribute):
- """attribute -- attribute with a QName value (eg. ref).
- collection -- check model_group collection in parent Schema instance.
- """
- return self.getQNameAttribute(MODEL_GROUPS, attribute)
-
- def getQNameAttribute(self, collection, attribute):
- """returns object instance representing QName --> (namespace,name),
- or if does not exist return None.
- attribute -- an information item attribute, with a QName value.
- collection -- collection in parent Schema instance to search.
- """
- tdc = self.getAttributeQName(attribute)
- if not tdc:
- return
-
- obj = self.getSchemaItem(collection, tdc.getTargetNamespace(), tdc.getName())
- if obj:
- return obj
-
- # raise SchemaError, 'No schema item "%s" in collection %s' %(tdc, collection)
- return
-
- def getSchemaItem(self, collection, namespace, name):
- """returns object instance representing namespace, name,
- or if does not exist return None if built-in, else
- raise SchemaError.
-
- namespace -- namespace item defined in.
- name -- name of item.
- collection -- collection in parent Schema instance to search.
- """
- parent = GetSchema(self)
- if parent.targetNamespace == namespace:
- try:
- obj = getattr(parent, collection)[name]
- except KeyError, ex:
- raise KeyError('targetNamespace(%s) collection(%s) has no item(%s)' % (namespace, collection, name))
-
- return obj
-
- if not namespace in parent.imports:
- if namespace in BUILT_IN_NAMESPACES:
- # built-in just return
- # WARNING: expecting import if "redefine" or add to built-in namespace.
- return
-
- raise SchemaError('schema "%s" does not import namespace "%s"' % (
- parent.targetNamespace, namespace))
-
- # Lazy Eval
- schema = parent.imports[namespace]
- if not isinstance(schema, XMLSchema):
- schema = schema.getSchema()
- if schema is not None:
- parent.imports[namespace] = schema
-
- if schema is None:
- if namespace in BUILT_IN_NAMESPACES:
- # built-in just return
- return
-
- raise SchemaError('no schema instance for imported namespace (%s).' % (namespace))
-
- if not isinstance(schema, XMLSchema):
- raise TypeError('expecting XMLSchema instance not "%r"' % schema)
-
- try:
- obj = getattr(schema, collection)[name]
- except KeyError, ex:
- raise KeyError('targetNamespace(%s) collection(%s) has no item(%s)' % (namespace, collection, name))
-
- return obj
-
- def getXMLNS(self, prefix=None):
- """deference prefix or by default xmlns, returns namespace.
- """
- if prefix == XMLSchemaComponent.xml:
- return XMLNS.XML
- parent = self
- ns = self.attributes[XMLSchemaComponent.xmlns].get(prefix or\
- XMLSchemaComponent.xmlns_key)
- while not ns:
- parent = parent._parent()
- ns = parent.attributes[XMLSchemaComponent.xmlns].get(prefix or\
- XMLSchemaComponent.xmlns_key)
- if not ns and isinstance(parent, WSDLToolsAdapter):
- if prefix is None:
- return ''
- raise SchemaError('unknown prefix %s' % prefix)
- return ns
-
- def getAttribute(self, attribute):
- """return requested attribute value or None
- """
- if type(attribute) in (list, tuple):
- if len(attribute) != 2:
- raise LookupError('To access attributes must use name or (namespace,name)')
-
- ns_dict = self.attributes.get(attribute[0])
- if ns_dict is None:
- return None
-
- return ns_dict.get(attribute[1])
-
- return self.attributes.get(attribute)
-
- def getAttributeQName(self, attribute):
- """return requested attribute value as (namespace,name) or None
- """
- qname = self.getAttribute(attribute)
- if isinstance(qname, TypeDescriptionComponent) is True:
- return qname
- if qname is None:
- return None
-
- prefix, ncname = SplitQName(qname)
- namespace = self.getXMLNS(prefix)
- return TypeDescriptionComponent((namespace, ncname))
-
- def getAttributeName(self):
- """return attribute name or None
- """
- return self.getAttribute('name')
-
- def setAttributes(self, node):
- """Sets up attribute dictionary, checks for required attributes and
- sets default attribute values. attr is for default attribute values
- determined at runtime.
-
- structure of attributes dictionary
- ['xmlns'][xmlns_key] -- xmlns namespace
- ['xmlns'][prefix] -- declared namespace prefix
- [namespace][prefix] -- attributes declared in a namespace
- [attribute] -- attributes w/o prefix, default namespaces do
- not directly apply to attributes, ie Name can't collide
- with QName.
- """
- self.attributes = {XMLSchemaComponent.xmlns: {}}
- for k, v in node.getAttributeDictionary().items():
- prefix, value = SplitQName(k)
- if value == XMLSchemaComponent.xmlns:
- self.attributes[value][prefix or XMLSchemaComponent.xmlns_key] = v
- elif prefix:
- ns = node.getNamespace(prefix)
- if not ns:
- raise SchemaError('no namespace for attribute prefix %s' % prefix)
- if not ns in self.attributes:
- self.attributes[ns] = {}
- elif value in self.attributes[ns]:
- raise SchemaError('attribute %s declared multiple times in %s' % (value, ns))
- self.attributes[ns][value] = v
- elif not value in self.attributes:
- self.attributes[value] = v
- else:
- raise SchemaError('attribute %s declared multiple times' % value)
-
- if not isinstance(self, WSDLToolsAdapter):
- self.__checkAttributes()
- self.__setAttributeDefaults()
-
- #set QNames
- for k in ['type', 'element', 'base', 'ref', 'substitutionGroup', 'itemType']:
- if k in self.attributes:
- prefix, value = SplitQName(self.attributes.get(k))
- self.attributes[k] = \
- TypeDescriptionComponent((self.getXMLNS(prefix), value))
-
- #Union, memberTypes is a whitespace separated list of QNames
- for k in ['memberTypes']:
- if k in self.attributes:
- qnames = self.attributes[k]
- self.attributes[k] = []
- for qname in qnames.split():
- prefix, value = SplitQName(qname)
- self.attributes['memberTypes'].append(\
- TypeDescriptionComponent(\
- (self.getXMLNS(prefix), value)))
-
- def getContents(self, node):
- """retrieve xsd contents
- """
- return node.getContentList(*self.__class__.contents['xsd'])
-
- def __setAttributeDefaults(self):
- """Looks for default values for unset attributes. If
- class variable representing attribute is None, then
- it must be defined as an instance variable.
- """
- for k, v in self.__class__.attributes.items():
- if v is not None and k in self.attributes is False:
- if isinstance(v, types.FunctionType):
- self.attributes[k] = v(self)
- else:
- self.attributes[k] = v
-
- def __checkAttributes(self):
- """Checks that required attributes have been defined,
- attributes w/default cannot be required. Checks
- all defined attributes are legal, attribute
- references are not subject to this test.
- """
- for a in self.__class__.required:
- if not a in self.attributes:
- raise SchemaError('class instance %s, missing required attribute %s' % (self.__class__, a))
- for a, v in self.attributes.items():
- # attribute #other, ie. not in empty namespace
- if type(v) is dict:
- continue
-
- # predefined prefixes xmlns, xml
- if a in (XMLSchemaComponent.xmlns, XMLNS.XML):
- continue
-
- if (a not in self.__class__.attributes.keys()) and not\
- (self.isAttribute() and self.isReference()):
- raise SchemaError('%s, unknown attribute(%s, %s)' % (self.getItemTrace(), a, self.attributes[a]))
-
-
- class WSDLToolsAdapter(XMLSchemaComponent):
- """WSDL Adapter to grab the attributes from the wsdl document node.
- """
- attributes = {'name': None, 'targetNamespace': None}
- tag = 'definitions'
-
- def __init__(self, wsdl):
- XMLSchemaComponent.__init__(self, parent=wsdl)
- self.setAttributes(DOMAdapter(wsdl.document))
-
- def getImportSchemas(self):
- """returns WSDLTools.WSDL types Collection
- """
- return self._parent().types
-
-
- class Notation(XMLSchemaComponent):
- """<notation>
- parent:
- schema
- attributes:
- id -- ID
- name -- NCName, Required
- public -- token, Required
- system -- anyURI
- contents:
- annotation?
- """
- required = ['name', 'public']
- attributes = {'id': None, 'name': None, 'public': None, 'system': None}
- contents = {'xsd': ('annotation')}
- tag = 'notation'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class Annotation(XMLSchemaComponent):
- """<annotation>
- parent:
- all,any,anyAttribute,attribute,attributeGroup,choice,complexContent,
- complexType,element,extension,field,group,import,include,key,keyref,
- list,notation,redefine,restriction,schema,selector,simpleContent,
- simpleType,union,unique
- attributes:
- id -- ID
- contents:
- (documentation | appinfo)*
- """
- attributes = {'id': None}
- contents = {'xsd': ('documentation', 'appinfo')}
- tag = 'annotation'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'documentation':
- #print_debug('class %s, documentation skipped' %self.__class__, 5)
- continue
- elif component == 'appinfo':
- #print_debug('class %s, appinfo skipped' %self.__class__, 5)
- continue
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
- class Documentation(XMLSchemaComponent):
- """<documentation>
- parent:
- annotation
- attributes:
- source, anyURI
- xml:lang, language
- contents:
- mixed, any
- """
- attributes = {'source': None, 'xml: lang': None}
- contents = {'xsd': ('mixed', 'any')}
- tag = 'documentation'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'mixed':
- #print_debug('class %s, mixed skipped' %self.__class__, 5)
- continue
- elif component == 'any':
- #print_debug('class %s, any skipped' %self.__class__, 5)
- continue
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
- class Appinfo(XMLSchemaComponent):
- """<appinfo>
- parent:
- annotation
- attributes:
- source, anyURI
- contents:
- mixed, any
- """
- attributes = {'source': None, 'anyURI': None}
- contents = {'xsd': ('mixed', 'any')}
- tag = 'appinfo'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'mixed':
- #print_debug('class %s, mixed skipped' %self.__class__, 5)
- continue
- elif component == 'any':
- #print_debug('class %s, any skipped' %self.__class__, 5)
- continue
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
-
- class XMLSchemaFake:
- # This is temporary, for the benefit of WSDL until the real thing works.
- def __init__(self, element):
- self.targetNamespace = DOM.getAttr(element, 'targetNamespace')
- self.element = element
-
-
- class XMLSchema(XMLSchemaComponent):
- """A schema is a collection of schema components derived from one
- or more schema documents, that is, one or more <schema> element
- information items. It represents the abstract notion of a schema
- rather than a single schema document (or other representation).
-
- <schema>
- parent:
- ROOT
- attributes:
- id -- ID
- version -- token
- xml:lang -- language
- targetNamespace -- anyURI
- attributeFormDefault -- 'qualified' | 'unqualified', 'unqualified'
- elementFormDefault -- 'qualified' | 'unqualified', 'unqualified'
- blockDefault -- '#all' | list of
- ('substitution | 'extension' | 'restriction')
- finalDefault -- '#all' | list of
- ('extension' | 'restriction' | 'list' | 'union')
-
- contents:
- ((include | import | redefine | annotation)*,
- (attribute, attributeGroup, complexType, element, group,
- notation, simpleType)*, annotation*)*
-
-
- attributes -- schema attributes
- imports -- import statements
- includes -- include statements
- redefines --
- types -- global simpleType, complexType definitions
- elements -- global element declarations
- attr_decl -- global attribute declarations
- attr_groups -- attribute Groups
- model_groups -- model Groups
- notations -- global notations
- """
- attributes = {'id': None,
- 'version': None,
- 'xml: lang': None,
- 'targetNamespace': None,
- 'attributeFormDefault': 'unqualified',
- 'elementFormDefault': 'unqualified',
- 'blockDefault': None,
- 'finalDefault': None}
- contents = {'xsd': ('include', 'import', 'redefine', 'annotation',
- 'attribute', 'attributeGroup', 'complexType',
- 'element', 'group', 'notation', 'simpleType',
- 'annotation')}
- empty_namespace = ''
- tag = 'schema'
-
- def __init__(self, parent=None, logger=None):
- """parent --
- instance variables:
- targetNamespace -- schema's declared targetNamespace, or empty string.
- _imported_schemas -- namespace keyed dict of schema dependencies, if
- a schema is provided instance will not resolve import statement.
- _included_schemas -- schemaLocation keyed dict of component schemas,
- if schema is provided instance will not resolve include statement.
- _base_url -- needed for relative URLs support, only works with URLs
- relative to initial document.
- includes -- collection of include statements
- imports -- collection of import statements
- elements -- collection of global element declarations
- types -- collection of global type definitions
- attr_decl -- collection of global attribute declarations
- attr_groups -- collection of global attribute group definitions
- model_groups -- collection of model group definitions
- notations -- collection of notations
-
- """
- self.__node = None
- self.targetNamespace = None
- XMLSchemaComponent.__init__(self, parent)
- f = lambda k: k.attributes['name']
- ns = lambda k: k.attributes['namespace']
- sl = lambda k: k.attributes['schemaLocation']
- self.includes = Collection(self, key=sl)
- self.imports = Collection(self, key=ns)
- self.elements = Collection(self, key=f)
- self.types = Collection(self, key=f)
- self.attr_decl = Collection(self, key=f)
- self.attr_groups = Collection(self, key=f)
- self.model_groups = Collection(self, key=f)
- self.notations = Collection(self, key=f)
-
- self._imported_schemas = {}
- self._included_schemas = {}
- self._base_url = None
- self.logger = logger or logging.getLogger(__name__)
-
- def getNode(self):
- """
- Interacting with the underlying DOM tree.
- """
- return self.__node
-
- def addImportSchema(self, schema):
- """for resolving import statements in Schema instance
- schema -- schema instance
- _imported_schemas
- """
- if not isinstance(schema, XMLSchema):
- raise TypeError('expecting a Schema instance')
- if schema.targetNamespace != self.targetNamespace:
- self._imported_schemas[schema.targetNamespace] = schema
- else:
- raise SchemaError('import schema bad targetNamespace')
-
- def addIncludeSchema(self, schemaLocation, schema):
- """for resolving include statements in Schema instance
- schemaLocation -- schema location
- schema -- schema instance
- _included_schemas
- """
- if not isinstance(schema, XMLSchema):
- raise TypeError('expecting a Schema instance')
- if not schema.targetNamespace or\
- schema.targetNamespace == self.targetNamespace:
- self._included_schemas[schemaLocation] = schema
- else:
- raise SchemaError('include schema bad targetNamespace')
-
- def setImportSchemas(self, schema_dict):
- """set the import schema dictionary, which is used to
- reference depedent schemas.
- """
- self._imported_schemas = schema_dict
-
- def getImportSchemas(self):
- """get the import schema dictionary, which is used to
- reference depedent schemas.
- """
- return self._imported_schemas
-
- def getSchemaNamespacesToImport(self):
- """returns tuple of namespaces the schema instance has declared
- itself to be depedent upon.
- """
- return tuple(self.includes.keys())
-
- def setIncludeSchemas(self, schema_dict):
- """set the include schema dictionary, which is keyed with
- schemaLocation (uri).
- This is a means of providing
- schemas to the current schema for content inclusion.
- """
- self._included_schemas = schema_dict
-
- def getIncludeSchemas(self):
- """get the include schema dictionary, which is keyed with
- schemaLocation (uri).
- """
- return self._included_schemas
-
- def getBaseUrl(self):
- """get base url, used for normalizing all relative uri's
- """
- return self._base_url
-
- def setBaseUrl(self, url):
- """set base url, used for normalizing all relative uri's
- """
- self._base_url = url
-
- def getElementFormDefault(self):
- """return elementFormDefault attribute
- """
- return self.attributes.get('elementFormDefault')
-
- def isElementFormDefaultQualified(self):
- return self.attributes.get('elementFormDefault') == 'qualified'
-
- def getAttributeFormDefault(self):
- """return attributeFormDefault attribute
- """
- return self.attributes.get('attributeFormDefault')
-
- def getBlockDefault(self):
- """return blockDefault attribute
- """
- return self.attributes.get('blockDefault')
-
- def getFinalDefault(self):
- """return finalDefault attribute
- """
- return self.attributes.get('finalDefault')
-
- def load(self, node, location=None):
- self.__node = node
-
- pnode = node.getParentNode()
- if pnode:
- pname = SplitQName(pnode.getTagName())[1]
- if pname == 'types':
- attributes = {}
- self.setAttributes(pnode)
- attributes.update(self.attributes)
- self.setAttributes(node)
- for k, v in attributes['xmlns'].items():
- if not k in self.attributes['xmlns']:
- self.attributes['xmlns'][k] = v
- else:
- self.setAttributes(node)
- else:
- self.setAttributes(node)
-
- self.targetNamespace = self.getTargetNamespace()
- for childNode in self.getContents(node):
- component = SplitQName(childNode.getTagName())[1]
-
- if component == 'include':
- tp = self.__class__.Include(self)
- tp.fromDom(childNode)
-
- sl = tp.attributes['schemaLocation']
- schema = tp.getSchema()
-
- if sl not in self.getIncludeSchemas():
- self.addIncludeSchema(sl, schema)
-
- self.includes[sl] = tp
-
- pn = childNode.getParentNode().getNode()
- pn.removeChild(childNode.getNode())
- for child in schema.getNode().getNode().childNodes:
- pn.appendChild(child.cloneNode(1))
-
- for collection in ['imports', 'elements', 'types',
- 'attr_decl', 'attr_groups', 'model_groups',
- 'notations']:
- for k, v in getattr(schema, collection).items():
- if k not in getattr(self, collection):
- v._parent = weakref.ref(self)
- getattr(self, collection)[k] = v
- else:
- warnings.warn("Not keeping schema component.")
-
- elif component == 'import':
- slocd = SchemaReader.namespaceToSchema
- tp = self.__class__.Import(self)
- tp.fromDom(childNode)
- import_ns = tp.getAttribute('namespace') or\
- self.__class__.empty_namespace
- schema = slocd.get(import_ns)
- if schema is None:
- schema = XMLSchema()
- slocd[import_ns] = schema
- try:
- tp.loadSchema(schema)
- except NoSchemaLocationWarning, ex:
- # Dependency declaration, hopefully implementation
- # is aware of this namespace (eg. SOAP,WSDL,?)
- self.logger.debug("IMPORT: %s : %s" % (import_ns, ex))
- del slocd[import_ns]
- continue
- except SchemaError, ex:
- #warnings.warn(\
- # '<import namespace="%s" schemaLocation=?>, %s'\
- # %(import_ns, 'failed to load schema instance')
- #)
- self.logger.debug(ex)
- del slocd[import_ns]
-
- class _LazyEvalImport(str):
- '''Lazy evaluation of import, replace entry in self.imports.'''
- #attributes = dict(namespace=import_ns)
- def getSchema(namespace):
- schema = slocd.get(namespace)
- if schema is None:
- parent = self._parent()
- wstypes = parent
- if isinstance(parent, WSDLToolsAdapter):
- wstypes = parent.getImportSchemas()
- schema = wstypes.get(namespace)
- if isinstance(schema, XMLSchema):
- self.imports[namespace] = schema
- return schema
-
- return None
-
- self.imports[import_ns] = _LazyEvalImport(import_ns)
- continue
- else:
- tp._schema = schema
-
- if import_ns in self.getImportSchemas():
- warnings.warn(\
- 'Detected multiple imports of the namespace "%s" '\
- % import_ns)
-
- self.addImportSchema(schema)
- # spec says can have multiple imports of same namespace
- # but purpose of import is just dependency declaration.
- self.imports[import_ns] = tp
-
- elif component == 'redefine':
- warnings.warn('redefine is ignored')
- elif component == 'annotation':
- warnings.warn('annotation is ignored')
- elif component == 'attribute':
- tp = AttributeDeclaration(self)
- tp.fromDom(childNode)
- self.attr_decl[tp.getAttribute('name')] = tp
- elif component == 'attributeGroup':
- tp = AttributeGroupDefinition(self)
- tp.fromDom(childNode)
- self.attr_groups[tp.getAttribute('name')] = tp
- elif component == 'element':
- tp = ElementDeclaration(self)
- tp.fromDom(childNode)
- self.elements[tp.getAttribute('name')] = tp
- elif component == 'group':
- tp = ModelGroupDefinition(self)
- tp.fromDom(childNode)
- self.model_groups[tp.getAttribute('name')] = tp
- elif component == 'notation':
- tp = Notation(self)
- tp.fromDom(childNode)
- self.notations[tp.getAttribute('name')] = tp
- elif component == 'complexType':
- tp = ComplexType(self)
- tp.fromDom(childNode)
- self.types[tp.getAttribute('name')] = tp
- elif component == 'simpleType':
- tp = SimpleType(self)
- tp.fromDom(childNode)
- self.types[tp.getAttribute('name')] = tp
- else:
- break
-
- class Import(XMLSchemaComponent):
- """<import>
- parent:
- schema
- attributes:
- id -- ID
- namespace -- anyURI
- schemaLocation -- anyURI
- contents:
- annotation?
- """
- attributes = {'id': None,
- 'namespace': None,
- 'schemaLocation': None}
- contents = {'xsd': ['annotation']}
- tag = 'import'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self._schema = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- if self.attributes['namespace'] == self.getTargetNamespace():
- raise SchemaError('namespace of schema and import match')
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
- def getSchema(self):
- """if schema is not defined, first look for a Schema class instance
- in parent Schema. Else if not defined resolve schemaLocation
- and create a new Schema class instance, and keep a hard reference.
- """
- if not self._schema:
- ns = self.attributes['namespace']
- schema = self._parent().getImportSchemas().get(ns)
- if not schema and self._parent()._parent:
- schema = self._parent()._parent().getImportSchemas().get(ns)
-
- if not schema:
- url = self.attributes.get('schemaLocation')
- if not url:
- raise SchemaError('namespace(%s) is unknown' % ns)
- base_url = self._parent().getBaseUrl()
- reader = SchemaReader(base_url=base_url)
- reader._imports = self._parent().getImportSchemas()
- reader._includes = self._parent().getIncludeSchemas()
- self._schema = reader.loadFromURL(url)
- return self._schema or schema
-
- def loadSchema(self, schema):
- """
- """
- base_url = self._parent().getBaseUrl()
- reader = SchemaReader(base_url=base_url)
- reader._imports = self._parent().getImportSchemas()
- reader._includes = self._parent().getIncludeSchemas()
- self._schema = schema
-
- if not 'schemaLocation' in self.attributes:
- raise NoSchemaLocationWarning('no schemaLocation attribute in import')
-
- reader.loadFromURL(self.attributes.get('schemaLocation'), schema)
-
- class Include(XMLSchemaComponent):
- """<include schemaLocation>
- parent:
- schema
- attributes:
- id -- ID
- schemaLocation -- anyURI, required
- contents:
- annotation?
- """
- required = ['schemaLocation']
- attributes = {'id': None,
- 'schemaLocation': None}
- contents = {'xsd': ['annotation']}
- tag = 'include'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self._schema = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
- def getSchema(self):
- """if schema is not defined, first look for a Schema class instance
- in parent Schema. Else if not defined resolve schemaLocation
- and create a new Schema class instance.
- """
- if not self._schema:
- schema = self._parent()
- self._schema = schema.getIncludeSchemas().get(self.attributes['schemaLocation'])
- if not self._schema:
- url = self.attributes['schemaLocation']
- reader = SchemaReader(base_url=schema.getBaseUrl())
- reader._imports = schema.getImportSchemas()
- reader._includes = schema.getIncludeSchemas()
-
- # create schema before loading so chameleon include
- # will evalute targetNamespace correctly.
- self._schema = XMLSchema(schema)
- reader.loadFromURL(url, self._schema)
-
- return self._schema
-
-
- class AttributeDeclaration(XMLSchemaComponent,\
- AttributeMarker,\
- DeclarationMarker):
- """<attribute name>
- parent:
- schema
- attributes:
- id -- ID
- name -- NCName, required
- type -- QName
- default -- string
- fixed -- string
- contents:
- annotation?, simpleType?
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None,
- 'type': None,
- 'default': None,
- 'fixed': None}
- contents = {'xsd': ['annotation', 'simpleType']}
- tag = 'attribute'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- """ No list or union support
- """
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- elif component == 'simpleType':
- self.content = AnonymousSimpleType(self)
- self.content.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class LocalAttributeDeclaration(AttributeDeclaration,\
- AttributeMarker,\
- LocalMarker,\
- DeclarationMarker):
- """<attribute name>
- parent:
- complexType, restriction, extension, attributeGroup
- attributes:
- id -- ID
- name -- NCName, required
- type -- QName
- form -- ('qualified' | 'unqualified'), schema.attributeFormDefault
- use -- ('optional' | 'prohibited' | 'required'), optional
- default -- string
- fixed -- string
- contents:
- annotation?, simpleType?
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None,
- 'type': None,
- 'form': lambda self: GetSchema(self).getAttributeFormDefault(),
- 'use': 'optional',
- 'default': None,
- 'fixed': None}
- contents = {'xsd': ['annotation', 'simpleType']}
-
- def __init__(self, parent):
- AttributeDeclaration.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- elif component == 'simpleType':
- self.content = AnonymousSimpleType(self)
- self.content.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class AttributeWildCard(XMLSchemaComponent,\
- AttributeMarker,\
- DeclarationMarker,\
- WildCardMarker):
- """<anyAttribute>
- parents:
- complexType, restriction, extension, attributeGroup
- attributes:
- id -- ID
- namespace -- '##any' | '##other' |
- (anyURI* | '##targetNamespace' | '##local'), ##any
- processContents -- 'lax' | 'skip' | 'strict', strict
- contents:
- annotation?
- """
- attributes = {'id': None,
- 'namespace': '##any',
- 'processContents': 'strict'}
- contents = {'xsd': ['annotation']}
- tag = 'anyAttribute'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class AttributeReference(XMLSchemaComponent,\
- AttributeMarker,\
- ReferenceMarker):
- """<attribute ref>
- parents:
- complexType, restriction, extension, attributeGroup
- attributes:
- id -- ID
- ref -- QName, required
- use -- ('optional' | 'prohibited' | 'required'), optional
- default -- string
- fixed -- string
- contents:
- annotation?
- """
- required = ['ref']
- attributes = {'id': None,
- 'ref': None,
- 'use': 'optional',
- 'default': None,
- 'fixed': None}
- contents = {'xsd': ['annotation']}
- tag = 'attribute'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def getAttributeDeclaration(self, attribute='ref'):
- return XMLSchemaComponent.getAttributeDeclaration(self, attribute)
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class AttributeGroupDefinition(XMLSchemaComponent,\
- AttributeGroupMarker,\
- DefinitionMarker):
- """<attributeGroup name>
- parents:
- schema, redefine
- attributes:
- id -- ID
- name -- NCName, required
- contents:
- annotation?, (attribute | attributeGroup)*, anyAttribute?
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None}
- contents = {'xsd': ['annotation', 'attribute', 'attributeGroup', 'anyAttribute']}
- tag = 'attributeGroup'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.attr_content = None
-
- def getAttributeContent(self):
- return self.attr_content
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for indx in range(len(contents)):
- component = SplitQName(contents[indx].getTagName())[1]
- if (component == 'annotation') and (not indx):
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- elif component == 'attribute':
- if contents[indx].hasattr('name'):
- content.append(LocalAttributeDeclaration(self))
- elif contents[indx].hasattr('ref'):
- content.append(AttributeReference(self))
- else:
- raise SchemaError('Unknown attribute type')
- content[-1].fromDom(contents[indx])
- elif component == 'attributeGroup':
- content.append(AttributeGroupReference(self))
- content[-1].fromDom(contents[indx])
- elif component == 'anyAttribute':
- if len(contents) != indx + 1:
- raise SchemaError('anyAttribute is out of order in %s' % self.getItemTrace())
- content.append(AttributeWildCard(self))
- content[-1].fromDom(contents[indx])
- else:
- raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName()))
-
- self.attr_content = tuple(content)
-
-
- class AttributeGroupReference(XMLSchemaComponent,\
- AttributeGroupMarker,\
- ReferenceMarker):
- """<attributeGroup ref>
- parents:
- complexType, restriction, extension, attributeGroup
- attributes:
- id -- ID
- ref -- QName, required
- contents:
- annotation?
- """
- required = ['ref']
- attributes = {'id': None,
- 'ref': None}
- contents = {'xsd': ['annotation']}
- tag = 'attributeGroup'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def getAttributeGroup(self, attribute='ref'):
- """attribute -- attribute with a QName value (eg. type).
- collection -- check types collection in parent Schema instance
- """
- return XMLSchemaComponent.getAttributeGroup(self, attribute)
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- ######################################################
- # Elements
- #####################################################
- class IdentityConstrants(XMLSchemaComponent):
- """Allow one to uniquely identify nodes in a document and ensure the
- integrity of references between them.
-
- attributes -- dictionary of attributes
- selector -- XPath to selected nodes
- fields -- list of XPath to key field
- """
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.selector = None
- self.fields = None
- self.annotation = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- fields = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- elif component == 'selector':
- self.selector = self.Selector(self)
- self.selector.fromDom(i)
- continue
- elif component == 'field':
- fields.append(self.Field(self))
- fields[-1].fromDom(i)
- continue
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.fields = tuple(fields)
-
- class Constraint(XMLSchemaComponent):
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
- class Selector(Constraint):
- """<selector xpath>
- parent:
- unique, key, keyref
- attributes:
- id -- ID
- xpath -- XPath subset, required
- contents:
- annotation?
- """
- required = ['xpath']
- attributes = {'id': None,
- 'xpath': None}
- contents = {'xsd': ['annotation']}
- tag = 'selector'
-
- class Field(Constraint):
- """<field xpath>
- parent:
- unique, key, keyref
- attributes:
- id -- ID
- xpath -- XPath subset, required
- contents:
- annotation?
- """
- required = ['xpath']
- attributes = {'id': None,
- 'xpath': None}
- contents = {'xsd': ['annotation']}
- tag = 'field'
-
-
- class Unique(IdentityConstrants):
- """<unique name> Enforce fields are unique w/i a specified scope.
-
- parent:
- element
- attributes:
- id -- ID
- name -- NCName, required
- contents:
- annotation?, selector, field+
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None}
- contents = {'xsd': ['annotation', 'selector', 'field']}
- tag = 'unique'
-
-
- class Key(IdentityConstrants):
- """<key name> Enforce fields are unique w/i a specified scope, and all
- field values are present w/i document. Fields cannot
- be nillable.
-
- parent:
- element
- attributes:
- id -- ID
- name -- NCName, required
- contents:
- annotation?, selector, field+
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None}
- contents = {'xsd': ['annotation', 'selector', 'field']}
- tag = 'key'
-
-
- class KeyRef(IdentityConstrants):
- """<keyref name refer> Ensure a match between two sets of values in an
- instance.
- parent:
- element
- attributes:
- id -- ID
- name -- NCName, required
- refer -- QName, required
- contents:
- annotation?, selector, field+
- """
- required = ['name', 'refer']
- attributes = {'id': None,
- 'name': None,
- 'refer': None}
- contents = {'xsd': ['annotation', 'selector', 'field']}
- tag = 'keyref'
-
-
- class ElementDeclaration(XMLSchemaComponent,\
- ElementMarker,\
- DeclarationMarker):
- """<element name>
- parents:
- schema
- attributes:
- id -- ID
- name -- NCName, required
- type -- QName
- default -- string
- fixed -- string
- nillable -- boolean, false
- abstract -- boolean, false
- substitutionGroup -- QName
- block -- ('#all' | ('substition' | 'extension' | 'restriction')*),
- schema.blockDefault
- final -- ('#all' | ('extension' | 'restriction')*),
- schema.finalDefault
- contents:
- annotation?, (simpleType,complexType)?, (key | keyref | unique)*
-
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None,
- 'type': None,
- 'default': None,
- 'fixed': None,
- 'nillable': 0,
- 'abstract': 0,
- 'substitutionGroup': None,
- 'block': lambda self: self._parent().getBlockDefault(),
- 'final': lambda self: self._parent().getFinalDefault()}
- contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key',\
- 'keyref', 'unique']}
- tag = 'element'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
- self.constraints = ()
-
- def isQualified(self):
- """Global elements are always qualified.
- """
- return True
-
- def getAttribute(self, attribute):
- """return attribute.
- If attribute is type and it's None, and no simple or complex content,
- return the default type "xsd:anyType"
- """
- value = XMLSchemaComponent.getAttribute(self, attribute)
- if attribute != 'type' or value is not None:
- return value
-
- if self.content is not None:
- return None
-
- parent = self
- while 1:
- nsdict = parent.attributes[XMLSchemaComponent.xmlns]
- for k, v in nsdict.items():
- if v not in SCHEMA.XSD_LIST:
- continue
- return TypeDescriptionComponent((v, 'anyType'))
-
- if isinstance(parent, WSDLToolsAdapter)\
- or not hasattr(parent, '_parent'):
- break
-
- parent = parent._parent()
-
- raise SchemaError('failed to locate the XSD namespace')
-
- def getElementDeclaration(self, attribute):
- raise Warning('invalid operation for <%s>' % self.tag)
-
- def getTypeDefinition(self, attribute=None):
- """If attribute is None, "type" is assumed, return the corresponding
- representation of the global type definition (TypeDefinition),
- or the local definition if don't find "type". To maintain backwards
- compat, if attribute is provided call base class method.
- """
- if attribute:
- return XMLSchemaComponent.getTypeDefinition(self, attribute)
- gt = XMLSchemaComponent.getTypeDefinition(self, 'type')
- if gt:
- return gt
- return self.content
-
- def getConstraints(self):
- return self._constraints
-
- def setConstraints(self, constraints):
- self._constraints = tuple(constraints)
- constraints = property(getConstraints, setConstraints, None, "tuple of key, keyref, unique constraints")
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- constraints = []
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- elif component == 'simpleType' and not self.content:
- self.content = AnonymousSimpleType(self)
- self.content.fromDom(i)
- elif component == 'complexType' and not self.content:
- self.content = LocalComplexType(self)
- self.content.fromDom(i)
- elif component == 'key':
- constraints.append(Key(self))
- constraints[-1].fromDom(i)
- elif component == 'keyref':
- constraints.append(KeyRef(self))
- constraints[-1].fromDom(i)
- elif component == 'unique':
- constraints.append(Unique(self))
- constraints[-1].fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
- self.constraints = constraints
-
-
- class LocalElementDeclaration(ElementDeclaration,\
- LocalMarker):
- """<element>
- parents:
- all, choice, sequence
- attributes:
- id -- ID
- name -- NCName, required
- form -- ('qualified' | 'unqualified'), schema.elementFormDefault
- type -- QName
- minOccurs -- Whole Number, 1
- maxOccurs -- (Whole Number | 'unbounded'), 1
- default -- string
- fixed -- string
- nillable -- boolean, false
- block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault
- contents:
- annotation?, (simpleType,complexType)?, (key | keyref | unique)*
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None,
- 'form': lambda self: GetSchema(self).getElementFormDefault(),
- 'type': None,
- 'minOccurs': '1',
- 'maxOccurs': '1',
- 'default': None,
- 'fixed': None,
- 'nillable': 0,
- 'abstract': 0,
- 'block': lambda self: GetSchema(self).getBlockDefault()}
- contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key',\
- 'keyref', 'unique']}
-
- def isQualified(self):
- """
- Local elements can be qualified or unqualifed according
- to the attribute form, or the elementFormDefault. By default
- local elements are unqualified.
- """
- form = self.getAttribute('form')
- if form == 'qualified':
- return True
- if form == 'unqualified':
- return False
- raise SchemaError('Bad form (%s) for element: %s' % (form, self.getItemTrace()))
-
-
- class ElementReference(XMLSchemaComponent,\
- ElementMarker,\
- ReferenceMarker):
- """<element ref>
- parents:
- all, choice, sequence
- attributes:
- id -- ID
- ref -- QName, required
- minOccurs -- Whole Number, 1
- maxOccurs -- (Whole Number | 'unbounded'), 1
- contents:
- annotation?
- """
- required = ['ref']
- attributes = {'id': None,
- 'ref': None,
- 'minOccurs': '1',
- 'maxOccurs': '1'}
- contents = {'xsd': ['annotation']}
- tag = 'element'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def getElementDeclaration(self, attribute=None):
- """If attribute is None, "ref" is assumed, return the corresponding
- representation of the global element declaration (ElementDeclaration),
- To maintain backwards compat, if attribute is provided call base class method.
- """
- if attribute:
- return XMLSchemaComponent.getElementDeclaration(self, attribute)
- return XMLSchemaComponent.getElementDeclaration(self, 'ref')
-
- def fromDom(self, node):
- self.annotation = None
- self.setAttributes(node)
- for i in self.getContents(node):
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class ElementWildCard(LocalElementDeclaration, WildCardMarker):
- """<any>
- parents:
- choice, sequence
- attributes:
- id -- ID
- minOccurs -- Whole Number, 1
- maxOccurs -- (Whole Number | 'unbounded'), 1
- namespace -- '##any' | '##other' |
- (anyURI* | '##targetNamespace' | '##local'), ##any
- processContents -- 'lax' | 'skip' | 'strict', strict
- contents:
- annotation?
- """
- required = []
- attributes = {'id': None,
- 'minOccurs': '1',
- 'maxOccurs': '1',
- 'namespace': '##any',
- 'processContents': 'strict'}
- contents = {'xsd': ['annotation']}
- tag = 'any'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def isQualified(self):
- """
- Global elements are always qualified, but if processContents
- are not strict could have dynamically generated local elements.
- """
- return GetSchema(self).isElementFormDefaultQualified()
-
- def getAttribute(self, attribute):
- """return attribute.
- """
- return XMLSchemaComponent.getAttribute(self, attribute)
-
- def getTypeDefinition(self, attribute):
- raise Warning('invalid operation for <%s>' % self.tag)
-
- def fromDom(self, node):
- self.annotation = None
- self.setAttributes(node)
- for i in self.getContents(node):
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- ######################################################
- # Model Groups
- #####################################################
- class Sequence(XMLSchemaComponent,\
- SequenceMarker):
- """<sequence>
- parents:
- complexType, extension, restriction, group, choice, sequence
- attributes:
- id -- ID
- minOccurs -- Whole Number, 1
- maxOccurs -- (Whole Number | 'unbounded'), 1
-
- contents:
- annotation?, (element | group | choice | sequence | any)*
- """
- attributes = {'id': None,
- 'minOccurs': '1',
- 'maxOccurs': '1'}
- contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence',\
- 'any']}
- tag = 'sequence'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- continue
- elif component == 'element':
- if i.hasattr('ref'):
- content.append(ElementReference(self))
- else:
- content.append(LocalElementDeclaration(self))
- elif component == 'group':
- content.append(ModelGroupReference(self))
- elif component == 'choice':
- content.append(Choice(self))
- elif component == 'sequence':
- content.append(Sequence(self))
- elif component == 'any':
- content.append(ElementWildCard(self))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- content[-1].fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
-
- class All(XMLSchemaComponent,\
- AllMarker):
- """<all>
- parents:
- complexType, extension, restriction, group
- attributes:
- id -- ID
- minOccurs -- '0' | '1', 1
- maxOccurs -- '1', 1
-
- contents:
- annotation?, element*
- """
- attributes = {'id': None,
- 'minOccurs': '1',
- 'maxOccurs': '1'}
- contents = {'xsd': ['annotation', 'element']}
- tag = 'all'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- continue
- elif component == 'element':
- if i.hasattr('ref'):
- content.append(ElementReference(self))
- else:
- content.append(LocalElementDeclaration(self))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- content[-1].fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
-
- class Choice(XMLSchemaComponent,\
- ChoiceMarker):
- """<choice>
- parents:
- complexType, extension, restriction, group, choice, sequence
- attributes:
- id -- ID
- minOccurs -- Whole Number, 1
- maxOccurs -- (Whole Number | 'unbounded'), 1
-
- contents:
- annotation?, (element | group | choice | sequence | any)*
- """
- attributes = {'id': None,
- 'minOccurs': '1',
- 'maxOccurs': '1'}
- contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence',\
- 'any']}
- tag = 'choice'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- continue
- elif component == 'element':
- if i.hasattr('ref'):
- content.append(ElementReference(self))
- else:
- content.append(LocalElementDeclaration(self))
- elif component == 'group':
- content.append(ModelGroupReference(self))
- elif component == 'choice':
- content.append(Choice(self))
- elif component == 'sequence':
- content.append(Sequence(self))
- elif component == 'any':
- content.append(ElementWildCard(self))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- content[-1].fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
-
- class ModelGroupDefinition(XMLSchemaComponent,\
- ModelGroupMarker,\
- DefinitionMarker):
- """<group name>
- parents:
- redefine, schema
- attributes:
- id -- ID
- name -- NCName, required
-
- contents:
- annotation?, (all | choice | sequence)?
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None}
- contents = {'xsd': ['annotation', 'all', 'choice', 'sequence']}
- tag = 'group'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- continue
- elif component == 'all' and not self.content:
- self.content = All(self)
- elif component == 'choice' and not self.content:
- self.content = Choice(self)
- elif component == 'sequence' and not self.content:
- self.content = Sequence(self)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class ModelGroupReference(XMLSchemaComponent,\
- ModelGroupMarker,\
- ReferenceMarker):
- """<group ref>
- parents:
- choice, complexType, extension, restriction, sequence
- attributes:
- id -- ID
- ref -- NCName, required
- minOccurs -- Whole Number, 1
- maxOccurs -- (Whole Number | 'unbounded'), 1
-
- contents:
- annotation?
- """
- required = ['ref']
- attributes = {'id': None,
- 'ref': None,
- 'minOccurs': '1',
- 'maxOccurs': '1'}
- contents = {'xsd': ['annotation']}
- tag = 'group'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
-
- def getModelGroupReference(self):
- return self.getModelGroup('ref')
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class ComplexType(XMLSchemaComponent,\
- DefinitionMarker,\
- ComplexMarker):
- """<complexType name>
- parents:
- redefine, schema
- attributes:
- id -- ID
- name -- NCName, required
- mixed -- boolean, false
- abstract -- boolean, false
- block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault
- final -- ('#all' | ('extension' | 'restriction')*), schema.finalDefault
-
- contents:
- annotation?, (simpleContent | complexContent |
- ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None,
- 'mixed': 0,
- 'abstract': 0,
- 'block': lambda self: self._parent().getBlockDefault(),
- 'final': lambda self: self._parent().getFinalDefault()}
- contents = {'xsd': ['annotation', 'simpleContent', 'complexContent',\
- 'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',\
- 'anyAttribute', 'any']}
- tag = 'complexType'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
- self.attr_content = None
-
- def isMixed(self):
- m = self.getAttribute('mixed')
- if not m:
- return False
- if isinstance(m, basestring):
- if m in ('false', '0'):
- return False
- if m in ('true', '1'):
- return True
-
- raise SchemaError('invalid value for attribute mixed(%s): %s' % (m, self.getItemTrace()))
-
- def getAttributeContent(self):
- return self.attr_content
-
- def getElementDeclaration(self, attribute):
- raise Warning('invalid operation for <%s>' % self.tag)
-
- def getTypeDefinition(self, attribute):
- raise Warning('invalid operation for <%s>' % self.tag)
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- indx = 0
- num = len(contents)
- if not num:
- return
-
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'annotation':
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- indx += 1
- if indx < num:
- component = SplitQName(contents[indx].getTagName())[1]
-
- self.content = None
- if component == 'simpleContent':
- self.content = self.__class__.SimpleContent(self)
- self.content.fromDom(contents[indx])
- elif component == 'complexContent':
- self.content = self.__class__.ComplexContent(self)
- self.content.fromDom(contents[indx])
- else:
- if component == 'all':
- self.content = All(self)
- elif component == 'choice':
- self.content = Choice(self)
- elif component == 'sequence':
- self.content = Sequence(self)
- elif component == 'group':
- self.content = ModelGroupReference(self)
-
- if self.content:
- self.content.fromDom(contents[indx])
- indx += 1
-
- self.attr_content = []
- while indx < num:
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'attribute':
- if contents[indx].hasattr('ref'):
- self.attr_content.append(AttributeReference(self))
- else:
- self.attr_content.append(LocalAttributeDeclaration(self))
- elif component == 'attributeGroup':
- self.attr_content.append(AttributeGroupReference(self))
- elif component == 'anyAttribute':
- self.attr_content.append(AttributeWildCard(self))
- else:
- raise SchemaError('Unknown component (%s): %s' % (contents[indx].getTagName(), self.getItemTrace()))
- self.attr_content[-1].fromDom(contents[indx])
- indx += 1
-
- class _DerivedType(XMLSchemaComponent):
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- # XXX remove attribute derivation, inconsistent
- self.derivation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- for i in contents:
- component = SplitQName(i.getTagName())[1]
- if component in self.__class__.contents['xsd']:
- if component == 'annotation' and not self.annotation:
- self.annotation = Annotation(self)
- self.annotation.fromDom(i)
- continue
- elif component == 'restriction' and not self.derivation:
- self.derivation = self.__class__.Restriction(self)
- elif component == 'extension' and not self.derivation:
- self.derivation = self.__class__.Extension(self)
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.derivation.fromDom(i)
- self.content = self.derivation
-
- class ComplexContent(_DerivedType,\
- ComplexMarker):
- """<complexContent>
- parents:
- complexType
- attributes:
- id -- ID
- mixed -- boolean, false
-
- contents:
- annotation?, (restriction | extension)
- """
- attributes = {'id': None,
- 'mixed': 0}
- contents = {'xsd': ['annotation', 'restriction', 'extension']}
- tag = 'complexContent'
-
- def isMixed(self):
- m = self.getAttribute('mixed')
- if not m:
- return False
- if isinstance(m, basestring) is True:
- if m in ('false', '0'):
- return False
- if m in ('true', '1'):
- return True
- raise SchemaError('invalid value for attribute mixed(%s): %s' % (m, self.getItemTrace()))
-
- class _DerivationBase(XMLSchemaComponent):
- """<extension>,<restriction>
- parents:
- complexContent
- attributes:
- id -- ID
- base -- QName, required
-
- contents:
- annotation?, (group | all | choice | sequence)?,
- (attribute | attributeGroup)*, anyAttribute?
- """
- required = ['base']
- attributes = {'id': None,
- 'base': None}
- contents = {'xsd': ['annotation', 'group', 'all', 'choice',\
- 'sequence', 'attribute', 'attributeGroup', 'anyAttribute']}
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
- self.attr_content = None
-
- def getAttributeContent(self):
- return self.attr_content
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- indx = 0
- num = len(contents)
- #XXX ugly
- if not num:
- return
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'annotation':
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- indx += 1
- component = SplitQName(contents[indx].getTagName())[1]
-
- if component == 'all':
- self.content = All(self)
- self.content.fromDom(contents[indx])
- indx += 1
- elif component == 'choice':
- self.content = Choice(self)
- self.content.fromDom(contents[indx])
- indx += 1
- elif component == 'sequence':
- self.content = Sequence(self)
- self.content.fromDom(contents[indx])
- indx += 1
- elif component == 'group':
- self.content = ModelGroupReference(self)
- self.content.fromDom(contents[indx])
- indx += 1
- else:
- self.content = None
-
- self.attr_content = []
- while indx < num:
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'attribute':
- if contents[indx].hasattr('ref'):
- self.attr_content.append(AttributeReference(self))
- else:
- self.attr_content.append(LocalAttributeDeclaration(self))
- elif component == 'attributeGroup':
- if contents[indx].hasattr('ref'):
- self.attr_content.append(AttributeGroupReference(self))
- else:
- self.attr_content.append(AttributeGroupDefinition(self))
- elif component == 'anyAttribute':
- self.attr_content.append(AttributeWildCard(self))
- else:
- raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName()))
- self.attr_content[-1].fromDom(contents[indx])
- indx += 1
-
- class Extension(_DerivationBase,
- ExtensionMarker):
- """<extension base>
- parents:
- complexContent
- attributes:
- id -- ID
- base -- QName, required
-
- contents:
- annotation?, (group | all | choice | sequence)?,
- (attribute | attributeGroup)*, anyAttribute?
- """
- tag = 'extension'
-
- class Restriction(_DerivationBase,\
- RestrictionMarker):
- """<restriction base>
- parents:
- complexContent
- attributes:
- id -- ID
- base -- QName, required
-
- contents:
- annotation?, (group | all | choice | sequence)?,
- (attribute | attributeGroup)*, anyAttribute?
- """
- tag = 'restriction'
-
- class SimpleContent(_DerivedType,\
- SimpleMarker):
- """<simpleContent>
- parents:
- complexType
- attributes:
- id -- ID
-
- contents:
- annotation?, (restriction | extension)
- """
- attributes = {'id': None}
- contents = {'xsd': ['annotation', 'restriction', 'extension']}
- tag = 'simpleContent'
-
- class Extension(XMLSchemaComponent,\
- ExtensionMarker):
- """<extension base>
- parents:
- simpleContent
- attributes:
- id -- ID
- base -- QName, required
-
- contents:
- annotation?, (attribute | attributeGroup)*, anyAttribute?
- """
- required = ['base']
- attributes = {'id': None,
- 'base': None}
- contents = {'xsd': ['annotation', 'attribute', 'attributeGroup',
- 'anyAttribute']}
- tag = 'extension'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.attr_content = None
-
- def getAttributeContent(self):
- return self.attr_content
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
-
- indx = 0
- num = len(contents)
-
- if num:
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'annotation':
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- indx += 1
- component = SplitQName(contents[indx].getTagName())[1]
-
- content = []
- while indx < num:
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'attribute':
- if contents[indx].hasattr('ref'):
- content.append(AttributeReference(self))
- else:
- content.append(LocalAttributeDeclaration(self))
- elif component == 'attributeGroup':
- content.append(AttributeGroupReference(self))
- elif component == 'anyAttribute':
- content.append(AttributeWildCard(self))
- else:
- raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName()))
- content[-1].fromDom(contents[indx])
- indx += 1
- self.attr_content = tuple(content)
-
- class Restriction(XMLSchemaComponent,\
- RestrictionMarker):
- """<restriction base>
- parents:
- simpleContent
- attributes:
- id -- ID
- base -- QName, required
-
- contents:
- annotation?, simpleType?, (enumeration | length |
- maxExclusive | maxInclusive | maxLength | minExclusive |
- minInclusive | minLength | pattern | fractionDigits |
- totalDigits | whiteSpace)*, (attribute | attributeGroup)*,
- anyAttribute?
- """
- required = ['base']
- attributes = {'id': None,
- 'base': None}
- contents = {'xsd': ['annotation', 'simpleType', 'attribute',\
- 'attributeGroup', 'anyAttribute'] + RestrictionMarker.facets}
- tag = 'restriction'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
- self.attr_content = None
-
- def getAttributeContent(self):
- return self.attr_content
-
- def fromDom(self, node):
- self.content = []
- self.setAttributes(node)
- contents = self.getContents(node)
-
- indx = 0
- num = len(contents)
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'annotation':
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- indx += 1
- component = SplitQName(contents[indx].getTagName())[1]
-
- content = []
- while indx < num:
- component = SplitQName(contents[indx].getTagName())[1]
- if component == 'attribute':
- if contents[indx].hasattr('ref'):
- content.append(AttributeReference(self))
- else:
- content.append(LocalAttributeDeclaration(self))
- elif component == 'attributeGroup':
- content.append(AttributeGroupReference(self))
- elif component == 'anyAttribute':
- content.append(AttributeWildCard(self))
- elif component == 'simpleType':
- self.content.append(AnonymousSimpleType(self))
- self.content[-1].fromDom(contents[indx])
- else:
- raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName()))
- content[-1].fromDom(contents[indx])
- indx += 1
- self.attr_content = tuple(content)
-
-
- class LocalComplexType(ComplexType,\
- LocalMarker):
- """<complexType>
- parents:
- element
- attributes:
- id -- ID
- mixed -- boolean, false
-
- contents:
- annotation?, (simpleContent | complexContent |
- ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
- """
- required = []
- attributes = {'id': None,
- 'mixed': 0}
- tag = 'complexType'
-
-
- class SimpleType(XMLSchemaComponent,\
- DefinitionMarker,\
- SimpleMarker):
- """<simpleType name>
- parents:
- redefine, schema
- attributes:
- id -- ID
- name -- NCName, required
- final -- ('#all' | ('extension' | 'restriction' | 'list' | 'union')*),
- schema.finalDefault
-
- contents:
- annotation?, (restriction | list | union)
- """
- required = ['name']
- attributes = {'id': None,
- 'name': None,
- 'final': lambda self: self._parent().getFinalDefault()}
- contents = {'xsd': ['annotation', 'restriction', 'list', 'union']}
- tag = 'simpleType'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def getElementDeclaration(self, attribute):
- raise Warning('invalid operation for <%s>' % self.tag)
-
- def getTypeDefinition(self, attribute):
- raise Warning('invalid operation for <%s>' % self.tag)
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- for child in contents:
- component = SplitQName(child.getTagName())[1]
- if component == 'annotation':
- self.annotation = Annotation(self)
- self.annotation.fromDom(child)
- continue
- break
- else:
- return
- if component == 'restriction':
- self.content = self.__class__.Restriction(self)
- elif component == 'list':
- self.content = self.__class__.List(self)
- elif component == 'union':
- self.content = self.__class__.Union(self)
- else:
- raise SchemaError('Unknown component (%s)' % (component))
- self.content.fromDom(child)
-
- class Restriction(XMLSchemaComponent,\
- RestrictionMarker):
- """<restriction base>
- parents:
- simpleType
- attributes:
- id -- ID
- base -- QName, required or simpleType child
-
- contents:
- annotation?, simpleType?, (enumeration | length |
- maxExclusive | maxInclusive | maxLength | minExclusive |
- minInclusive | minLength | pattern | fractionDigits |
- totalDigits | whiteSpace)*
- """
- attributes = {'id': None,
- 'base': None}
- contents = {'xsd': ['annotation', 'simpleType'] + RestrictionMarker.facets}
- tag = 'restriction'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
- self.facets = None
-
- def getAttributeBase(self):
- return XMLSchemaComponent.getAttribute(self, 'base')
-
- def getTypeDefinition(self, attribute='base'):
- return XMLSchemaComponent.getTypeDefinition(self, attribute)
-
- def getSimpleTypeContent(self):
- for el in self.content:
- if el.isSimple():
- return el
- return None
-
- def fromDom(self, node):
- self.facets = []
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for indx in range(len(contents)):
- component = SplitQName(contents[indx].getTagName())[1]
- if (component == 'annotation') and (not indx):
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- continue
- elif (component == 'simpleType') and (not indx or indx == 1):
- content.append(AnonymousSimpleType(self))
- content[-1].fromDom(contents[indx])
- elif component in RestrictionMarker.facets:
- self.facets.append(contents[indx])
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
- class Union(XMLSchemaComponent,
- UnionMarker):
- """<union>
- parents:
- simpleType
- attributes:
- id -- ID
- memberTypes -- list of QNames, required or simpleType child.
-
- contents:
- annotation?, simpleType*
- """
- attributes = {'id': None,
- 'memberTypes': None}
- contents = {'xsd': ['annotation', 'simpleType']}
- tag = 'union'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def fromDom(self, node):
- self.setAttributes(node)
- contents = self.getContents(node)
- content = []
-
- for indx in range(len(contents)):
- component = SplitQName(contents[indx].getTagName())[1]
- if (component == 'annotation') and (not indx):
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- elif (component == 'simpleType'):
- content.append(AnonymousSimpleType(self))
- content[-1].fromDom(contents[indx])
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
- self.content = tuple(content)
-
- class List(XMLSchemaComponent,
- ListMarker):
- """<list>
- parents:
- simpleType
- attributes:
- id -- ID
- itemType -- QName, required or simpleType child.
-
- contents:
- annotation?, simpleType?
- """
- attributes = {'id': None,
- 'itemType': None}
- contents = {'xsd': ['annotation', 'simpleType']}
- tag = 'list'
-
- def __init__(self, parent):
- XMLSchemaComponent.__init__(self, parent)
- self.annotation = None
- self.content = None
-
- def getItemType(self):
- return self.attributes.get('itemType')
-
- def getTypeDefinition(self, attribute='itemType'):
- """
- return the type refered to by itemType attribute or
- the simpleType content. If returns None, then the
- type refered to by itemType is primitive.
- """
- tp = XMLSchemaComponent.getTypeDefinition(self, attribute)
- return tp or self.content
-
- def fromDom(self, node):
- self.annotation = None
- self.content = None
- self.setAttributes(node)
- contents = self.getContents(node)
- for indx in range(len(contents)):
- component = SplitQName(contents[indx].getTagName())[1]
- if (component == 'annotation') and (not indx):
- self.annotation = Annotation(self)
- self.annotation.fromDom(contents[indx])
- elif (component == 'simpleType'):
- self.content = AnonymousSimpleType(self)
- self.content.fromDom(contents[indx])
- break
- else:
- raise SchemaError('Unknown component (%s)' % (i.getTagName()))
-
-
- class AnonymousSimpleType(SimpleType,\
- SimpleMarker,\
- LocalMarker):
- """<simpleType>
- parents:
- attribute, element, list, restriction, union
- attributes:
- id -- ID
-
- contents:
- annotation?, (restriction | list | union)
- """
- required = []
- attributes = {'id': None}
- tag = 'simpleType'
-
-
- class Redefine:
- """<redefine>
- parents:
- attributes:
-
- contents:
- """
- tag = 'redefine'
-
-
- ###########################
- ###########################
-
-
- if sys.version_info[:2] >= (2, 2):
- tupleClass = tuple
- else:
- import UserTuple
- tupleClass = UserTuple.UserTuple
-
-
- class TypeDescriptionComponent(tupleClass):
- """Tuple of length 2, consisting of
- a namespace and unprefixed name.
- """
- def __new__(typ, args):
- """args -- (namespace, name)
- Remove the name's prefix, irrelevant.
- """
- if len(args) != 2:
- raise TypeError('expecting tuple (namespace, name), got %s' % args)
- elif args[1].find(':') >= 0:
- args = (args[0], SplitQName(args[1])[1])
- return tuple.__new__(typ, args)
-
- def getTargetNamespace(self):
- return self[0]
-
- def getName(self):
- return self[1]
|