# core classes import layer import types import urlparse import string import os import sys import traceback import re import indNorm import XMLSchemaElt import XMLSchema import XML import PyLTXML import SchemaFiles AST='anySimpleType' syspat=re.compile("^[^[]* (SYSTEM|PUBLIC) ") intpat=re.compile("^[^[]*\[([^\001]*)\]") class SSchema(layer.factory): useDTD=0 prepared=0 current=None # the Schema being built targetNS=0 # the target namespace thereof rebuilding=0 def __init__(self,filename=None,useDump=0): # TODO: use the base property in the appropriate infoset if ((not filename) or (not urlparse.urlparse(filename)[0])): cwd=string.replace(os.getcwd(),'\\','/')+'/' if cwd[1]==':': cwd='file:///'+cwd self.base=cwd else: self.base=filename self.fileNames=[self.base] self.schemaStack=[] self.eltStack=[] self.schemas={} self.unprocessedImports={} self.processingInclude=0 self.inputFileMap={} self.losingNamespaces={} self.knownComps={} self.losers=[] self.openNow=[] self.allowedNamespaces=[] self.checkingSchema=0 home='.' for p in sys.path: if os.path.isfile("%s/%s"%(p or '.','XMLSchema.dtd')): home=p or '.' break home = os.path.abspath(home) home=string.replace(home,"\\","/") if home[1]==':': home='file:///'+home self.home=home if useDump: self.initFromDump("%s/nndump.xml"%home) def initFromDump(self,dumpFileName): self.prepare() self.rebuilding=1 rds=indNorm.fromIndFile(dumpFileName,self.psviConstruct) for nsi in rds.schemaInformation: if nsi.schemaNamespace: # xsi is skipped if self.schemas.has_key(nsi.schemaNamespace): s=self.schemas[nsi.schemaNamespace] else: s=Schema(self,None) s.targetNS=s.targetNamespace=nsi.schemaNamespace self.schemas[nsi.schemaNamespace]=s s.prepared=1 for c in nsi.components: if c.foundWhere: if getattr(s,c.foundWhere).has_key(c.name): if not ((c.name is None) and isinstance(c,XMLSchema.Group)): print ('oops',s,c,c.name) else: getattr(s,c.foundWhere)[c.name]=c self.rebuilding=0 self.current=None self.targetNS=0 def fromFile(self,filename,targetNS,why,btlist,ne,useDTD=0,keepGoing=0): # if not factory: # factory=newFactory(filename) # factory.targetNS=targetNS if useDTD: self.useDTD=1 elif self.useDTD: useDTD=1 schema=None if self.targetNS!=0: # we save the defaults in case an d schema changes them self.schemaStack[0:0]=[(self.current,self.targetNS, self.allowedNamespaces, self.processingInclude, self.current and (self.current.errors, self.current.elementFormDefault, self.current.attributeFormDefault, self.current.blockDefault, self.current.finalDefault, self.current.xrpr))] # if targetNS!=self.current.targetNS: # if self.schemas.has_key(targetNS): # self.current=self.schemas[targetNS] # else: # self.current=None self.processingInclude=(why=='include' or why=='redefine') if self.current: self.current.errors=0 self.targetNS=targetNS fullFile=filename layErr=None self.fileNames[0:0]=[fullFile] if useDTD: vres=0 sdoc=1 try: f=PyLTXML.Open(fullFile,PyLTXML.NSL_read|PyLTXML.NSL_read_namespaces) if f is not None: dts=f.doctype.doctypeStatement if dts is not None and syspat.match(dts): # let them use their own doctype ff=None fake=None else: intDecls="" if dts is not None: mres=intpat.match(dts) if mres: intDecls=mres.group(1) prefs=[] scpFound=0 b=PyLTXML.GetNextBit(f) while (b and b.type not in ('start','empty')): if b.type=='bad': b=None break b=PyLTXML.GetNextBit(f) if b is None: sys.stderr.write("%s has no elements???\n"%fullFile) raise PyLTXML.error for (key,val) in b.item.nsdict.items(): if val==XMLSchema.XMLSchemaNS: scpFound=1 scp=key elif key=='xml' and val==XMLSchema.XMLNS: continue else: prefs.append(key) if not scpFound: sys.stderr.write("document element of %s is not in namespace %s\n"%(fullFile,XMLSchema.XMLSchemaNS)) raise PyLTXML.error if scp!='xs': if scp: pref="%s:"%scp pds="\n\n"%(scp,scp) else: pref="" pds="\n\n" else: pds="" pref="xs:" ns="" for p in prefs: if p: ns=ns+"\n"%(pref,p) if pds or ns or intDecls: fake1="\n"%(ns, intDecls) fake=fake1+fake2+fake3 else: fake="\n"%(pref, self.home) fake=fake+"<%sschema/>"%pref ff=PyLTXML.OpenString(fake, PyLTXML.NSL_read|PyLTXML.NSL_read_namespaces) if ff or not fake: try: res=layer.factory.fromFile(self,schemaEltDispatch, {"finalDefault":"ignore", "blockDefault":"ignore", "elementFormDefault":"ignore", "attributeFormDefault":"ignore"}, lookup,"instance","variable",None, XMLSchema.XMLSchemaNS, fullFile, (XMLSchema.XMLSchemaNS,"schema"),ff) except layer.LayerError,layErr: res=None else: res=None else: res=None except PyLTXML.error: res=None else: # Use dumped/reloaded schema for schemas sdoc=SchemaFiles.safeReadXML(fullFile,ne,"schema",btlist) res=None vres=0 if sdoc is not None: selt=sdoc.documentElement if (selt.localName=='schema' and selt.namespaceName==XMLSchema.XMLSchemaNS): if selt.attributes.has_key((None,'targetNamespace')): ntns=selt.attributes[(None,'targetNamespace')].normalizedValue else: ntns=None self.allowedNamespaces=[XMLSchema.XMLSchemaNS,ntns] else: # will fail lower down anyway ntns=0 if ntns in (XMLSchema.XMLSchemaNS, XMLSchema.XMLSchemaInstanceNS,XMLSchema.XMLNS): ne.addAttr('outcome','redundant') schema=self.schemas[selt.attributes[(None,'targetNamespace')].normalizedValue] else: oerrs=self.errors stns=self.targetNS self.targetNS=ntns # so the doSchemaLocs will push slerrs=SchemaFiles.doSchemaLocs(selt,self.sfors,ne,0, filename,None,None, useDTD,keepGoing) self.targetNS=stns self.checkingSchema=1 vres=XMLSchema.validate(selt,self.sfors)+slerrs-oerrs self.checkingSchema=0 if ((not vres) or keepGoing): try: res=layer.factory.fromFile(self,schemaEltDispatch, {"finalDefault":"ignore", "blockDefault":"ignore", "elementFormDefault":"ignore", "attributeFormDefault":"ignore"}, lookup,"instance","variable",None, XMLSchema.XMLSchemaNS, None, (XMLSchema.XMLSchemaNS,"schema"),None, sdoc.documentElement) except layer.LayerError,layErr: pass if ((sdoc is None) or ((schema is None) and ((not isinstance(res,XMLSchema.schemaElt)) or vres))): xe=XML.Element("notASchema") xe.addAttr('filename',fullFile) if layErr: xe.addAttr('lowLevelErrorMsg',layErr) if vres: xe.addAttr('errors','%s'%vres) ne.children.append(xe) if res is not None: schema=res.component vres=vres+schema.errors if vres: schema.buggy=1 schema.locations.append(fullFile) else: self.losers.append(fullFile) # schema is a an instance of schema, if present self.fileNames=self.fileNames[1:] if self.schemaStack: self.current=self.schemaStack[0][0] (self.current,self.targetNS, self.allowedNamespaces, self.processingInclude, currentStuff) = self.schemaStack[0] if self.current: (self.current.errors, self.current.elementFormDefault, self.current.attributeFormDefault, self.current.blockDefault, self.current.finalDefault, self.current.xrpr)=currentStuff self.schemaStack=self.schemaStack[1:] # elif hasattr(self,'sfors') and self.sfors: # self.current=self.sfors # self.targetNS=self.current.targetNS else: self.current=None self.targetNS=0 return schema def prepare(self): # before we do anything serious, check if we need to # bootstrap the schema for schema if self.schemas.has_key(XMLSchema.XMLSchemaNS): # we're validating a schema with a (purported) schema for schemas, # or we're running useDTD=0 sfors=self.schemas[XMLSchema.XMLSchemaNS] self.sfors=sfors if ((not sfors.typeTable.has_key('string')) or (not sfors.typeTable['string'].__dict__.has_key('basetype')) or (sfors.typeTable['string'].basetype is None) or sfors.typeTable['string'].basetype.name is not AST): # need the ab-initio types sfors.targetNS=XMLSchema.XMLSchemaNS self.current=sfors self.targetNS=XMLSchema.XMLSchemaNS sfors.doBuiltIns(self) else: self.initSforS() self.sfors.nsdict={'xs':XMLSchema.XMLSchemaNS} sforsi=Schema(self,None) self.schemas[XMLSchema.XMLSchemaInstanceNS]=sforsi self.sforsi=sforsi sforsi.targetNS=XMLSchema.XMLSchemaInstanceNS self.current=sforsi self.targetNS=XMLSchema.XMLSchemaInstanceNS sforsi.installInstanceAttrs(self) sforsi.prepared=1 self.current=self.sfors self.targetNS=XMLSchema.XMLSchemaNS ec=0 for sch in self.schemas.values(): ec=ec+sch.errors self.prepared=1 return ec def initSforS(self): sfors=Schema(self,None) self.schemas[XMLSchema.XMLSchemaNS]=sfors self.sfors=sfors sfors.targetNS=XMLSchema.XMLSchemaNS self.current=sfors self.targetNS=XMLSchema.XMLSchemaNS sfors.doBuiltIns(self) def schemaFile(self,filename,base,reason,noRDDL=0): full=urlparse.urljoin(base,filename) if self.inputFileMap.has_key(full): return self.inputFileMap[full] else: self.inputFileMap[full]=None res=self.schemaFile1(full,reason,noRDDL) self.inputFileMap[full]=res return res def schemaFile1(self,full,reason,noRDDL): # sniff the file to see what it's like em=None while full: ffull=full try: f=PyLTXML.Open(full,PyLTXML.NSL_read|PyLTXML.NSL_read_namespaces) except PyLTXML.error: full=None em="couldn't open" break b=PyLTXML.GetNextBit(f) while (b and b.type not in ('start','empty')): if b.type=='bad': b=None break b=PyLTXML.GetNextBit(f) if b is None: sys.stderr.write("%s has no elements???\n"%full) raise PyLTXML.error # PyLTXML.error nsdict=b.item.nsdict if ((not noRDDL) and b.item.llabel=="html" and b.item.nsuri=="http://www.w3.org/1999/xhtml"): # may be RDDL file rddl=0 for (key,val) in nsdict.items(): if val=="http://www.rddl.org/": rddl=1 break if rddl: ne=XML.Element("importAttempt") ne.addAttr('URI',full) ne.addAttr('outcome','RDDL') reason.children.append(ne) b=GetNextBit(f) while b: if ((b.type=='start' or b.type=='empty') and b.item.llabel=="resource" and b.item.nsuri=="http://www.rddl.org/"): # this is somewhat tedious for (p,n) in b.item.nsdict.items(): if n=="http://www.w3.org/1999/xlink": break else: p="" # hack to fail if PyLTXML.GetAttrVal(b.item,"%s:role"%p)==XMLSchema.XMLSchemaNS: newf=PyLTXML.GetAttrVal(b.item,"%s:href"%p) if newf: full=urlparse.urljoin(full,newf) else: em="RDDL resource for W3C XML Schema lacked an xlink:href" full=None break elif b.type=='bad': PyLTXML.Close(f) raise PyLTXML.error b=PyLTXML.GetNextBit(f) else: full=None em="Recognised as RDDL, but no W3C XML Schema resource found" elif b.item.llabel=="schema": if b.item.nsuri==XMLSchema.XMLSchemaNS: PyLTXML.Close(f) return (full,PyLTXML.GetAttrVal(b.item,"targetNamespace")) em="Root was , but not in W3C XML Schema namespace: %s (was %s)"%(XMLSchema.XMLSchemaNS,b.item.nsuri) full=None else: em="Not recognised as W3C XML Schema or RDDL: %s"%b.item.label full=None try: PyLTXML.Close(f) except: pass ne=XML.Element("notASchema") ne.addAttr('filename',ffull) if em: ne.children=[XML.Pcdata(em)] reason.children.append(ne) def checkinSchema(self,namespace,location,base,why,useDTD=0,keepGoing=0, elt=None): ne=XML.Element("schemaDocAttempt") ne.addAttr('source',why) if namespace!=0: ne.addAttr('namespace',namespace) fullLoc=urlparse.urljoin(base,location) ne.addAttr('URI',fullLoc) self.resElt.children.append(ne) including=(why=='include' or why=='redefine') res=None btlist=[] try: lres=self.schemaFile(location,base,ne,including) if lres: (loc,fileTargetNamespace)=lres if (loc in self.openNow or (self.schemas.has_key(namespace) and (loc in self.schemas[namespace].locations))): ne.addAttr('outcome','redundant') # i.e. we've seen this before for this namespace or it's in play now return self.schemas[namespace] if loc in self.losers: ne.addAttr('outcome','failed already') return if (namespace!=0 and namespace!=fileTargetNamespace and ((not including) or fileTargetNamespace)): # allow for chameleon ne.addAttr('outcome', "Failure: targetNamespace mismatch: %s expected, %s found" % (namespace,fileTargetNamespace)) if elt: sa=ne.attrs['source'] sa.value="%s, %s"%(sa.value,whereString(elt.where)) return if loc!=fullLoc: ne.addAttr('trueURI',loc) self.openNow[0:0]=[loc] res=self.fromFile(loc,namespace,why,btlist,ne,useDTD,keepGoing) except: pfe=XML.Element("bug") errstr=string.join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback), '') pfe.children=[XML.Pcdata("validator crash during %s:\n%s"%(why, errstr))] self.resElt.children.append(pfe) self.openNow=self.openNow[1:] if (res is not None) and not res.buggy and not ne.attrs.has_key('outcome'): # last clause is to avoid being fooled by sfors redundancy lower down ne.addAttr('outcome','success') else: if not ne.attrs.has_key('outcome'): ne.addAttr('outcome','failure') for err in btlist: pfe=XML.Element("bug") errstr=string.join(err,'') pfe.children=[XML.Pcdata("validator crash during %s:\n%s"%(why, errstr))] self.resElt.children.append(pfe) return res def tryHardForDecl(self,localName,namespace,kind,schema,item): if ((not self.schemas.has_key(namespace)) or (kind=='element' and not self.schemas[namespace].elementTable.has_key(localName)) or (kind=='attribute' and self.schemas[namespace].attributeTable.has_key(localName))): # first try xsi:schemaLoc # TODO: schemaLoc not allowed after first appearance of NS it 'addresses' if kind=='element': sbs=self.resElt.attrs["target"].value if sbs=='[stdin]': sbs=self.base SchemaFiles.doSchemaLocs(item,schema,self.resElt,0,sbs,None) if (namespace and (not self.schemas.has_key(namespace)) and (not self.losingNamespaces.has_key(namespace))): # now try namespace name (will be cheap if tried before) self.checkinSchema(namespace, namespace, self.base, "new namespace",0,0,item) def psviConstruct(self,name,attrs): rrm=None if XMLSchema.psviIndMap.has_key(name): iClass=XMLSchema.psviIndMap[name] if iClass is None: # means skip it altogether return None if type(iClass)==types.TupleType: # cheat for subclasses types, e.g. SimpleType, KCons rrm=iClass[1].reflectionInMap if iClass[1].__dict__.has_key('reflectedName'): rrn=iClass[1].reflectedName else: rrn=None iClass=iClass[0] else: iClass=XMLSchema.__dict__[name] # should prune all the non-ref'ed IDs out ref=indNorm.av(attrs,'ref') if ref: if self.knownComps.has_key(ref): # print ('known ref',ref) val=self.knownComps[ref] val.reffed=1 return val elif self.sfors.typeTable.has_key(ref): # print ('prim ref',ref) val=self.sfors.typeTable[ref] val.reffed=1 return val elif (ref[0:10]=='xsd..type.' and ref[10]!='_' and self.sfors.typeTable.has_key(ref[10:])): # print ('type ref',ref) val=self.sfors.typeTable[ref[10:]] val.reffed=1 else: # put in in identified anyway, right thing will happen # print ('unknown ref',ref) val=iClass(self,None) self.knownComps[ref]=val val.reffed=1 name=indNorm.av(attrs,'name') if name is not None: val.name=name val.targetNamespace=indNorm.av(attrs,'tns') return val else: id=indNorm.av(attrs,'id') if id: if self.knownComps.has_key(id): # print ('preknown comp',id) # there were forward references to this val=self.knownComps[id] val.name=val.targetNamespace=None else: # print ('unknown comp',id,val,val.__dict__.has_key('variety')) val=iClass(self,None) self.knownComps[id]=val else: val=iClass(self,None) if rrm is not None: val.reflectionInMap=rrm if rrn: val.reflectedName=rrn if iClass is XMLSchema.ComplexType: val.saveCTC=XMLSchema.currentCTC XMLSchema.currentCTC=val return val class dumpDummy: reffed=0 rebuild=None foundWhere=None def __init__(self,sschema,xrpr): pass class DumpedSchema(dumpDummy): pass class namespaceSchemaInformation(dumpDummy): schemaNamespace=None class contentType(dumpDummy): model=None class namespaceConstraint(dumpDummy): pass class valueConstraint(dumpDummy): pass class xpathTemp(dumpDummy): pass class schemaDocument(dumpDummy): pass class Schema: annotations=[] buggy=0 prepared=0 errors=0 elementFormDefault=attributeFormDefault=finalDefault=blockDefault=None def __init__(self,sschema,xrpr): # note that unlike other components, this one is built _before_ processing # the children of the elt it corresponds to self.xrpr=xrpr self.sschema=sschema self.errors=0 self.locations=[] if xrpr is not None: # these are needed during schema accumulation self.maybeSetVar('targetNS','targetNamespace',None) self.maybeSetVar('elementFormDefault','elementFormDefault','unqualified') self.maybeSetVar('attributeFormDefault','attributeFormDefault', 'unqualified') self.maybeSetVar('finalDefault','finalDefault','') self.maybeSetVar('blockDefault','blockDefault','') if self.targetNS=="": self.error("Empty string is not allowed as value of targetNamespace", xrpr.elt) self.targetNS=None if (sschema.processingInclude and self.targetNS!=sschema.targetNS and (not self.targetNS)): # chameleon include, OK self.targetNS=sschema.targetNS sschema.processingInclude=2 sschema.targetNS=self.targetNS if sschema.schemas.has_key(self.targetNS): shouldnt('oldcopy') oldSchema=sschema.schemas[self.targetNS] # use real tables, we're ephemeral self.locations=oldSchema.locations # broken sschema.current=oldSchema self.typeTable=oldSchema.typeTable self.elementTable=oldSchema.elementTable self.attributeTable=oldSchema.attributeTable self.groupTable=oldSchema.groupTable self.attributeGroupTable=oldSchema.attributeGroupTable self.vTypeTable=oldSchema.vTypeTable self.vElementTable=oldSchema.vElementTable self.vAttributeTable=oldSchema.vAttributeTable self.vGroupTable=oldSchema.vGroupTable self.vAttributeGroupTable=oldSchema.vAttributeGroupTable # copy defaults (they've been saved, will be restored) oldSchema.elementFormDefault=self.elementFormDefault oldSchema.attributeFormDefault=self.attributeFormDefault oldSchema.blockDefault=self.blockDefault oldSchema.finalDefault=self.finalDefault return else: sschema.schemas[self.targetNS]=self sschema.current=self # either we're the first for this NS, or we're the FIRST self.typeTable={} self.elementTable={} self.attributeTable={} self.groupTable={} self.attributeGroupTable={} self.keyUniqueTable={} self.vTypeTable=VMapping(self, "typeTable") self.vElementTable=VMapping(self, "elementTable") self.vAttributeTable=VMapping(self, "attributeTable") self.vGroupTable=VMapping(self, "groupTable") self.vKeyUniqueTable=VMapping(self, "keyUniqueTable") self.vAttributeGroupTable=VMapping(self, "attributeGroupTable") def __str__(self): types=map(str,self.typeTable.values()) groups=map(str, self.groupTable.values()) attributeGroups=map(str, self.attributeGroupTable.values()) elts=map(str,self.elementTable.values()) attrs=map(str,self.attributeTable.values()) return "{Target:%s}{Types:%s}{Groups:%s}{AttrGroups:%s}{Elements:%s}{Attributes:%s}"%(self.targetNS,string.join(types,''),string.join(groups,''),string.join(attributeGroups,''),string.join(elts,''),string.join(attrs,'')) def maybeSetVar(self,varName,attrName,default): if self.xrpr.elt.hasAttrVal(attrName): setattr(self,varName,self.xrpr.elt.attrVal(attrName)) else: setattr(self,varName,default) def doBuiltIns(self,sschema): self.doAbInitios(sschema) # TODO: implement fixed facets for (bitn,basen,facets) in XMLSchema.builtinTypeNames: fake=XMLSchema.simpleTypeElt(sschema,None) fake.name=bitn fake.restriction=XMLSchema.restrictionElt(sschema,None) fake.restriction.init(None) fake.init(None) fake.component.basetypeName=QName(None,basen,XMLSchema.XMLSchemaNS) fake.component.variety='atomic' bit=fake.restriction.component bit.rootName=fake.component.basetype.rootName self.typeTable[bitn]=fake.component for (fc,fv) in facets: nf=fc(sschema,None) fake.restriction.facets[fc.name]=nf nf.value=fv for (bitn,basen) in XMLSchema.builtinLists: fake=XMLSchema.simpleTypeElt(sschema,None) fake.name=bitn fake.list=XMLSchema.listElt(sschema,None) fake.list.init(None) fake.init(None) fake.component.basetype=XMLSchema.urSimpleType fake.component.variety='list' fake.list.component.itemtypeName=QName(None,basen,XMLSchema.XMLSchemaNS) self.typeTable[bitn]=fake.component ap=XMLSchema.Particle(sschema,None, XMLSchema.AnyAny(sschema,None),None) ap.term.processContents='lax' ap.occurs=(0,None) if not XMLSchema.urType.model.term.particles: XMLSchema.urType.model.term.particles.append(ap) au=XMLSchema.AttributeUse(sschema,None, XMLSchema.AnyAny(sschema,None),'optional') au.attributeDeclaration.processContents='lax' XMLSchema.urType.attributeDeclarations={'#any':au} else: shouldnt('dbl ur') self.typeTable['anyType']=XMLSchema.urType XMLSchema.urSimpleType.schema=XMLSchema.urType.schema=self XMLSchema.urSimpleType.sschema=XMLSchema.urType.sschema=sschema ws=XMLSchema.Whitespace(sschema,None) ws.value="preserve" XMLSchema.urSimpleType.facets['whiteSpace']=ws self.typeTable['anySimpleType']=XMLSchema.urSimpleType def doAbInitios(self,sschema): wsf1=XMLSchema.Whitespace(sschema,None) wsf1.value="collapse" wsf1.fixed=1 wsf2=XMLSchema.Whitespace(sschema,None) wsf2.value="preserve" for (ain,ait) in XMLSchema.abInitioTypes: aiti=ait(sschema) aiti.rootName=ain aiti.basetype=XMLSchema.urSimpleType if ain=='string': aiti.facets['whiteSpace']=wsf2 else: aiti.facets['whiteSpace']=wsf1 self.typeTable[ain]=aiti def installInstanceAttrs(self,sschema): sschema.eltStack=['a'] # hack for (attrn,basen) in instanceAttrs: fake=XMLSchema.attributeElt(sschema,None) fake.name=attrn fake.type=basen fake.init(None) fake.component.typeDefinitionName=XMLSchema.QName(None,basen, XMLSchema.XMLSchemaNS) self.attributeTable[attrn]=fake.component for (attrn,itemn) in instanceLists: fake=XMLSchema.attributeElt(sschema,None) fake.name=attrn fake.simpleType=XMLSchema.simpleTypeElt(sschema,None) fake.simpleType.list=XMLSchema.listElt(sschema,None) fake.simpleType.list.init(None) fake.simpleType.list.component.itemtypeName=XMLSchema.QName(None,itemn, XMLSchema.XMLSchemaNS) fake.simpleType.init(None) fake.simpleType.component.variety='list' fake.simpleType.component.basetype=XMLSchema.urSimpleType fake.init(None) self.attributeTable[attrn]=fake.component sschema.eltStack=[] # hack ap=XMLSchema.Particle(sschema,None, XMLSchema.AnyAny(sschema,None),None) ap.term.processContents='lax' ap.occurs=(0,None) def prepare(self): if self.prepared: return # try to touch everything that might cause errors cool=1 for i in self.typeTable.values(): if isinstance(i,XMLSchema.Type): cool=i.prepare() and cool for tab in (self.elementTable, self.attributeTable, self.groupTable, self.attributeGroupTable): for i in tab.values(): cool=i.prepare() and cool self.prepared=1 return cool def error(self,message,elt=None,warning=0,extras=None): # should have code argument to identify SRC/COS if warning: ee=XML.Element("schemaWarning") else: ee=XML.Element("schemaError") if self.sschema.prepared: ee.addAttr("phase","instance") else: ee.addAttr("phase","schema") if not warning: self.errors=self.errors+1 if elt is not None: where(ee,elt.where) ee.children=[XML.Pcdata(message)] if extras: ee.children=ee.children+extras self.sschema.resElt.children.append(ee) def newComponent(self,table,kind,comp): if comp is None: return if comp.name: if table.has_key(comp.name): comp.schema.error("attempt to overwrite %s {%s}%s, ignored"%(kind, self.targetNS, comp.name), comp.xrpr.elt, 1) else: table[comp.name]=comp comp.qname=QName(None,comp.name,self.targetNS) else: shouldnt('nc: %s'%comp) instanceAttrs=[('nil','boolean'),('type','QName'), ('noNamespaceSchemaLocation','anyURI')] instanceLists=[('schemaLocation','anyURI')] class Component: prepared=0 reffed=0 name=None targetNamespace=None idCounter=1 annotation=None def __init__(self,sschema,xrpr,ns='ns'): self.sschema=sschema if sschema is not None: self.schema=sschema.current if ns=='ns' and (self.schema is not None) and not sschema.rebuilding: self.targetNamespace=self.schema.targetNS self.xrpr=xrpr if xrpr is not None: if xrpr.__dict__.has_key('name'): self.name=xrpr.name if xrpr.__dict__.has_key('annot') and xrpr.annot: if len(xrpr.annot)!=1: error('shouldnt '+str(len(xrpr.annot))) self.annotation=xrpr.annot[0].component if xrpr.elt is not None: ooba=filter(lambda a:a.nsuri, xrpr.elt.actualAttrs) if ooba: ooba=map(lambda a:a.elt,ooba) if self.annotation is None: self.annotation=XMLSchema.Annotation(self.sschema,None) if not self.annotation.attrs: self.annotation.attrs=ooba else: self.annotation.attrs=self.annotation.attrs.append(ooba) self.id=self.idCounter Component.idCounter=self.id+1 def __copy__(self): # cribbed from copy.py:_copy_inst_ y = _EmptyClass() y.__class__ = self.__class__ state = self.__dict__ y.__dict__.update(state) return y def error(self,message,warning=0,extras=None): if self.xrpr is None: elt=None else: elt=self.xrpr.elt self.schema.error(message,elt,warning,extras) def rebuild(self): # called after reln's plugged in during initFromDump map=self.reflectionInMap if map: for (reflName,vtype,nillable,attr) in map: if vtype=='boolean': setattr(self,attr,getattr(self,attr)=='true') elif vtype=='integer': setattr(self,attr,string.atoi(getattr(self,attr))) elif vtype=='list': # always list of atoms encoded as string val=getattr(self,attr) if val is None: nval=[] else: nval=string.split(val) setattr(self,attr,nval) elif vtype=='aspecial': getattr(self,reflName+"Rebuild")(getattr(self,reflName)) # must work by side-effect, must precede pointer check elif vtype=='especial' or vtype=='esspecial': getattr(self,reflName[0]+"Rebuild")(getattr(self,reflName[0])) def scopeRebuild(self,val): # shared by Element and Attribute -- will always be a pointer if val=='': self.scope=None elif val=='global': self.scope=val else: # warning -- global variable hack!!! self.scope=XMLSchema.currentCTC def valueConstraintRebuild(self,val): # shared by Element, Attribute and AttributeUse if val is not None: self.valueConstraint=(val.variety,val.value) class _EmptyClass: pass class QName: # either QName(qname, item, sschema) or QName(prefix, local, uri) or # QName(qname, nsdict, sschema) (doesn't happen????) def __init__(self, arg1, arg2, arg3): # print "QName(%s,%s,%s),%s,%s" % (arg1, arg2, arg3,isinstance(arg2,layer.Mapper),isinstance(arg2,layer.Mapper) and arg3.processingInclude) if isinstance(arg2,layer.Mapper): (self.prefix,self.local) = splitQName(arg1) if self.prefix or not arg3.processingInclude==2: self.uri=arg2.lookupPrefix(self.prefix) else: # chameleon include fix self.uri=arg3.targetNS if self.prefix and not self.uri: self.uri="error: prefixWasNotDeclared" elif type(arg2) is types.DictType: (self.prefix,self.local) = splitQName(arg1) if arg2.has_key(self.prefix): self.uri=arg2[self.prefix] elif self.prefix: self.uri="error: prefixWasNotDeclared" else: self.uri=None else: self.prefix = arg1 self.local = arg2 self.uri = arg3 self.pair = (self.uri, self.local) def __str__(self): return str(self.string()) # str is in case we're unicode def __cmp__(self, other): # print "comparing %s and %s" % (self,other) if not isinstance(other, QName): # ??? XXX return -1 return cmp(self.pair, other.pair) def __hash__(self): return hash(self.pair) def string(self): # may be Unicode return "%s{%s}:%s" % (self.prefix or "",self.uri,self.local) def splitQName(qname): n=string.find(qname,':') if n>-1: prefix=qname[0:n] local=qname[n+1:] else: prefix=None local=qname return (prefix, local) class VMapping: def __init__(self, schema, tablename): self.schema = schema self.tablename = tablename def findSchema(self, uri, local): if uri == self.schema.targetNS: return self.schema # look it up if self.schema.sschema.schemas.has_key(uri): return self.schema.sschema.schemas[uri] else: return None def has_key(self, key): if key is None: return 0 if not isinstance(key, QName): shouldnt('nk: '+str(key)) return 0 s = self.findSchema(key.uri, key.local) if s is None: # not an error to check, we'll record one error when we really go for it return 0 return s.__dict__[self.tablename].has_key(key.local) def __getitem__(self, key): s = self.findSchema(key.uri, key.local) if s is None: self.schema.error("unknown namespace for %s for %s" % (key.uri, key.local)) return None return s.__dict__[self.tablename][key.local] class SchemaError(Exception): pass def shouldnt(msg): error("Shouldn't happen "+msg) def error(msg): raise SchemaError,msg def where(elt,w): if w and w[3]!=0: if w[0]!='unnamed entity': elt.addAttr('entity',w[0]) elt.addAttr('line',str(w[1])) elt.addAttr('char',str(w[2])) elt.addAttr('resource',w[3]) def whereString(w): if w and w[3]!=0: return ("in %s at line %d char %d of %s" % w) else: return "location unknown" schemaEltDispatch= {("schema","element"):("group","dds"), ("group","element"):("group","model"), ("all","element"):("group","model"), ("choice","element"):("group","model"), ("sequence","element"):("group","model"), ("complexType","element"):"error", ("complexType","any"):"error", ("schema","group"):("group","dds"), ("redefine","group"):("group","dds"), ("restriction","group"):"self", ("restriction","all"):"self", ("restriction","choice"):"self", ("restriction","sequence"):"self", ("extension","group"):"self", ("extension","all"):"self", ("extension","choice"):"self", ("extension","sequence"):"self", ("complexType","group"):"self", ("complexType","all"):"self", ("complexType","choice"):"self", ("complexType","sequence"):"self", "complexContent":"self", "simpleContent":"self", ("group","group"):("group","model"), ("group","all"):("group","model"), ("group","choice"):("group","model"), ("group","sequence"):("group","model"), ("all","group"):("group","model"), ("all","all"):("group","model"), ("all","choice"):("group","model"), ("all","sequence"):("group","model"), ("choice","group"):("group","model"), ("choice","all"):("group","model"), ("choice","choice"):("group","model"), ("choice","sequence"):("group","model"), ("sequence","group"):("group","model"), ("sequence","all"):("group","model"), ("sequence","choice"):("group","model"), ("sequence","sequence"):("group","model"), "any":("group","model"), "anyAttribute":("group","attrs"), ("attributeGroup","attribute"):("group","attrs"), ("restriction","attribute"):("group","attrs"), ("extension","attribute"):("group","attrs"), ("complexType","attribute"):("group","attrs"), ("schema","attribute"):("group","dds"), "annotation":("group","annot"), # broken for schema "documentation":("group","documentation"), "appinfo":("group","appinfo"), "key":("group","keys"), "keyref":("group","keyrefs"), "unique":("group","uniques"), ("attributeGroup","attributeGroup"):("group","attrs"), ("complexType","attributeGroup"):("group","attrs"), ("restriction","attributeGroup"):("group","attrs"), ("extension","attributeGroup"):("group","attrs"), ("schema","attributeGroup"):("group","dds"), ("redefine","attributeGroup"):("group","dds"), ("element","complexType"):"self", ("element","simpleType"):"self", ("attribute","simpleType"):"self", "restriction":"self", "extension":"self", ("restriction","simpleType"):"self", "list":"self", ("list","simpleType"):"self", "union":"self", ("union","simpleType"):("group","subTypes"), ("schema","complexType"):("group","dds"), ("redefine","complexType"):("group","dds"), ("schema","simpleType"):("group","dds"), ("redefine","simpleType"):("group","dds"), "maxInclusive":("group","facets"), "maxExclusive":("group","facets"), "minInclusive":("group","facets"), "minExclusive":("group","facets"), "enumeration":("group","facets"), "fractionDigits":("group","facets"), "totalDigits":("group","facets"), "length":("group","facets"), "maxLength":("group","facets"), "minLength":("group","facets"), "pattern":("group","facets"), "whiteSpace":("group","facets"), "field":("group","fields"), "selector":"self" } def lookup(eltName): if XMLSchema.eltClasses.has_key(eltName): return XMLSchema.eltClasses[eltName] else: return userClass class userClass: def __init__(self,sschema,elt): self.elt=elt self.sschema=sschema # $Log: XMLSchemaCore.py,v $ # Revision 1.10 2002/06/20 17:08:09 ht # make booleans be booleans, # stop trying (and failing :-( to rename nillable on the way in # # Revision 1.9 2002/06/15 18:57:49 ht # switch to reflectionInMap for rebuilding # # Revision 1.8 2002/06/13 21:03:08 ht # get current complex type stack working properly # # Revision 1.7 2002/06/12 18:46:20 ht # restructure in preparation for allowing either normal form to be reflected # # Revision 1.6 2002/06/11 13:15:28 ht # dump non-global, non-None scope as local, rebuild properly # # Revision 1.5 2002/05/28 16:47:48 ht # fix aspecial rebuilding, # change especial rebuilding to avoid trashing reflection method, # rebuild scope # # Revision 1.4 2002/05/27 22:30:25 ht # remove debuggin print, # actually _use_ reloaded ind dump, # handle esspecial properly # # Revision 1.3 2002/05/27 20:17:54 ht # individual normal form reload barely working, debugging prints still in # # Revision 1.2 2002/05/27 16:11:44 ht # working on new restore # # Revision 1.1 2002/05/25 21:55:45 ht # split more off from XMLSchema.py #