Annotation of xmlschema/applyschema.py, revision 1.74.2.26
1.44 ht 1: # Copyright (C) 2000 LTG -- See accompanying COPYRIGHT and COPYING files
1.24 ht 2: # actually apply a schema to an instance
1.74.2.26! ht 3: # $Id: applyschema.py,v 1.74.2.25 2001/01/03 19:13:19 ht Exp $
1.58 ht 4:
5: # TODO: enforce datatype constraints on xsi:type,
6: # null, (noNamespace)schemaLocation
1.24 ht 7:
1.63 ht 8: from PyLTXML import *
1.74.2.1 richard 9: import XML
10: import XMLInfoset
11: import LTXMLInfoset
1.74.2.2 ht 12: import PSVInfoset
1.58 ht 13: import os
1.41 ht 14: import XMLSchema
1.28 ht 15: import layer
1.3 aqw 16: import sys
1.4 richard 17: import re
1.18 ht 18: import xpath
1.20 ht 19: import types
1.41 ht 20: import string
1.53 ht 21: from urlparse import urljoin
1.58 ht 22: import tempfile
1.62 ht 23: import traceback
1.74.2.2 ht 24: import asInfoset
1.74.2.8 ht 25: import time
1.4 richard 26:
27: whitespace = re.compile("^[ \t\r\n]*$")
1.74.2.12 ht 28: xsi = XMLSchema.XMLSchemaInstanceNS
1.74.2.26! ht 29: vsraw="$Revision: 1.74.2.25 $ of $Date: 2001/01/03 19:13:19 $"
1.40 ht 30: vss=string.split(vsraw)
1.41 ht 31: vs="XSV %s/%s of %s %s"%(string.split(XMLSchema.versionString)[0],
1.40 ht 32: vss[1],vss[5],vss[6])
1.74.2.8 ht 33: dontWarn=1
1.5 richard 34:
1.2 ht 35: def readXML(url):
1.74.2.25 ht 36: if url:
37: doc = LTXMLInfoset.documentFromURI(url)
38: else:
39: file = FOpen(sys.stdin,
40: NSL_read+NSL_read_all_bits+NSL_read_namespaces+
41: NSL_read_no_consume_prolog)
42: doc = LTXMLInfoset.documentFromFile(file)
43: Close(file)
44: return doc
1.2 ht 45:
1.55 ht 46: def validate(element, typedef, schema, eltDecl):
1.58 ht 47: if not hasattr(schema.factory,'errors'):
48: schema.factory.errors=0
1.55 ht 49: validateElement(element, typedef, schema, eltDecl)
1.33 ht 50: return schema.factory.errors
1.2 ht 51:
1.55 ht 52: def validateElement(element, type, schema, eltDecl=None):
1.4 richard 53: global vel, vtype
54: vel = element
55: vtype = type
1.47 richard 56: if not eltDecl:
1.74.2.1 richard 57: eqn=XMLSchema.QName(None,element.localName,element.namespaceName or None)
1.47 richard 58: if s.vElementTable.has_key(eqn):
59: eltDecl=s.vElementTable[eqn]
1.74.2.12 ht 60: if eltDecl:
61: type=eltDecl.typeDefinition
1.74.2.13 ht 62: validateXSIAttrs(element,schema)
1.58 ht 63: nullable = eltDecl and eltDecl.nullable # TODO: is this right if no eltDecl?
1.48 richard 64: nulled = 0
1.74 richard 65: if element.attributes.has_key((xsi, "null")):
1.48 richard 66: if not nullable:
1.58 ht 67: verror(element,
1.74 richard 68: "xsi:null specified on non-nullable element %s" % element.originalName,
1.58 ht 69: schema,"cvc-elt.1.1")
1.74.2.20 ht 70: element.assess(schema.factory,eltDecl)
1.48 richard 71: return
1.74.2.13 ht 72: nulla=element.attributes[(xsi,"null")]
73: nulled = (nulla.validity=='valid' and
74: nulla.schemaNormalizedValue == "true")
1.74 richard 75: if element.attributes.has_key((xsi, "type")):
1.74.2.13 ht 76: typea=element.attributes[(xsi, "type")]
77: if typea.validity=='valid':
78: t = typea.schemaNormalizedValue;
79: (tp,tl) = XMLSchema.splitQName(t)
1.74.2.24 ht 80: tp=tp or ''
81: qt = XMLSchema.QName(tp, tl, element.inScopeNamespaces[tp].namespaceName)
1.74.2.13 ht 82: if schema.vTypeTable.has_key(qt):
83: xsitype=schema.vTypeTable[qt]
84: else:
85: verror(element,"xsi:type %s undefined" % qt,schema,"cvc-elt.2.2")
1.74.2.20 ht 86: element.assess(schema.factory,eltDecl)
1.74.2.13 ht 87: return
88: if type and not xsitype.isSubtype(type):
89: verror(element,
1.58 ht 90: "xsi:type %s is not a subtype of the declared type %s"%(qt,
91: type.name),
1.74.2.13 ht 92: schema,"cvc-elt.2.3")
1.74.2.20 ht 93: element.assess(schema.factory,eltDecl)
1.74.2.13 ht 94: return
95: if type:
96: vwarn(element,
97: "using xsi:type %s instead of original %s" % (qt, type.name))
98: else:
99: vwarn(element,"using xsi:type %s" % qt)
100: type = xsitype
1.74.2.12 ht 101: element.assessedType = type
1.55 ht 102: lax = not type
103: # might have none in case of recursive call inside <any/>, or at top level
1.48 richard 104: if nulled:
1.74.2.2 ht 105: validateElementNull(element, type, schema)
1.55 ht 106: if type:
1.58 ht 107: # TODO: check type is not abstract
108: if ((not type==XMLSchema.urType) and
109: (isinstance(type, XMLSchema.AbInitio) or
110: isinstance(type, XMLSchema.SimpleType))):
1.74.2.2 ht 111: if not nulled:
112: validateElementSimple(element, type, schema)
1.58 ht 113: if eltDecl:
114: validateKeys(eltDecl,element)
1.74.2.20 ht 115: element.assess(schema.factory,eltDecl)
1.58 ht 116: return
117: # a complexType
1.55 ht 118: ad=type.attributeDeclarations
119: ps=type.prohibitedSubstitutions
120: et=type.elementTable
121: else:
122: ps=[]
123: ad={}
124: et={}
125: assignAttributeTypes(element, ad, ps, schema, lax)
126: validateAttributeTypes(element, element.attrTable, ad, schema)
1.74.2.2 ht 127: # print "assigning types for %s" % element.originalName
128: if not nulled:
129: assignChildTypes(element.chunkedChildren, et, ps, schema, lax)
130: # we must look at the content model before checking the types, so that
131: # we know which children matched <any>
132: if type:
133: validateContentModel(element, type, schema)
134: validateChildTypes(element.chunkedChildren, schema, lax)
1.21 ht 135: if eltDecl:
1.33 ht 136: validateKeys(eltDecl,element)
1.74.2.20 ht 137: element.assess(schema.factory,eltDecl)
1.74.2.7 richard 138:
1.48 richard 139: def validateElementNull(element, type, schema):
1.74 richard 140: if len(element.chunkedChildren) != 0:
141: verror(element,"element %s is nulled but is not empty" % element.originalName,
1.58 ht 142: schema,"cvc-elt.1.2.1")
1.74.2.17 ht 143: else:
144: element.null=1
1.58 ht 145: # TODO: should check for fixed value constraint
1.48 richard 146:
1.2 ht 147: def validateElementSimple(element, type, schema):
148: # check that:
1.47 richard 149: # it has no attributes (except xsi: ones)
1.2 ht 150: # it has one pcdata child, and if so
151: # the text of the pcdata matches the type
1.74 richard 152: if element.attributes:
153: for a in element.attributes.values():
154: if a.namespaceName != xsi:
1.58 ht 155: verror(element,
156: "element {%s}%s with simple type not allowed attributes"%
1.74 richard 157: (element.namespaceName, element.localName),
1.58 ht 158: schema,"cvc-elt.4.1.1")
1.47 richard 159: return
1.2 ht 160: return validateTextModel(element, type, schema)
161:
1.74.2.13 ht 162: def validateXSIAttrs(element,schema):
163: for a in element.attributes.values():
164: if a.namespaceName == xsi:
165: if a.localName not in ('type','null','schemaLocation','noNamespaceSchemaLocation'):
166: verror(element,"unknown xsi attribute %s" % a.localName,schema,
167: "cvc-complex-type.1.3")
168: else:
169: a.type=schema.factory.sforsi.attributeTable[a.localName]
1.74.2.22 ht 170: res=a.type.typeDefinition.validateText(a.normalizedValue,a,
1.74.2.13 ht 171: element,schema)
172: a.assessedType = a.type.typeDefinition
173: if res:
174: verror(element,
175: "attribute type check failed for %s: %s%s"%(a.localName,
176: a.normalizedValue,
177: res),
178: schema,'cvc-attribute.1.2',0,None,a)
179: else:
180: a.schemaNormalizedValue=a.normalizedValue
1.74.2.20 ht 181: a.assess(schema.factory,a.type)
1.74.2.13 ht 182:
1.55 ht 183: def assignAttributeTypes(element, attrdefs, extendable, schema, lax):
1.2 ht 184: # look up each attribute in attrdefs and assign its type
185: # error if attr declaration is not found and type is not extendable
1.74 richard 186: # print "assigning attrs for %s {%s}%s" % (element.originalName, element.namespaceName, element.localName)
1.74.2.1 richard 187: # print "declared attrs are:"
188: # for zz in attrdefs.keys():
189: # if isinstance(zz, XMLSchema.QName):
190: # print "{%s}%s " % (zz.uri, zz.local)
191: # else:
192: # print zz
1.33 ht 193: element.attrTable={}
1.74 richard 194: for a in element.attributes.values():
1.74.2.14 ht 195: # print "assigning attr %s {%s}%s,%s,%s" % (a.originalName, a.namespaceName, a.localName,lax,attrdefs.has_key("#any"))
1.74.2.1 richard 196: an=XMLSchema.QName(None,a.localName,a.namespaceName or None)
1.33 ht 197: element.attrTable[an]=a
1.74 richard 198: if a.namespaceName == xsi:
1.74.2.13 ht 199: continue
1.27 richard 200: elif attrdefs.has_key(an):
1.43 ht 201: a.type = attrdefs[an].attributeDeclaration
1.55 ht 202: elif lax:
1.74 richard 203: if a.namespaceName and schema.vAttributeTable.has_key(an):
1.55 ht 204: a.type=schema.vAttributeTable[an]
205: else:
206: a.type=None
1.43 ht 207: elif (attrdefs.has_key("#any") and
1.74.2.14 ht 208: attrdefs["#any"].attributeDeclaration.allows(a.namespaceName or None)):
1.43 ht 209: a.type = attrdefs["#any"].attributeDeclaration
1.2 ht 210: else:
1.58 ht 211: verror(element,"undeclared attribute %s" % an,schema,
212: "cvc-complex-type.1.3")
1.2 ht 213: a.type = None
1.33 ht 214: return
1.2 ht 215:
1.33 ht 216: def validateAttributeTypes(element,attrs, attrdefs, schema):
1.2 ht 217: # check that each attribute matches its type
218: # check that all required attributes are present
1.74.2.8 ht 219: # TODO: add defaulted attributes (shouldn't need to check their types)
220: # checked fixed values
1.33 ht 221: for (adq,ad) in attrdefs.items():
222: if ad.minOccurs==1 and not attrs.has_key(adq):
1.58 ht 223: verror(element,"required attribute %s not present"%adq,schema,
224: 'cvc-complex-type.1.4')
1.33 ht 225: for (an,a) in attrs.items():
1.74.2.10 ht 226: if an.uri==xsi:
1.74.2.13 ht 227: # handled already
228: continue
1.74.2.10 ht 229: elif a.type:
1.43 ht 230: if isinstance(a.type,XMLSchema.Wildcard):
231: res=a.type.validate(a,schema,'attribute',element)
232: else:
1.58 ht 233: if a.type.typeDefinition:
1.74.2.22 ht 234: res=a.type.typeDefinition.validateText(a.normalizedValue,a,
235: element, schema)
1.74.2.12 ht 236: a.assessedType = a.type.typeDefinition
1.74.2.8 ht 237: if a.type.valueConstraint and a.type.valueConstraint[0]=='fixed':
238: if a.normalizedValue!=a.type.valueConstraint[1]:
239: verror(element,"fixed value did not match for attribute %s: %s!=%s"%(an,a.normalizedValue,a.type.valueConstraint[1]),schema,"cvc-attribute.1.3")
1.58 ht 240: else:
241: res=None
1.33 ht 242: if res:
243: verror(element,"attribute type check failed for %s: %s%s"%(an,
1.74 richard 244: a.normalizedValue,
1.33 ht 245: res),
1.74.2.9 ht 246: schema,'cvc-attribute.1.2',0,None,a)
1.74.2.22 ht 247: a.schemaNormalizedValue=None
1.74.2.20 ht 248: a.assess(schema.factory,a.type)
1.2 ht 249:
1.55 ht 250: def assignChildTypes(children, elementTable, extendable, schema, lax):
1.2 ht 251: # look up each child tag and record the type
252: # (it may not be an error if it is not declared; we don't know that
253: # until we see what it matches in the content model)
254: for child in children:
1.74.2.1 richard 255: if isinstance(child,XMLInfoset.Element):
256: qname = XMLSchema.QName(None,child.localName,child.namespaceName or None)
1.10 richard 257: if elementTable.has_key(qname):
1.74.2.8 ht 258: decl=elementTable[qname]
1.74.2.22 ht 259: child.type = decl.typeDefinition
1.74.2.8 ht 260: child.eltDecl = decl
1.74 richard 261: elif lax and child.namespaceName and schema.vElementTable.has_key(qname):
1.74.2.8 ht 262: decl=schema.vElementTable[qname]
263: child.type=decl.typeDefinition
264: child.eltDecl=decl
1.2 ht 265: else:
266: child.type = None
1.74.2.8 ht 267: child.eltDecl=None
1.2 ht 268: return 1
269:
270: def validateContentModel(element, type, schema):
271: # trace a path through the content model
272: # if a child matches an <any tag=... type=...> we need to indicate
273: # that that child should be validated with its xsd:type if it has one
274: # if a child matches some other kind of <any> we need to indicate
275: # that it's not an error if we can't find its type
276:
1.74.2.7 richard 277: # print "validating model for %s content type %s" % (element.originalName, type.contentType)
1.33 ht 278: if type.contentType == "empty":
279: validateEmptyModel(element, type, schema)
280: elif type.contentType == "textOnly":
281: validateTextModel(element, type.model, schema)
282: else:
283: validateElementModel(element, type.fsm,
284: type.contentType == "mixed", schema)
1.2 ht 285:
286: def validateEmptyModel(element, type, schema):
1.74 richard 287: if len(element.chunkedChildren) != 0:
288: verror(element,"element %s must be empty but is not" % element.originalName,schema,
1.58 ht 289: "cvc-complex-type.1.2")
1.2 ht 290:
291: def validateTextModel(element, type, schema):
292: # check that:
293: # it has one pcdata child, and if so
294: # the text of the pcdata matches the type
1.74.2.1 richard 295: name = element.localName
1.58 ht 296: n=0
1.74 richard 297: for child in element.chunkedChildren:
1.74.2.1 richard 298: if isinstance(child,XMLInfoset.Characters):
1.58 ht 299: n=1
1.74.2.1 richard 300: elif isinstance(child,XMLInfoset.Element):
1.58 ht 301: verror(element,
302: "element {%s}%s with simple type not allowed element children"%
1.74 richard 303: (element.namespaceName,name),schema,"cvc-complex-type.1.2.2")
1.66 ht 304: # TODO: mark this (and any others) as not validated
1.62 ht 305: return
1.2 ht 306: else:
307: if n == 0:
308: text = ""
309: else:
1.74 richard 310: text = element.chunkedChildren[0].characters
1.74.2.22 ht 311: res=type.validateText(text, element, element, schema)
1.33 ht 312: if res:
313: verror(element,"element content failed type check: %s%s"%(text,res),
1.58 ht 314: schema,"cvc-complex-type.1.2.2")
1.74.2.22 ht 315: element.schemaNormalizedValue=None
1.2 ht 316:
1.4 richard 317: def validateElementModel(element, fsm, mixed, schema):
1.74 richard 318: # print "validating element model for %s" % element.originalName
1.4 richard 319: n = fsm.startNode
1.74 richard 320: for c in element.chunkedChildren:
1.74.2.1 richard 321: if isinstance(c,XMLInfoset.Characters):
1.74 richard 322: if (not mixed) and (not whitespace.match(c.characters)):
1.74.2.19 ht 323: verror(element,
324: "text not allowed: |%s|" % c.characters,
1.58 ht 325: schema,"cvc-complex-type.1.2.3")
1.33 ht 326: return
1.74.2.1 richard 327: elif isinstance(c,XMLInfoset.Element):
328: qname = XMLSchema.QName(None, c.localName, c.namespaceName or None)
1.8 richard 329: next = None
1.13 richard 330: anynext = None
1.4 richard 331: for e in n.edges:
1.10 richard 332: if e.label == qname:
1.8 richard 333: next = e.dest
1.74.2.7 richard 334: c.strict = 1
1.4 richard 335: break
1.43 ht 336: if isinstance(e.label, XMLSchema.Wildcard):
1.74.2.14 ht 337: if e.label.allows(c.namespaceName or None):
1.41 ht 338: anynext = e.dest
339: anylab = e.label
1.8 richard 340: if not next:
1.13 richard 341: if anynext:
342: n = anynext
1.74.2.7 richard 343: c.strict = (anylab.processContents == 'strict')
1.17 richard 344: # this is no longer an error, but something more complicated is XXX
345: # if c.type:
346: # where(child.where)
347: # print "element matched <any> but had a type assigned"
348: # v = 0
349: # else:
350: # c.type = "<any>"
1.33 ht 351: c.type = anylab
1.13 richard 352: else:
1.74.2.17 ht 353: allowed=[]
354: for e in n.edges:
355: if isinstance(e.label, XMLSchema.QName):
356: allowed.append(str(e.label))
357: elif isinstance(e.label, XMLSchema.Wildcard):
1.74.2.26! ht 358: allowed.append("{%s}:*"%str(e.label.allowed))
1.74.2.17 ht 359: fx=fsm.asXML()
1.58 ht 360: verror(c,
1.74.2.17 ht 361: "element %s not allowed here (%s) in element %s, expecting %s:\n"%
362: (qname, n.id,
363: XMLSchema.QName(None,element.localName,element.namespaceName or None),
364: allowed),
365: schema,"cvc-complex-type.1.2.4",0,fx)
1.13 richard 366: else:
367: n = next
1.4 richard 368: if not n.isEndNode:
1.74.2.17 ht 369: allowed=[]
370: for e in n.edges:
371: if isinstance(e.label, XMLSchema.QName):
372: allowed.append(str(e.label))
373: elif isinstance(e.label, XMLSchema.Wildcard):
374: allowed.append(e.label.allowed)
375: fx=fsm.asXML()
1.58 ht 376: verror(element,
1.74.2.17 ht 377: "content of %s is not allowed to end here (%s), expecting %s:\n"%
378: (element.originalName,n.id,allowed),
379: schema,"cvc-complex-type.1.2.4",1,fx)
1.33 ht 380: return
1.2 ht 381:
1.55 ht 382: def validateChildTypes(children, schema, lax):
1.2 ht 383: # validate each child element against its type, if we know it
384: # report an error if we don't know it and it's not in <any>
1.7 richard 385: v = 1
1.2 ht 386: for child in children:
1.74.2.1 richard 387: if isinstance(child,XMLInfoset.Element):
1.33 ht 388: if child.type:
1.74.2.8 ht 389: if child.eltDecl:
390: validateElement(child,child.type,schema,child.eltDecl)
391: else:
392: # child.type is actually a wildcard
393: child.type.validate(child,schema,'element',child)
1.55 ht 394: elif lax:
1.74.2.8 ht 395: # TODO: check that this branch ever happens at all
1.58 ht 396: # TODO: record impact of missing type in PSVI
1.55 ht 397: validateElement(child,None,schema) # will be lax because no type
1.2 ht 398: else:
1.33 ht 399: verror(child,
1.58 ht 400: "undeclared element %s"%
1.74.2.1 richard 401: XMLSchema.QName(None,child.localName,child.namespaceName or None),
1.58 ht 402: schema,"src-resolve")
1.2 ht 403:
1.21 ht 404: def validateKeys(decl,elt):
1.22 ht 405: elt.keyTabs={}
1.33 ht 406: validateKeys1(elt,decl.keys,1)
407: validateKeys1(elt,decl.uniques,0)
408: validateKeyRefs(elt,decl.keyrefs)
1.22 ht 409:
410: def validateKeys1(elt,kds,reqd):
411: for key in kds:
1.21 ht 412: tab={}
413: sp=xpath.XPath(key.selector)
1.24 ht 414: candidates=sp.find(elt)
1.21 ht 415: if candidates:
1.69 ht 416: fps=map(lambda f:xpath.XPath(f),key.fields)
1.21 ht 417: for s in candidates:
1.22 ht 418: keyKey=buildKey(s,fps)
1.59 ht 419: if keyKey:
420: if len(keyKey)>1:
421: keyKey=tuple(keyKey)
422: else:
423: keyKey=keyKey[0]
424: else:
425: if reqd:
426: verror(s,
1.69 ht 427: "missing one or more fields %s from key %s"%(key.fields,
1.59 ht 428: key.name),
429: key.schema,"cvc-identity-constraint.2.2.2")
1.22 ht 430: break
1.21 ht 431: if tab.has_key(keyKey):
1.58 ht 432: if reqd:
433: code="cvc-identity-constraint.2.2.3"
434: else:
435: code="cvc-identity-constraint.2.1.2"
436: verror(s,"duplicate key %s, first appearance was %s"%
437: (str(keyKey),
438: XMLSchema.whereString(tab[keyKey].where)),
439: key.schema,code)
1.21 ht 440: else:
441: tab[keyKey]=s
1.22 ht 442: elt.keyTabs[key.name]=tab
443:
444: def buildKey(s,fps):
445: keyKey=[]
446: for fp in fps:
1.24 ht 447: kv=fp.find(s)
1.22 ht 448: if kv:
449: if len(kv)>1:
1.58 ht 450: # TODO error or shouldnt?
1.33 ht 451: vwarn(s,"oops, multiple field hits for %s at %s: %s"%(fp.str,s,kv))
1.74.2.1 richard 452: if isinstance(kv[0],XMLInfoset.Element):
1.74 richard 453: if (len(kv[0].chunkedChildren)>0 and
1.74.2.1 richard 454: isinstance(kv[0].chunkedChildren[0],XMLInfoset.Characters)):
1.74 richard 455: keyKey.append(kv[0].chunkedChildren[0].characters)
1.22 ht 456: else:
457: # XPath says in this case value is the empty string
458: pass
1.74.2.1 richard 459: elif XML.somestring(type(kv[0])):
1.22 ht 460: keyKey.append(kv[0])
461: else:
1.58 ht 462: # TODO error or shouldnt?
1.33 ht 463: vwarn(s,"oops, key value %s:%s"%(type(kv[0]),kv[0]))
1.22 ht 464: else:
1.74.2.22 ht 465: return
1.22 ht 466: return keyKey
467:
468: def validateKeyRefs(elt,krds):
469: res=1
470: for ref in krds:
1.25 ht 471: if elt.keyTabs.has_key(ref.refer):
472: keyTab=elt.keyTabs[ref.refer]
473: if keyTab=='bogus':
474: break
475: else:
476: elt.keyTabs[ref.refer]='bogus'
1.52 richard 477: verror(elt,
1.33 ht 478: "No key or unique constraint named %s declared, refed by keyref %s"%(ref.refer,ref.name),
1.58 ht 479: ref.schema,"cvc-identity-constraint.2.3.2")
1.25 ht 480: break
1.22 ht 481: sp=xpath.XPath(ref.selector)
1.24 ht 482: candidates=sp.find(elt)
1.22 ht 483: if candidates:
1.69 ht 484: fps=map(lambda f:xpath.XPath(f),ref.fields)
1.22 ht 485: for s in candidates:
486: keyKey=buildKey(s,fps)
487: if not keyKey:
488: break
489: if len(keyKey)>1:
490: keyKey=tuple(keyKey)
491: else:
492: keyKey=keyKey[0]
1.25 ht 493: if not keyTab.has_key(keyKey):
1.58 ht 494: verror(s,"no key in %s for %s"%(ref.refer,str(keyKey)),ref.schema,
495: "cvc-identity-constraint.2.3.2")
1.21 ht 496:
1.58 ht 497: def findSchemaLocs(element,schema):
1.30 richard 498: pairs = []
1.74 richard 499: for a in element.attributes.values():
500: if a.namespaceName == xsi:
501: if a.localName == "schemaLocation":
502: scls=string.split(a.normalizedValue)
1.43 ht 503: while scls:
1.58 ht 504: if len(scls)>1:
505: pairs.append((scls[0], scls[1]))
506: else:
1.74 richard 507: verror(element,"xsi:schemaLocation must be a list with an even number of members: %s"%string.split(a.normalizedValue),schema,"???")
1.43 ht 508: scls=scls[2:]
1.74 richard 509: elif a.localName == "noNamespaceSchemaLocation":
510: pairs.append((None,a.normalizedValue))
511: for c in element.chunkedChildren:
1.74.2.1 richard 512: if isinstance(c, XMLInfoset.Element):
1.58 ht 513: scl=findSchemaLocs(c,schema)
1.43 ht 514: if scl:
515: pairs = pairs + scl
1.30 richard 516: return pairs
517:
1.74.2.8 ht 518: def runitAndShow(en,rns=[],k=0,style=None,enInfo=None,outfile=None,dw=1,
1.74.2.18 ht 519: timing=0,reflect=0):
1.74.2.8 ht 520: global dontWarn
521: dontWarn=dw
522: if timing:
523: timing=time.time()
524: (res,encoding,errs)=runit(en,rns,k,timing)
525: if timing:
526: sys.stderr.write("Finished: %6.2f\n"%(time.time()-timing))
1.58 ht 527: if not encoding:
528: encoding='UTF-8'
1.74.2.2 ht 529: if outfile:
530: try:
531: outf=open(outfile,"w")
532: except:
533: sys.stderr.write("couldn't open %s for output, falling back to stderr"%
534: outfile)
535: outf=sys.stderr
536: else:
537: outf=sys.stderr
538: errout=OpenStream(outf,
1.58 ht 539: CharacterEncodingNames[encoding],
540: NSL_write+NSL_write_plain)
541: if encoding!='UTF-8':
542: es=" encoding='%s'"%encoding
543: else:
544: es=""
1.74.2.2 ht 545: PrintTextLiteral(errout,"<?xml version='1.0'%s?>\n"%es)
1.58 ht 546: if style:
1.74.2.2 ht 547: PrintTextLiteral(errout,
548: "<?xml-stylesheet type='text/xsl' href='%s'?>\n"%style)
1.64 ht 549: if enInfo:
550: for (k,v) in enInfo.items():
551: res.addAttr(k,v)
1.74.2.8 ht 552: if errs:
1.74.2.2 ht 553: res.addAttr("crash","true")
1.58 ht 554: res.printme(errout)
1.74.2.2 ht 555: PrintTextLiteral(errout,"\n")
1.58 ht 556: Close(errout)
1.74.2.18 ht 557: if reflect:
558: dumpInfoset(sys.stdout)
1.74.2.8 ht 559: if errs:
560: return string.join(map(lambda es:string.join(es,''),errs),'')
1.74.2.2 ht 561: else:
562: return
563:
564: class SchemaValidationError(Exception):
565: def __init__(self,arg):
566: Exception.__init__(self,arg)
1.58 ht 567:
1.74.2.8 ht 568: def runit(en,rns=[],k=0,timing=0):
569: global s,e,t,f,res,ed,btlist
570: btlist=[]
1.33 ht 571:
1.45 ht 572: ss = s = None
1.33 ht 573:
1.41 ht 574: f=XMLSchema.newFactory()
1.58 ht 575: f.errors=0
1.36 ht 576: base=f.fileNames[0]
1.67 ht 577: if en:
578: ren=urljoin(base,en)
579: else:
580: ren=None
1.30 richard 581:
1.74.2.1 richard 582: res=XML.Element("xsv")
1.58 ht 583: f.resElt=res
584: res.addAttr("xmlns","http://www.w3.org/2000/05/xsv")
585: res.addAttr("version",vs)
1.67 ht 586: res.addAttr("target",ren or "[stdin]")
1.58 ht 587: if rns:
588: res.addAttr("schemaDocs",string.join(rns,' '))
589:
590: rdn=tempfile.mktemp("xsverrs")
591: redirect=open(rdn,"w+")
592: savedstderr=os.dup(2) # save stderr
593: os.dup2(redirect.fileno(),2)
594: try:
1.74.2.15 ht 595: doc=readXML(ren)
596: e=doc.documentElement
597: f.docElt=e
598: encoding=doc.documentEntity.charset
1.74.2.8 ht 599: if timing:
600: os.write(savedstderr,"target read: %6.2f\n"%(time.time()-timing))
1.74.2.25 ht 601: except:
1.74.2.9 ht 602: pfe=XML.Element("bug")
603: pfe.children=[XML.Pcdata("validator crash during target reading")]
1.74.2.8 ht 604: res.children.append(pfe)
1.58 ht 605: e=None
606: encoding=None
607: if not e:
608: res.addAttr('outcome',"validation not attempted")
609: sys.stderr.flush()
610: registerRawErrors(redirect,res)
611: # put stderr back
612: os.dup2(savedstderr,2)
1.74.2.8 ht 613: return (res,None,btlist)
1.58 ht 614:
615: # TODO: check each schema doc against schema for schemas, if possible,
616: # unless caller explicitly opts out (?)
1.28 ht 617: if rns:
1.49 ht 618: try:
1.53 ht 619: s = XMLSchema.fromFile(urljoin(base,rns[0]),f)
1.74.2.8 ht 620: if timing:
621: os.write(savedstderr,"schema read: %6.2f\n"%(time.time()-timing))
622: except:
1.74.2.9 ht 623: pfe=XML.Element("bug")
624: pfe.children=[XML.Pcdata("validator crash during schema reading")]
1.74.2.8 ht 625: res.children.append(pfe)
626: btlist.append(traceback.format_exception(sys.exc_type,
627: sys.exc_value,
628: sys.exc_traceback))
1.30 richard 629: for rn in rns[1:]:
1.49 ht 630: try:
1.67 ht 631: ffr=XMLSchema.fromFile(urljoin(base,rn),f)
1.74.2.8 ht 632: if timing:
633: os.write(savedstderr,"schema read: %6.2f\n"%(time.time()-timing))
1.67 ht 634: ss=ss or ffr
1.74.2.8 ht 635: except:
1.74.2.9 ht 636: pfe=XML.Element("bug")
637: pfe.children=[XML.Pcdata("validator crash during schema reading")]
1.74.2.8 ht 638: res.children.append(pfe)
639: btlist.append(traceback.format_exception(sys.exc_type,
640: sys.exc_value,
641: sys.exc_traceback))
1.30 richard 642:
1.45 ht 643: if not s:
1.65 ht 644: if ss:
645: s=ss
646: else:
647: s = XMLSchema.Schema(f,None)
648: s.targetNS='##dummy'
1.45 ht 649:
1.58 ht 650: schemaLocs = findSchemaLocs(e,s)
1.74.2.1 richard 651: res.addAttr('schemaLocs',string.join(map(lambda p:"%s -> %s"%(p[0] or 'None',p[1]),
1.58 ht 652: schemaLocs),
653: '; '))
1.30 richard 654: for (ns, sl) in schemaLocs:
1.49 ht 655: try:
1.67 ht 656: XMLSchema.checkinSchema(f, ns, sl,e,ren or "[stdin]")
1.74.2.8 ht 657: if timing:
658: os.write(savedstderr,"schema read: %6.2f\n"%(time.time()-timing))
659: except:
1.74.2.9 ht 660: pfe=XML.Element("bug")
661: pfe.children=[XML.Pcdata("validator crash during schema reading")]
1.74.2.8 ht 662: res.children.append(pfe)
663: btlist.append(traceback.format_exception(sys.exc_type,
664: sys.exc_value,
665: sys.exc_traceback))
1.30 richard 666:
1.74 richard 667: res.addAttr('docElt',"{%s}%s"%(e.namespaceName,e.localName))
668: if (e.namespaceName and
1.74.2.9 ht 669: (e.namespaceName not in ('http://www.w3.org/XML/1998/namespace',xsi)) and
1.74 richard 670: not f.schemas.has_key(e.namespaceName)):
1.34 ht 671: try:
1.74 richard 672: XMLSchema.checkinSchema(f,e.namespaceName,e.namespaceName,e,ren or "[stdin]")
1.74.2.8 ht 673: if timing:
674: os.write(savedstderr,"schema read: %6.2f\n"%(time.time()-timing))
1.58 ht 675: res.addAttr('nsURIDeref','success')
1.74.2.8 ht 676: except:
1.74.2.9 ht 677: pfe=XML.Element("bug")
678: pfe.children=[XML.Pcdata("validator crash during schema reading")]
1.74.2.8 ht 679: res.children.append(pfe)
680: btlist.append(traceback.format_exception(sys.exc_type,
681: sys.exc_value,
682: sys.exc_traceback))
1.58 ht 683: res.addAttr('nsURIDeref','failure')
1.30 richard 684:
1.58 ht 685: sys.stderr.flush()
686: registerRawErrors(redirect,res)
687: # put stderr back
688: os.dup2(savedstderr,2)
689:
690: try:
691: ecount=XMLSchema.prepare(f)
1.74.2.8 ht 692: if timing:
693: sys.stderr.write("schemas prepared: %6.2f\n"%(time.time()-timing))
1.58 ht 694: except:
695: ecount=-1
1.74.2.8 ht 696: btlist.append(traceback.format_exception(sys.exc_type,
697: sys.exc_value,
698: sys.exc_traceback))
1.74.2.9 ht 699: pfe=XML.Element("bug")
700: pfe.children=[XML.Pcdata("validator crash during factory preparation")]
1.58 ht 701: res.children.append(pfe)
1.74.2.2 ht 702:
1.58 ht 703: kgm="true"
704: kg=1
1.33 ht 705: if ecount:
1.58 ht 706: if ecount<0:
707: kg=0
1.33 ht 708: else:
1.58 ht 709: if not k:
710: kg=0
711: if not kg:
712: kgm="false"
713: res.addAttr('instanceAssessed',kgm)
714: if not kg:
1.74.2.8 ht 715: if ecount<0:
716: ecount=0
717: for sch in f.schemas.values():
718: ecount=ecount+sch.errors
719: res.addAttr('schemaErrors',str(ecount))
720: return (res,encoding,btlist)
1.30 richard 721:
1.74 richard 722: cl=string.find(':',e.originalName)
1.28 ht 723: if cl>-1:
1.74 richard 724: prefix=e.originalName[0:cl]
1.28 ht 725: else:
726: prefix=''
1.74.2.1 richard 727: eltname = XMLSchema.QName(prefix,e.localName,e.namespaceName or None)
1.30 richard 728:
729: if not s:
730: # any one will do
1.33 ht 731: s = f.sfors
732: t=None
733:
1.55 ht 734: ed=None
1.33 ht 735: if s and s.vElementTable.has_key(eltname):
1.55 ht 736: ed=s.vElementTable[eltname]
737: t=ed.typeDefinition
1.58 ht 738: if t:
739: if t.name:
1.66 ht 740: if hasattr(t,'qname'):
741: tn=t.qname.string()
742: else:
743: tn=t.name
1.58 ht 744: else:
745: tn='[Anonymous]'
746: res.addAttr('rootType',tn)
747: res.addAttr('validation','strict')
748: else:
749: res.addAttr('validation','lax')
1.33 ht 750:
751: if e and s:
1.74.2.2 ht 752: try:
753: validate(e, t, s, ed)
1.74.2.17 ht 754: sforsi=PSVInfoset.NamespaceSchemaInformation(f.schemas[XMLSchema.XMLSchemaNS])
755: sforsi.schemaComponents.sort(PSVInfoset.compareSFSComps) # ensure atomics
756: # are first
757: e.schemaInformation=[sforsi,
758: PSVInfoset.NamespaceSchemaInformation(f.schemas[xsi])]
1.74.2.16 ht 759: for s in f.schemas.values():
760: if s.targetNS not in (XMLSchema.XMLSchemaNS,xsi):
761: e.schemaInformation.append(PSVInfoset.NamespaceSchemaInformation(s))
1.74.2.2 ht 762: except:
1.74.2.8 ht 763: btlist.append(traceback.format_exception(sys.exc_type,
764: sys.exc_value,
765: sys.exc_traceback))
1.74.2.9 ht 766: pfe=XML.Element("bug")
767: pfe.children=[XML.Pcdata("validator crash during validation")]
1.74.2.2 ht 768: res.children.append(pfe)
1.58 ht 769: res.addAttr('instanceErrors',str(s.factory.errors))
1.74.2.2 ht 770: ec=0
771: for sch in f.schemas.values():
772: ec=ec+sch.errors
773: res.addAttr('schemaErrors',str(ec))
1.74.2.8 ht 774: return (res,encoding,btlist)
1.30 richard 775:
1.58 ht 776: def registerRawErrors(redirect,res):
777: if redirect.tell():
778: redirect.seek(0)
1.74.2.1 richard 779: ro=XML.Element("XMLMessages")
1.58 ht 780: o="\n%s"%redirect.read()
1.74.2.1 richard 781: ro.children=[XML.Pcdata(o)]
1.58 ht 782: res.children.append(ro)
783: redirect.close()
784:
1.74.2.9 ht 785: def verror(elt,message,schema,code=None,two=0,daughter=None,iitem=None):
1.58 ht 786: # code argument identifies CVC
1.74.2.1 richard 787: ve=XML.Element("invalid")
788: ve.children=[XML.Pcdata(message)]
1.58 ht 789: if code:
790: ve.addAttr("code",code)
1.33 ht 791: if two:
1.58 ht 792: XMLSchema.where(ve,elt.where2)
1.33 ht 793: else:
1.58 ht 794: XMLSchema.where(ve,elt.where)
795: if daughter:
796: ve.children.append(daughter)
797: res.children.append(ve)
1.33 ht 798: schema.factory.errors=schema.factory.errors+1
1.74.2.9 ht 799: if not iitem:
800: iitem=elt
801: if iitem.errorCode:
802: iitem.errorCode.append(" "+code)
1.74.2.2 ht 803: else:
1.74.2.9 ht 804: iitem.errorCode=[code]
1.33 ht 805:
806: def vwarn(elt,message):
1.74.2.8 ht 807: if dontWarn:
808: return
1.74.2.9 ht 809: ve=XML.Element("warning")
810: ve.children=[XML.Pcdata(message)]
1.33 ht 811: if elt:
1.58 ht 812: XMLSchema.where(ve,elt.where)
813: res.children.append(ve)
1.24 ht 814:
1.41 ht 815: # validation methods for schema components
816:
1.43 ht 817: def av(self,child,schema,kind,elt):
1.74.2.1 richard 818: q = XMLSchema.QName(None,child.localName,child.namespaceName or None)
1.43 ht 819: vwarn(elt,"allowing %s because it matched wildcard(%s)" %
820: (q,self.allowed))
821: if self.processContents!='skip':
1.74.2.12 ht 822: # print "looking for decl for %s" % child.originalName
1.74 richard 823: if schema.factory.schemas.has_key(child.namespaceName):
1.41 ht 824: # only try if we might win -- needs work
825: try:
1.43 ht 826: if kind=='element':
827: e = schema.vElementTable[q]
828: else:
829: e = schema.vAttributeTable[q]
1.41 ht 830: except KeyError:
831: e=None
1.74.2.12 ht 832: # print "decl for %s is %s" % (child.originalName, e)
1.58 ht 833: if e and e.typeDefinition:
1.43 ht 834: vwarn(None,"validating it against %s" %
835: (e.typeDefinition.name or 'anonymous type'))
836: if kind=='element':
837: validateElement(child, e.typeDefinition, schema)
838: else:
1.74.2.12 ht 839: child.assessedType = e.typeDefinition
1.74.2.22 ht 840: res=e.typeDefinition.validateText(child.normalizedValue,child,
1.74.2.12 ht 841: elt, schema)
1.74.2.22 ht 842: if res:
843: verror(elt,
844: "attribute type check failed for %s: %s%s"%(q,
845: child.normalizedValue,
846: res),
847: schema,'cvc-attribute.1.2',0,None,child)
848: child.schemaNormalizedValue=None
1.61 ht 849: elif (self.processContents=='strict' and
1.74 richard 850: not (kind=='element' and child.attributes.has_key((xsi, "type")))):
1.58 ht 851: # TODO check this against actual def'n of missing component
1.43 ht 852: verror(elt,
853: "can't find a type for wildcard-matching %s %s" %(kind, q),
1.58 ht 854: schema,
855: "src-resolve")
1.61 ht 856: elif kind=='element':
857: vwarn(None,"validating it laxly")
858: validateElement(child,None,schema)
1.74.2.7 richard 859:
1.43 ht 860: XMLSchema.Wildcard.validate=av
1.42 ht 861:
1.43 ht 862: def tv(self,child,schema,kind,elt):
1.42 ht 863: validateElement(child, self, schema)
1.41 ht 864:
1.43 ht 865: XMLSchema.Type.validate=XMLSchema.AbInitio.validate=tv
1.41 ht 866:
1.74.2.22 ht 867: def validateText(self, text, item, context, schema):
1.58 ht 868: if self==XMLSchema.urType:
869: return
870: else:
1.69 ht 871: if self.variety=='atomic':
872: # ref may have failed
1.74.2.22 ht 873: if self.primitiveType:
874: return self.primitiveType.checkString(self.primitiveType.normalize(text,
875: item),
876: context)
877: else:
878: item.schemaNormalizedValue=None
879: return
1.69 ht 880: elif self.variety=='list':
881: it=self.itemType
1.58 ht 882: # TODO: what about post-list facets?
1.70 ht 883: if not it:
884: return
1.74.2.22 ht 885: for substr in string.split(normalize(None,text,item,'collapse')):
886: res=it.validateText(substr,None,context,schema)
1.58 ht 887: if res:
888: return res+' in list'
889: return
1.69 ht 890: elif self.variety=='union':
891: mts=self.memberTypes
892: subres=[]
893: # TODO: what about post-union facets?
894: for mt in mts:
1.70 ht 895: if mt:
1.74.2.22 ht 896: res=mt.validateText(text,item,context,schema)
1.70 ht 897: if res:
898: subres.append(res)
899: else:
900: # bingo
901: return
1.69 ht 902: # no subtypes won, we lose
1.74.2.22 ht 903: item.schemaNormalizedValue=None
1.70 ht 904: return " no members of union succeeded: %s"%subres
1.58 ht 905: else:
1.69 ht 906: XMLSchema.shouldnt('vv '+str(self.variety))
1.58 ht 907:
908: XMLSchema.SimpleType.validateText=validateText
909:
1.74.2.22 ht 910: def validateText(self, text, item, context, schema):
911: return self.checkString(self.normalize(text,item),context)
1.58 ht 912:
913: XMLSchema.AbInitio.validateText=validateText
914:
1.71 richard 915: # checkString methods
916:
917: def checkString(self,str,context):
1.74.2.22 ht 918: if self.facetValue('enumeration')!=None:
1.74.2.21 ht 919: evs=self.facetValue('enumeration')
920: for val in evs:
1.71 richard 921: if val==str:
922: return
1.74.2.21 ht 923: return " not in enumeration %s"%evs
1.71 richard 924:
925: XMLSchema.AbInitio.checkString = checkString
926:
1.74.2.22 ht 927: wsoChar=re.compile("[\t\r\n]")
928: wsChars=re.compile("[ \t\r\n]+")
929: iSpace=re.compile("^ ")
930: fSpace=re.compile(" $")
931: def normalize(self,str,item,ws=None):
932: if not item:
933: # list component, shouldn't be processed
934: return str
935: if not ws:
1.74.2.23 ht 936: ws=self.facetValue('whiteSpace')
1.74.2.22 ht 937: if ws=='replace':
938: str=wsoChar.sub(' ',str)
939: elif ws=='collapse':
940: str=wsChars.sub(' ',str)
941: str=iSpace.sub('',str)
942: str=fSpace.sub('',str)
943: # else ((not ws) or ws=='preserve'): pass
944: item.schemaNormalizedValue=str
945: return str
946:
947: XMLSchema.AbInitio.normalize=normalize
948:
1.71 richard 949: def checkString(self,str,context):
950: try:
951: if ('.' in str) or ('E' in str):
952: val=string.atof(str)
953: else:
954: val=string.atoi(str)
955: except ValueError:
956: return " does not represent a number"
1.74.2.21 ht 957: minI=self.facetValue('minInclusive')
958: if minI!=None and val<minI:
959: return "<%d"%minI
960: minE=self.facetValue('minExclusive')
961: if minE!=None and val<=minE:
962: return "<=%d"%minE
963: maxI=self.facetValue('maxInclusive')
964: if maxI!=None and val>maxI:
965: return ">%d"%maxI
966: maxE=self.facetValue('maxExclusive')
967: if maxE!=None and val>=maxE:
968: return ">=%d"%maxE
1.72 richard 969: return XMLSchema.AbInitio.checkString(self,str,context)
1.71 richard 970:
971: XMLSchema.DecimalST.checkString = checkString
972:
973: def checkString(self,str,context):
974: # not complete by any means
975: parts=string.split(str,':')
976: if len(parts)>2:
977: return " has more than one colon"
1.74.2.1 richard 978: if len(parts)==2 and not context.inScopeNamespaces.has_key(parts[0]):
1.71 richard 979: return " has undeclared prefix: %s"%parts[0]
1.72 richard 980: return XMLSchema.AbInitio.checkString(self,str,context)
1.71 richard 981:
982: XMLSchema.QNameST.checkString = checkString
1.58 ht 983:
1.74.2.12 ht 984: # assess methods
985:
1.74.2.20 ht 986: def assess(self,factory,decl):
1.74.2.12 ht 987: allfull = 1
988: allnone = 1
989: nochildren = 1
990: for c in self.chunkedChildren:
991: if isinstance(c, XMLInfoset.Element):
992: nochildren = 0
993: validationAttempted = c.__dict__.has_key("validationAttempted") and c.validationAttempted
994: if validationAttempted != 'full':
995: allfull = 0
996: if validationAttempted and c.validationAttempted != 'none':
997: allnone = 0
998: attrs=self.attributes.values()
999: for c in attrs:
1000: if isinstance(c, XMLInfoset.Attribute):
1001: nochildren = 0
1002: validationAttempted = c.__dict__.has_key("validationAttempted") and c.validationAttempted
1003: if validationAttempted != 'full':
1004: allfull = 0
1005: if validationAttempted and c.validationAttempted != 'none':
1006: allnone = 0
1007:
1008: if nochildren:
1009: if self.assessedType:
1010: self.validationAttempted = 'full'
1011: else:
1012: self.validationAttempted = 'none'
1013: else:
1014: if allfull and self.assessedType:
1015: self.validationAttempted = 'full'
1016: elif allnone and not self.assessedType:
1017: self.validationAttempted = 'none'
1018: else:
1019: self.validationAttempted = 'partial'
1020:
1021: if self.errorCode:
1022: self.validity = 'invalid'
1023: else:
1024: has_losing_child = 0
1025: has_untyped_strict_child = 0
1026: has_non_winning_typed_child = 0
1027: for c in self.chunkedChildren:
1028: if not isinstance(c, XMLInfoset.Element):
1029: continue
1030: strict = c.__dict__.has_key("strict") and c.strict
1031: validatedType = c.__dict__.has_key("validatedType") and c.assessedType
1032: validity = c.__dict__.has_key("validity") and c.validity
1033: if validity == 'invalid':
1034: has_losing_child = 1
1035: if strict and not validatedType:
1036: has_untyped_strict_child = 1
1037: if validatedType and validity != 'valid':
1038: has_non_winning_typed_child = 1
1039: for c in attrs:
1040: if not isinstance(c, XMLInfoset.Attribute):
1041: continue
1042: strict = c.__dict__.has_key("strict") and c.strict
1043: validatedType = c.__dict__.has_key("validatedType") and c.assessedType
1044: validity = c.__dict__.has_key("validity") and c.validity
1045: if validity == 'invalid':
1046: has_losing_child = 1
1047: if strict and not validatedType:
1048: has_untyped_strict_child = 1
1049: if validatedType and validity != 'valid':
1050: has_non_winning_typed_child = 1
1051: if has_losing_child or has_untyped_strict_child:
1052: self.validity = 'invalid'
1053: elif has_non_winning_typed_child:
1054: self.validity = 'unknown'
1055: else:
1056: self.validity = 'valid'
1057:
1058: if self.assessedType and self.validity=='valid':
1.74.2.16 ht 1059: self.typeDefinition=self.assessedType
1.74.2.20 ht 1060: self.elementDeclaration=decl
1.74.2.15 ht 1061: self.validationContext=factory.docElt
1.74.2.12 ht 1062:
1063: XMLInfoset.Element.assess=assess
1064: XMLInfoset.Element.assessedType=None
1065:
1.74.2.20 ht 1066: def assess(self,factory,decl):
1.74.2.12 ht 1067: if self.errorCode:
1068: self.validity = 'invalid'
1069: else:
1070: self.validity = 'valid'
1071: if self.assessedType:
1072: self.validationAttempted = 'full'
1073: if self.validity=='valid':
1.74.2.16 ht 1074: self.typeDefinition=self.assessedType
1.74.2.20 ht 1075: self.attributeDeclaration=decl
1.74.2.12 ht 1076: else:
1077: self.validationAttempted = 'none'
1078: self.validity = 'unknown'
1.74.2.15 ht 1079: self.validationContext=factory.docElt
1.74.2.12 ht 1080:
1081: XMLInfoset.Attribute.assess=assess
1082: XMLInfoset.Attribute.assessedType=None
1083:
1.74.2.18 ht 1084: def dumpInfoset(fileOrName):
1085: close=0
1086: if type(fileOrName)==types.FileType:
1087: ff=fileOrName
1088: else:
1089: close=1
1090: ff = open(fileOrName, "w")
1.74.2.15 ht 1091: r = f.docElt.parent.reflect()
1.74.2.11 ht 1092: r.documentElement.inScopeNamespaces["psv"]=XMLInfoset.Namespace("psv",
1093: PSVInfoset.infosetSchemaNamespace)
1.74.2.18 ht 1094: r.indent("",1)
1.74.2.5 richard 1095: r.printme(ff)
1.74.2.18 ht 1096: if close:
1097: ff.close()
1.74.2.5 richard 1098:
1.42 ht 1099: # run at import if top
1100:
1101: if __name__=='__main__':
1102: argl=sys.argv[1:]
1103: k=0
1.74.2.8 ht 1104: dw=1
1105: timing=0
1.58 ht 1106: style=None
1.74.2.2 ht 1107: outfile=None
1.74.2.18 ht 1108: reflect=0
1.74.2.23 ht 1109: proFile=None
1.42 ht 1110: while argl:
1111: if argl[0]=='-k':
1112: k=1
1.58 ht 1113: elif argl[0]=='-s':
1114: style=argl[1]
1115: argl=argl[1:]
1.74.2.2 ht 1116: elif argl[0]=='-o':
1117: outfile=argl[1]
1118: argl=argl[1:]
1.74.2.23 ht 1119: elif argl[0]=='-p':
1120: proFile=argl[1]
1121: argl=argl[1:]
1.74.2.8 ht 1122: elif argl[0]=='-w':
1123: dw=0
1124: elif argl[0]=='-t':
1125: timing=1
1.74.2.18 ht 1126: elif argl[0]=='-r':
1127: reflect=1
1.74.2.2 ht 1128: elif argl[0][0]=='-':
1.74.2.23 ht 1129: sys.stderr.write("Usage: [-ktwr] [-s stylesheet] [-o outputFile] [-p profileOut] file [schema1 schema2 . . .]\n")
1.74.2.2 ht 1130: sys.exit(-1)
1.42 ht 1131: else:
1132: break
1133: argl=argl[1:]
1134:
1135: if argl:
1.74.2.23 ht 1136: if proFile:
1137: import profile
1138: res=profile.run("""runitAndShow(argl[0],argl[1:],k,
1139: style,None,outfile,dw,timing,reflect)""",
1140: proFile)
1141: else:
1142: res=runitAndShow(argl[0],argl[1:],k,style,None,outfile,dw,timing,reflect)
1.42 ht 1143: else:
1.74.2.18 ht 1144: res=runitAndShow(None,[],k,style,None,outfile,dw,timing,reflect)
1.74.2.2 ht 1145:
1146: if res:
1147: raise SchemaValidationError,res
1.41 ht 1148:
1.25 ht 1149: # $Log: applyschema.py,v $
1.74.2.26! ht 1150: # Revision 1.74.2.25 2001/01/03 19:13:19 ht
! 1151: # accommodate to change of exception with LTXMLInfoset
! 1152: #
1.74.2.25 ht 1153: # Revision 1.74.2.24 2001/01/03 11:57:52 ht
1154: # fix xsi:type bugs
1155: #
1.74.2.24 ht 1156: # Revision 1.74.2.23 2000/12/23 13:08:21 ht
1157: # fix spelling of whiteSpace,
1158: # add -p file switch for profiling
1159: #
1.74.2.23 ht 1160: # Revision 1.74.2.22 2000/12/22 18:33:54 ht
1161: # add whitespace processing,
1162: # fix some bugs?
1163: #
1.74.2.22 ht 1164: # Revision 1.74.2.21 2000/12/21 18:29:38 ht
1165: # accommodate to .facets and real facets
1166: #
1.74.2.21 ht 1167: # Revision 1.74.2.20 2000/12/16 12:10:29 ht
1168: # add logging of relevant declaration to elt/attr assess
1169: #
1.74.2.20 ht 1170: # Revision 1.74.2.19 2000/12/14 14:21:59 ht
1171: # fix bug in e-o error msg
1172: #
1.74.2.19 ht 1173: # Revision 1.74.2.18 2000/12/13 23:30:09 ht
1174: # add -r switch to produce reflected output
1175: #
1.74.2.18 ht 1176: # Revision 1.74.2.17 2000/12/12 17:33:06 ht
1177: # get builtin-schemas out first, sort AbInitios to the front,
1178: # more details in content-model error messages,
1179: # set null property
1180: #
1.74.2.17 ht 1181: # Revision 1.74.2.16 2000/12/08 18:08:42 ht
1182: # install schemaInformation on validation root,
1183: # assign type defn as such to typeDefinition property
1184: #
1.74.2.16 ht 1185: # Revision 1.74.2.15 2000/12/08 15:16:07 ht
1186: # put the docElt in the factory,
1187: # use it for reflection at the end,
1188: # and to implement validationContext
1189: #
1.74.2.15 ht 1190: # Revision 1.74.2.14 2000/12/07 13:18:42 ht
1191: # work around null vs "" for missing namespace name
1192: #
1.74.2.14 ht 1193: # Revision 1.74.2.13 2000/12/07 10:20:48 ht
1194: # handle xsi: attrs cleanly
1195: #
1.74.2.13 ht 1196: # Revision 1.74.2.12 2000/12/06 22:43:11 ht
1197: # make assess a method on Element,
1198: # add one on Attribute,
1199: # refer to the latter from the former
1200: #
1.74.2.12 ht 1201: # Revision 1.74.2.11 2000/12/06 09:21:05 ht
1202: # add psv infoset namespace URI to reflected docapplyschema.py
1203: #
1.74.2.11 ht 1204: # Revision 1.74.2.10 2000/12/04 22:31:03 ht
1205: # stubs for schemaNormalizedValue in place
1206: #
1.74.2.10 ht 1207: # Revision 1.74.2.9 2000/12/04 22:09:00 ht
1208: # remove convert,
1209: # accommodate change to importing XML,
1210: # put attribute verror on right item
1211: #
1.74.2.9 ht 1212: # Revision 1.74.2.8 2000/12/04 13:30:42 ht
1213: # merge in main line fixes thru 1.82
1214: #
1.74.2.8 ht 1215: # Revision 1.74.2.7 2000/10/13 12:48:42 richard
1216: # more infoset contributions
1217: #
1.74.2.7 richard 1218: # Revision 1.74.2.6 2000/10/02 13:33:28 richard
1219: # update values for validity property
1220: #
1.74.2.6 richard 1221: # Revision 1.74.2.5 2000/09/29 17:18:09 richard
1222: # More towards PSV infoset
1223: #
1.74.2.5 richard 1224: # Revision 1.74.2.4 2000/09/29 16:45:27 richard
1225: # correct errorCode setting
1226: #
1.74.2.4 richard 1227: # Revision 1.74.2.3 2000/09/29 16:04:24 richard
1228: # More towards PSV infoset
1229: #
1.74.2.3 richard 1230: # Revision 1.74.2.2 2000/09/29 14:16:15 ht
1231: # towards PSVI contributions
1232: #
1.74.2.2 ht 1233: # Revision 1.74.2.1 2000/09/27 17:21:20 richard
1234: # Changes for infoset-based
1.74.2.8 ht 1235: #
1236: # Revision 1.77 2000/09/28 15:54:50 ht
1237: # schema error count includes all errors, not just those found at prep
1238: # time
1239: #
1240: # Revision 1.76 2000/09/28 15:09:14 ht
1241: # try catching and returning any crashes
1242: #
1243: # Revision 1.75 2000/09/28 08:41:57 ht
1244: # add usage message
1245: # add -o outfile cmd line arg
1246: #
1247: # Revision 1.82 2000/10/31 16:30:47 ht
1248: # validate subordinate elements with eltdecl if available
1249: # return schema error count if not attempting instance validation
1250: #
1251: # Revision 1.81 2000/10/27 15:33:30 ht
1252: # Output timing info if -t on command line
1253: #
1254: # Revision 1.80 2000/10/18 15:54:58 ht
1255: # make effort to check 'fixed' attribute values
1256: #
1257: # Revision 1.79 2000/10/17 13:35:41 ht
1258: # put switch on warnings, default is don't
1259: #
1260: # Revision 1.78 2000/10/17 12:45:15 ht
1261: # try to catch and log all crashes
1262: # replace stale reference to atribute.characters
1.74.2.2 ht 1263: #
1264: # Revision 1.77 2000/09/28 15:54:50 ht
1265: # schema error count includes all errors, not just those found at prep
1266: # time
1267: #
1268: # Revision 1.76 2000/09/28 15:09:14 ht
1269: # try catching and returning any crashes
1270: #
1271: # Revision 1.75 2000/09/28 08:41:57 ht
1272: # add usage message
1273: # add -o outfile cmd line arg
1274: #
1.74.2.1 richard 1275: # Revision 1.74 2000/09/27 13:48:47 richard
1276: # Use infoset-like names for slots (now provided in XML.py) to reduce
1277: # differences with infoset-based version.
1278: #
1.74 richard 1279: # Revision 1.73 2000/09/27 12:22:22 richard
1280: # correct element.name to element.local in an error message
1281: #
1.73 richard 1282: # Revision 1.72 2000/09/26 14:29:36 richard
1283: # Oops, didn't change AbInitio to XMLSchema.AbInitio when moving methods
1284: #
1.72 richard 1285: # Revision 1.71 2000/09/26 14:05:28 richard
1286: # Move checkString methods from XMLSchema.py, because they may need to look
1287: # at *instance* in-scope namespaces
1288: #
1.71 richard 1289: # Revision 1.70 2000/09/26 13:38:49 ht
1290: # protect against undefined list itemType/union memberType
1291: #
1.70 ht 1292: # Revision 1.69 2000/09/23 11:17:31 ht
1293: # merge in CR branch
1294: #
1.69 ht 1295:
1296: # Revision 1.68 2000/09/23 11:14:26 ht
1297: # towards merge in CR branch
1298: #
1.68 ht 1299: # Revision 1.66.2.3 2000/09/21 09:14:33 ht
1300: # property name change
1301: #
1302: # Revision 1.66.2.2 2000/09/11 12:23:27 ht
1303: # Move to branch: more debug in vv crash
1304: #
1305: # Revision 1.68 2000/09/03 15:57:23 ht
1306: # more debug in vv crash
1307:
1308: # Revision 1.67 2000/09/11 12:59:09 ht
1309: # allow stdin,
1310: # fix stupid bug missing third schema on command line
1311:
1312: # Revision 1.67 2000/08/31 11:48:41 ht
1313: # Direct support for validating lists and unions
1314:
1.67 ht 1315: # Revision 1.66 2000/08/22 13:11:30 ht
1316: # handle type w/o qname as document validation type
1317: # remove special treatment for AbInitio simple types on elements,
1318: # thereby fixing list validation bug
1.69 ht 1319:
1320: # Revision 1.66.2.3 2000/09/21 09:14:33 ht
1321: # property name change
1.67 ht 1322: #
1.69 ht 1323: # Revision 1.66.2.2 2000/09/11 12:23:27 ht
1324: # Move to branch: more debug in vv crash
1325: #
1326: # Revision 1.68 2000/09/03 15:57:23 ht
1327: # more debug in vv crash
1328: #
1329: # Revision 1.67 2000/08/31 11:48:41 ht
1330: # Direct support for validating lists and unions
1331: #
1332:
1.66 ht 1333: # Revision 1.66 2000/08/22 13:11:30 ht
1334: # handle type w/o qname as document validation type
1.65 ht 1335: # remove special treatment for AbInitio simple types on elements,
1.64 ht 1336: # thereby fixing list validation bug
1337: #
1338: # Revision 1.65 2000/07/12 09:31:58 ht
1.63 ht 1339: # try harder to always have a schema
1340: #
1341: # Revision 1.64 2000/07/10 14:39:02 ht
1342: # prepare for fileinfo to runit
1.62 ht 1343: #
1344: # Revision 1.63 2000/07/05 09:05:37 ht
1345: # change name to PyLTXML
1.61 ht 1346: #
1347: # Revision 1.62 2000/07/03 09:37:38 ht
1348: # bail out if textonly has elt daughter(s)
1.60 ht 1349: # add missing import
1350: #
1351: # Revision 1.61 2000/06/27 09:25:51 ht
1.59 ht 1352: # attempt to handle interaction between xsi:type and <any>
1353: #
1354: # Revision 1.60 2000/06/24 11:17:07 ht
1.58 ht 1355: # fix bug in unqualified xsi:type
1356: #
1357: # Revision 1.59 2000/06/22 10:31:33 ht
1358: # Bug in unique processing -- broke on missing field
1359: #
1360: # Revision 1.58 2000/06/20 08:07:42 ht
1361: # merge xmlout branches back in to main line
1362: #
1363:
1364: # Revision 1.57 2000/05/18 08:01:25 ht
1365: # fix bug in handling of xsi:type
1366: #
1367: # Revision 1.56 2000/05/14 12:19:34 ht
1368: # add context to checkSting calls
1369: #
1370: # Revision 1.55 2000/05/11 11:55:57 ht
1371: # just better handling of lax validation from other branch
1372: #
1373: # Revision 1.54.2.16 2000/06/15 16:03:20 ht
1374: # cover several missing definition cases
1375: #
1376: # Revision 1.54.2.15 2000/06/03 16:29:30 ht
1377: # oops, removing debugging comment
1378: #
1379: # Revision 1.54.2.14 2000/06/03 13:45:55 ht
1380: # catch arity bug in xsi:schemaLoc
1381: #
1382: # Revision 1.54.2.13 2000/05/30 09:35:43 ht
1383: # fix encoding bug when things break down altogether
1384: #
1385: # Revision 1.54.2.12 2000/05/29 08:46:53 ht
1386: # strong enforcement of nullable
1387: # add error codes to all errors
1388: # remove remaining __class__ tests
1389: # change error reporting wrt disallowed content
1390: #
1391: # Revision 1.54.2.11 2000/05/24 20:46:47 ht
1392: # make validateText a method, split across SimpleType and AbInitio
1393: #
1394: # Revision 1.54.2.10 2000/05/24 12:03:28 ht
1395: # modest effort to validate list types
1396: # fix bug in noNamespaceSchemaLocation handling at validation time
1397: #
1398: # Revision 1.54.2.9 2000/05/22 16:11:52 ht
1399: # use OpenStream, take more control of encoding
1400: #
1401: # Revision 1.54.2.8 2000/05/18 17:37:40 ht
1402: # parameterise stylesheet,
1403: # remove formatting from xsv:xsv attributes,
1404: # add namespace decl
1405: #
1406: # Revision 1.54.2.7 2000/05/18 07:59:48 ht
1407: # fix xsi:type validation bug
1408: #
1409: # Revision 1.54.2.6 2000/05/16 16:31:11 ht
1410: # fix bug handling un-typed element declarations == urType validation
1411: #
1412: # Revision 1.54.2.5 2000/05/14 12:29:59 ht
1413: # merge QName checking from main branch
1414: #
1415: # Revision 1.54.2.4 2000/05/12 15:15:01 ht
1416: # process keys even if type is simple,
1417: # add a few codes to get started
1418: #
1419: # Revision 1.54.2.3 2000/05/11 13:59:11 ht
1420: # convert verror/vwarn to produce elements
1421: # eliminate a few special error outputs in favour of special
1422: # sub-elements
1.57 ht 1423: #
1424: # Revision 1.54.2.2 2000/05/11 11:14:00 ht
1425: # more error protection
1.56 ht 1426: # handle lax recursively and at the start
1427: #
1428: # Revision 1.54.2.1 2000/05/10 11:36:47 ht
1.55 ht 1429: # begin converting to XML output
1430: #
1431: # Revision 1.56 2000/05/14 12:19:34 ht
1.54 ht 1432: # add context to checkSting calls
1433: #
1434: # Revision 1.55 2000/05/11 11:55:57 ht
1435: # just better handling of lax validation from other branch
1.53 ht 1436: #
1437: # Revision 1.54 2000/05/09 14:52:52 ht
1438: # Check for strings in a way that works with or without 16-bit support
1.52 richard 1439: #
1440: # Revision 1.53 2000/05/09 12:27:58 ht
1441: # replace our hack with python's url parsing stuff
1.51 ht 1442: # make f global for debugging
1443: #
1444: # Revision 1.52 2000/05/05 15:15:45 richard
1.50 richard 1445: # wrong (?) elt arg to verror in validateKeyRefs
1446: #
1447: # Revision 1.51 2000/05/04 07:56:35 ht
1.49 ht 1448: # Fix typo in opportunistic attribute validation
1449: #
1450: # Revision 1.50 2000/05/01 15:07:00 richard
1.48 richard 1451: # bug fix schema -> key.schema
1452: #
1453: # Revision 1.49 2000/05/01 10:05:43 ht
1454: # catch various missing file errors more gracefully
1.47 richard 1455: #
1456: # Revision 1.48 2000/04/28 15:40:01 richard
1457: # Implement xsi:null (still don't check nullable)
1.46 ht 1458: #
1459: # Revision 1.47 2000/04/28 15:11:23 richard
1460: # allow xsi: attributes on simple type
1461: # moved eltDecl code up validateElement ready for implementing xsi:null
1.45 ht 1462: #
1463: # Revision 1.46 2000/04/27 09:41:18 ht
1464: # remove raw types from error messages
1.44 ht 1465: #
1466: # Revision 1.45 2000/04/27 09:30:21 ht
1467: # check that inputs are actually schemas,
1468: # remove schema arg to doImport, checkInSchema
1469: #
1470: # Revision 1.44 2000/04/26 13:00:40 ht
1.43 ht 1471: # add copyright
1472: #
1473: # Revision 1.43 2000/04/24 20:46:40 ht
1.42 ht 1474: # cleanup residual bugs with massive rename,
1475: # rename Any to Wildcard,
1476: # replace AnyAttribute with Wildcard,
1477: # get validation of Wildcard working in both element and attribute contexts
1.41 ht 1478: #
1479: # Revision 1.42 2000/04/24 15:08:34 ht
1480: # minor glitches, tiny.xml works again
1.40 ht 1481: #
1482: # Revision 1.41 2000/04/24 15:00:09 ht
1483: # wholesale name changes -- init. caps for all classes,
1.39 ht 1484: # schema.py -> XMLSchema.py
1485: #
1486: # Revision 1.40 2000/04/24 11:09:17 ht
1.38 ht 1487: # make version string universally available
1488: #
1489: # Revision 1.39 2000/04/24 10:06:59 ht
1.37 ht 1490: # add version info to message
1491: #
1492: # Revision 1.38 2000/04/24 10:02:39 ht
1493: # change invocation message
1.36 ht 1494: #
1495: # Revision 1.37 2000/04/24 09:41:43 ht
1496: # clean up invocation some more, add k arg't to runit
1.35 ht 1497: #
1498: # Revision 1.36 2000/04/21 09:32:21 ht
1499: # another dose of resolveURL
1.34 ht 1500: # use tiny only if run from command line
1501: #
1502: # Revision 1.35 2000/04/20 22:12:43 ht
1.33 ht 1503: # use resolveURL on input, schemaLocs
1504: #
1505: # Revision 1.34 2000/04/20 15:45:08 ht
1506: # better handling of use of ns uri for loc
1507: #
1508: # Revision 1.33 2000/04/20 14:26:59 ht
1509: # merge in private and comp branches
1510: #
1511: # Revision 1.32.2.5 2000/04/20 14:25:54 ht
1512: # merge in comp branch
1513: #
1514: # Revision 1.32.2.4.2.9 2000/04/20 14:22:39 ht
1515: # manage document validation schema creation and search better
1516: #
1517: # Revision 1.32.2.4.2.8 2000/04/20 12:03:21 ht
1518: # Remove a few lingering effectiveTypes
1519: # Allow better for absent types etc.
1520: #
1521: # Revision 1.32.2.4.2.7 2000/04/14 21:18:27 ht
1522: # minor attr names/path changes to track schema
1523: #
1524: # Revision 1.32.2.4.2.6 2000/04/13 23:04:39 ht
1525: # allow for urType as simple type (?)
1526: # track Any->AnyWrap change
1527: #
1528: # Revision 1.32.2.4.2.5 2000/04/12 17:29:37 ht
1529: # begin work on model merger,
1530: #
1531: # Revision 1.32.2.4.2.4 2000/04/11 18:13:17 ht
1532: # interpolate attributeUse between complexType and attributeDeclaration,
1533: # parallel to particle
1534: #
1535: # Revision 1.32.2.4.2.3 2000/04/10 15:48:46 ht
1536: # put modest attribute validation in place
1537: #
1538: # Revision 1.32.2.4.2.2 2000/04/09 16:13:26 ht
1539: # working on complex type, attribute;
1540: # back out component.qname
1541: #
1542: # Revision 1.32.2.4.2.1 2000/04/05 12:12:36 ht
1543: # accommodate changes in schema.py
1544: #
1545: # Revision 1.32.2.4 2000/04/01 18:01:25 ht
1546: # various minor compatibility fixes
1547: #
1548: # Revision 1.32.2.3 2000/03/25 12:12:27 ht
1549: # restructure error handling/reporting;
1550: # allow for switching 208 on and off
1551: #
1552: # Revision 1.32.2.2 2000/03/21 15:57:23 ht
1553: # fix bug in skip,
1.32 ht 1554: # allow 208 override
1555: #
1556: # Revision 1.32.2.1 2000/03/20 17:22:52 ht
1557: # better coverage of <any>, including beginning of processcontents
1558: #
1559: # Revision 1.33 2000/03/20 17:20:53 ht
1560: # better coverage of <any>, including beginning of processcontents
1561: #
1562: # Revision 1.32 2000/03/08 15:28:46 ht
1563: # merge private branches back into public after 20000225 release
1564: #
1565: # Revision 1.31.2.3 2000/02/24 23:40:32 ht
1566: # fix any bug
1567: #
1568: # Revision 1.31.2.2 2000/02/21 09:18:13 ht
1569: # bug in <any> handling
1570: #
1.31 richard 1571: # Revision 1.31.2.1 2000/02/08 21:43:39 ht
1572: # fork private branch to track internal drafts
1573: # change calling sequence of checkinSchema
1.30 richard 1574: #
1575: # Revision 1.31.1.1 2000/02/08 13:54:25 ht
1576: # fork branch for non-public changes
1.29 ht 1577: # calling sequence to checkinSchema changed
1578: #
1579: # Revision 1.31 2000/01/13 16:55:42 richard
1580: # Finally do something with xsi:type
1.28 ht 1581: #
1582: # Revision 1.30 2000/01/10 17:36:34 richard
1583: # changes for xsi:schemaLocation
1.27 richard 1584: #
1585: # Revision 1.29 2000/01/08 23:33:50 ht
1586: # towards support for xsi:schemaLocation
1.26 ht 1587: #
1588: # Revision 1.28 2000/01/08 12:07:38 ht
1589: # Change command-line arg sequence in preparation for use of schemaLocation!!!!!
1.25 ht 1590: # Add debug printout for schemaLocation for now
1591: #
1592: # Revision 1.27 2000/01/07 17:08:26 richard
1593: # start on xsi:type
1594: #
1.24 ht 1595: # Revision 1.26 2000/01/06 14:59:38 ht
1.1 ht 1596: # fix command line bug, display args on entry
1597: #
1598: # Revision 1.25 2000/01/06 14:38:56 ht
1599: # detect cross-scope keyref and signal error
1600: #
1601: # Revision 1.24 2000/01/03 17:02:37 ht
1602: # Include result of sub-ordinate key checking in overall result
1603: # Accommodate new calling sequence for xpath.find
1604: # add Log and Id
1605: #
1606: #
Webmaster