|
- # 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.
-
- import string, types, base64, re
- from Utility import DOM, Collection
- from StringIO import StringIO
-
-
- class SchemaReader:
- """A SchemaReader creates XMLSchema objects from urls and xml data."""
-
- def loadFromStream(self, file):
- """Return an XMLSchema instance loaded from a file object."""
- document = DOM.loadDocument(file)
- schema = XMLSchema()
- schema.load(document)
- return schema
-
- def loadFromString(self, data):
- """Return an XMLSchema instance loaded from an xml string."""
- return self.loadFromStream(StringIO(data))
-
- def loadFromURL(self, url):
- """Return an XMLSchema instance loaded from the given url."""
- document = DOM.loadFromURL(url)
- schema = XMLSchema()
- schema.location = url
- schema.load(document)
- return schema
-
- def loadFromFile(self, filename):
- """Return an XMLSchema instance loaded from the given file."""
- file = open(filename, 'rb')
- try: schema = self.loadFromStream(file)
- finally: file.close()
- return schema
-
-
- class XMLSchema:
- # 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 realXMLSchema:
- """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)."""
- def __init__(self):
- self.simpleTypes = Collection(self)
- self.complexTypes = Collection(self)
- self.attributes = Collection(self)
- self.elements = Collection(self)
- self.attrGroups = Collection(self)
- self.idConstraints=None
- self.modelGroups = None
- self.notations = None
- self.extensions = []
-
- targetNamespace = None
- attributeFormDefault = 'unqualified'
- elementFormDefault = 'unqualified'
- blockDefault = None
- finalDefault = None
- location = None
- version = None
- id = None
-
- def load(self, document):
- if document.nodeType == document.DOCUMENT_NODE:
- schema = DOM.getElement(document, 'schema', None, None)
- else:
- schema = document
- if schema is None:
- raise SchemaError('Missing <schema> element.')
-
- self.namespace = namespace = schema.namespaceURI
- if not namespace in DOM.NS_XSD_ALL:
- raise SchemaError(
- 'Unknown XML schema namespace: %s.' % self.namespace
- )
-
- for attrname in (
- 'targetNamespace', 'attributeFormDefault', 'elementFormDefault',
- 'blockDefault', 'finalDefault', 'version', 'id'
- ):
- value = DOM.getAttr(schema, attrname, None, None)
- if attr is not None:
- setattr(self, attrname, value)
-
-
- # Resolve imports and includes here?
- ## imported = {}
- ## while 1:
- ## imports = []
- ## for element in DOM.getElements(definitions, 'import', NS_WSDL):
- ## location = DOM.getAttr(element, 'location')
- ## if not imported.has_key(location):
- ## imports.append(element)
- ## if not imports:
- ## break
- ## for element in imports:
- ## self._import(document, element)
- ## imported[location] = 1
-
- for element in DOM.getElements(schema, None, None):
- localName = element.localName
-
- if not DOM.nsUriMatch(element.namespaceURI, namespace):
- self.extensions.append(element)
- continue
-
- elif localName == 'message':
- name = DOM.getAttr(element, 'name')
- docs = GetDocumentation(element)
- message = self.addMessage(name, docs)
- parts = DOM.getElements(element, 'part', NS_WSDL)
- message.load(parts)
- continue
-
- def _import(self, document, element):
- namespace = DOM.getAttr(element, 'namespace', default=None)
- location = DOM.getAttr(element, 'location', default=None)
- if namespace is None or location is None:
- raise WSDLError(
- 'Invalid import element (missing namespace or location).'
- )
-
- # Sort-of support relative locations to simplify unit testing. The
- # WSDL specification actually doesn't allow relative URLs, so its
- # ok that this only works with urls relative to the initial document.
- location = urllib.basejoin(self.location, location)
-
- obimport = self.addImport(namespace, location)
- obimport._loaded = 1
-
- importdoc = DOM.loadFromURL(location)
- try:
- if location.find('#') > -1:
- idref = location.split('#')[-1]
- imported = DOM.getElementById(importdoc, idref)
- else:
- imported = importdoc.documentElement
- if imported is None:
- raise WSDLError(
- 'Import target element not found for: %s' % location
- )
-
- imported_tns = DOM.getAttr(imported, 'targetNamespace')
- importer_tns = namespace
-
- if imported_tns != importer_tns:
- return
-
- if imported.localName == 'definitions':
- imported_nodes = imported.childNodes
- else:
- imported_nodes = [imported]
- parent = element.parentNode
- for node in imported_nodes:
- if node.nodeType != node.ELEMENT_NODE:
- continue
- child = DOM.importNode(document, node, 1)
- parent.appendChild(child)
- child.setAttribute('targetNamespace', importer_tns)
- attrsNS = imported._attrsNS
- for attrkey in attrsNS.keys():
- if attrkey[0] == DOM.NS_XMLNS:
- attr = attrsNS[attrkey].cloneNode(1)
- child.setAttributeNode(attr)
- finally:
- importdoc.unlink()
-
-
- class Element:
- """Common base class for element representation classes."""
- def __init__(self, name=None, documentation=''):
- self.name = name
- self.documentation = documentation
- self.extensions = []
-
- def addExtension(self, item):
- self.extensions.append(item)
-
-
- class SimpleTypeDefinition:
- """Represents an xml schema simple type definition."""
-
- class ComplexTypeDefinition:
- """Represents an xml schema complex type definition."""
-
- class AttributeDeclaration:
- """Represents an xml schema attribute declaration."""
-
- class ElementDeclaration:
- """Represents an xml schema element declaration."""
- def __init__(self, name, type=None, targetNamespace=None):
- self.name = name
-
- targetNamespace = None
- annotation = None
- nillable = 0
- abstract = 0
- default = None
- fixed = None
- scope = 'global'
- type = None
- form = 0
- # Things we will not worry about for now.
- id_constraint_defs = None
- sub_group_exclude = None
- sub_group_affils = None
- disallowed_subs = None
-
-
-
-
-
-
-
-
-
-
- class AttributeGroupDefinition:
- """Represents an xml schema attribute group definition."""
-
- class IdentityConstraintDefinition:
- """Represents an xml schema identity constraint definition."""
-
- class ModelGroupDefinition:
- """Represents an xml schema model group definition."""
-
- class NotationDeclaration:
- """Represents an xml schema notation declaration."""
-
- class Annotation:
- """Represents an xml schema annotation."""
-
- class ModelGroup:
- """Represents an xml schema model group."""
-
- class Particle:
- """Represents an xml schema particle."""
-
- class WildCard:
- """Represents an xml schema wildcard."""
-
- class AttributeUse:
- """Represents an xml schema attribute use."""
-
-
- class ElementComponent:
- namespace = ''
- name = ''
- type = None
- form = 'qualified | unqualified'
- scope = 'global or complex def'
- constraint = ('value', 'default | fixed')
- nillable = 0
- id_constraint_defs = None
- sub_group_affil = None
- sub_group_exclusions = None
- disallowed_subs = 'substitution, extension, restriction'
- abstract = 0
- minOccurs = 1
- maxOccurs = 1
- ref = ''
-
- class AttributeThing:
- name = ''
- namespace = ''
- typeName = ''
- typeUri = ''
- scope = 'global | local to complex def'
- constraint = ('value:default', 'value:fixed')
- use = 'optional | prohibited | required'
-
- class ElementDataType:
- namespace = ''
- name = ''
- element_form = 'qualified | unqualified'
- attr_form = None
- type_name = ''
- type_uri = ''
- def __init__(self, name, namespace, type_name, type_uri):
- self.namespace = namespace
- self.name = name
- # type may be anonymous...
- self.type_name = type_name
- self.type_uri = type_uri
-
- def checkValue(self, value, context):
- # Delegate value checking to the type of the element.
- typeref = (self.type_uri, self.type_name)
- handler = context.serializer.getType(typeref)
- return handler.checkValue(value, context)
-
- def serialize(self, name, namespace, value, context, **kwargs):
- if context.check_values:
- self.checkValue(value, context)
- # Delegate serialization to the type of the element.
- typeref = (self.type_uri, self.type_name)
- handler = context.serializer.getType(typeref)
- return handler.serialize(self.name, self.namespace, value, context)
-
- def deserialize(self, element, context):
- if element_is_null(element, context):
- return None
- # Delegate deserialization to the type of the element.
- typeref = (self.type_uri, self.type_name)
- handler = context.serializer.getType(typeref)
- return handler.deserialize(element, context)
-
-
-
- def parse_schema(data):
- targetNS = ''
- attributeFormDefault = 0
- elementFormDefault = 0
- blockDefault = ''
- finalDefault = ''
- language = None
- version = None
- id = ''
|