diff --git a/XMLSchema.py b/XMLSchema.py index abd89ac..b13c77c 100755 --- a/XMLSchema.py +++ b/XMLSchema.py @@ -14,7 +14,7 @@ ident = "$Id$" -import types, weakref, sys +import types, weakref, sys, warnings from Namespaces import XMLNS from Utility import DOM, DOMException, Collection, SplitQName, basejoin from StringIO import StringIO @@ -50,6 +50,9 @@ def GetSchema(component): 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 @@ -120,16 +123,17 @@ class SchemaReader: """ return self.loadFromStream(StringIO(data)) - def loadFromURL(self, url): + 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 = XMLSchema() + schema = schema or XMLSchema() schema.setBaseUrl(url) schema.load(reader) self.__setIncludes(schema) @@ -1009,6 +1013,9 @@ class XMLSchema(XMLSchemaComponent): schema -- schema instance _imported_schemas """ + print "XMLSchema(%s) ADD IMPORT SCHEMA: %s" \ + %(self.targetNamespace, schema.targetNamespace) + if not isinstance(schema, XMLSchema): raise TypeError, 'expecting a Schema instance' if schema.targetNamespace != self.targetNamespace: @@ -1115,7 +1122,6 @@ class XMLSchema(XMLSchemaComponent): self.setAttributes(node) self.targetNamespace = self.getTargetNamespace() - for childNode in self.getContents(node): component = SplitQName(childNode.getTagName())[1] @@ -1144,26 +1150,36 @@ class XMLSchema(XMLSchemaComponent): v._parent = weakref.ref(self) getattr(self,collection)[k] = v else: - print "Warning: Not keeping schema component." - + 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 - - if not self.getImportSchemas().has_key(import_ns) and \ - tp.getAttribute('schemaLocation'): - self.addImportSchema(tp.getSchema()) - + 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 + tp.loadSchema(schema) + else: + tp._schema = schema + + if self.getImportSchemas().has_key(import_ns): + 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': - # redefine not implemented yet - pass + warnings.warn('redefine is ignored') elif component == 'annotation': - # annotation not implemented yet - pass + warnings.warn('annotation is ignored') elif component == 'attribute': tp = AttributeDeclaration(self) tp.fromDom(childNode) @@ -1195,7 +1211,37 @@ class XMLSchema(XMLSchemaComponent): else: break -# indx += 1 +# slocd = SchemaReader.namespaceToSchema +# +# print "XMLSchema(%d): %s" %(id(self), self.targetNamespace) +# +# for node in imports: +# tp = self.__class__.Import(self) +# tp.fromDom(node) +# +# import_ns = tp.getAttribute('namespace') or \ +# self.__class__.empty_namespace +# +# print "" %import_ns +# +# schema = slocd.get(import_ns) +# if schema is None: +# schema = XMLSchema() +# slocd[import_ns] = schema +# tp.loadSchema(schema) +# else: +# tp._schema = schema +# +# if self.getImportSchemas().has_key(import_ns): +# warnings.warn(\ +# 'Detected multiple imports of the namespace "%s",'+ +# 'may cause problems if they have different schemaLocations.' %import_ns +# ) +# raise RuntimeError, 'hi' +# +# self.addImportSchema(schema) +# self.imports[import_ns] = tp + class Import(XMLSchemaComponent): """ @@ -1244,6 +1290,7 @@ class XMLSchema(XMLSchemaComponent): 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: @@ -1254,6 +1301,16 @@ class XMLSchema(XMLSchemaComponent): 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 + reader.loadFromURL(self.attributes.get('schemaLocation'), schema) class Include(XMLSchemaComponent):