xsvalBase.py
Go to the documentation of this file.
00001 #
00002 # minixsv, Release 0.9.0
00003 # file: xsvalBase.py
00004 #
00005 # XML schema validator base class
00006 #
00007 # history:
00008 # 2004-10-07 rl   created
00009 # 2006-08-18 rl   W3C testsuite passed for supported features
00010 # 2007-06-14 rl   Features for release 0.8 added, several bugs fixed
00011 #
00012 # Copyright (c) 2004-2008 by Roland Leuthe.  All rights reserved.
00013 #
00014 # --------------------------------------------------------------------
00015 # The minixsv XML schema validator is
00016 #
00017 # Copyright (c) 2004-2008 by Roland Leuthe
00018 #
00019 # By obtaining, using, and/or copying this software and/or its
00020 # associated documentation, you agree that you have read, understood,
00021 # and will comply with the following terms and conditions:
00022 #
00023 # Permission to use, copy, modify, and distribute this software and
00024 # its associated documentation for any purpose and without fee is
00025 # hereby granted, provided that the above copyright notice appears in
00026 # all copies, and that both that copyright notice and this permission
00027 # notice appear in supporting documentation, and that the name of
00028 # the author not be used in advertising or publicity
00029 # pertaining to distribution of the software without specific, written
00030 # prior permission.
00031 #
00032 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
00033 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
00034 # ABILITY AND FITNESS.  IN NO EVENT SHALL THE AUTHOR
00035 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
00036 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00037 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00038 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
00039 # OF THIS SOFTWARE.
00040 # --------------------------------------------------------------------
00041 
00042 import string
00043 import copy
00044 from ..minixsv             import *
00045 from ..genxmlif.xmlifUtils import collapseString, convertToAbsUrl, NsNameTupleFactory, NsNameTuple
00046 from xsvalSimpleTypes    import XsSimpleTypeVal, SimpleTypeError
00047 
00048 
00049 wxsdTree = None
00050 wxsdLookupDict = {}
00051 
00052 
00053 ##########################################################
00054 #  Validator class for validating one input file against one XML schema file
00055 
00056 class XsValBase:
00057 
00058     def __init__(self, xmlIf, errorHandler, verbose):
00059         self.xmlIf         = xmlIf
00060         self.errorHandler  = errorHandler
00061         self.verbose       = verbose
00062 
00063         self._raiseError   = self.errorHandler.raiseError
00064         self._addError     = self.errorHandler.addError
00065         self._addWarning   = self.errorHandler.addWarning
00066         self._addInfo      = self.errorHandler.addInfo
00067 
00068         self.checkKeyrefList = []
00069 
00070 
00071     def unlink(self):
00072         self.simpleTypeVal.unlink()
00073         
00074 
00075     ########################################
00076     # validate inputTree against xsdTree
00077     #
00078     def validate (self, inputTree, xsdTreeList):
00079         self.inputTree = inputTree
00080 
00081         self.inputRoot   = self.inputTree.getRootNode()
00082 
00083         self.inputNsURI  = self.inputRoot.getNamespaceURI()
00084         self.inputNsPrefix = self.inputRoot.getNsPrefix(self.inputRoot.getNsName())
00085         if self.inputNsPrefix != None:
00086             self.inputNsPrefixString = "%s:" %(self.inputNsPrefix)
00087         else:
00088             self.inputNsPrefixString = ""
00089 
00090         # initialise lookup dictionary
00091         global wxsdLookupDict
00092         if wxsdLookupDict == {}:
00093             wxsdLookupDict = {"ElementDict":{}, "TypeDict":{}, "GroupDict":{},
00094                               "AttrGroupDict":{}, "AttributeDict":{}, "IdentityConstrDict":{}}
00095             self._importWellknownSchemas(wxsdLookupDict)
00096    
00097         self.xsdLookupDict = {"ElementDict":        wxsdLookupDict["ElementDict"].copy(), 
00098                               "TypeDict":           wxsdLookupDict["TypeDict"].copy(), 
00099                               "GroupDict":          wxsdLookupDict["GroupDict"].copy(),
00100                               "AttrGroupDict":      wxsdLookupDict["AttrGroupDict"].copy(), 
00101                               "AttributeDict":      wxsdLookupDict["AttributeDict"].copy(), 
00102                               "IdentityConstrDict": wxsdLookupDict["IdentityConstrDict"].copy()}
00103         self.xsdElementDict        = self.xsdLookupDict["ElementDict"]
00104         self.xsdTypeDict           = self.xsdLookupDict["TypeDict"]
00105         self.xsdGroupDict          = self.xsdLookupDict["GroupDict"]
00106         self.xsdAttrGroupDict      = self.xsdLookupDict["AttrGroupDict"]
00107         self.xsdAttributeDict      = self.xsdLookupDict["AttributeDict"]
00108         self.xsdIdentityConstrDict = self.xsdLookupDict["IdentityConstrDict"]
00109 
00110         self.xsdIdDict = {}
00111         self.xsdIdRefDict = {}
00112         self.idAttributeForType = None
00113 
00114         for xsdTree in xsdTreeList:
00115             xsdRoot     = xsdTree.getRootNode()
00116 
00117             # TODO: The following member may differ if several schema files are used!!
00118             self.xsdNsURI    = xsdRoot.getNamespaceURI()
00119 
00120             self.xsdIncludeDict = {xsdRoot.getAbsUrl():1,}
00121             if xsdRoot.getFilePath() != os.path.join (MINIXSV_DIR, "XMLSchema.xsd"):
00122                 self._initInternalAttributes (xsdRoot)
00123                 self._updateLookupTables(xsdRoot, self.xsdLookupDict)
00124             
00125                 self._includeAndImport (xsdTree, xsdTree, self.xsdIncludeDict, self.xsdLookupDict)
00126             
00127 
00128         self.simpleTypeVal = XsSimpleTypeVal(self)
00129 
00130         inputRootNsName = self.inputRoot.getNsName()
00131         if self.xsdElementDict.has_key(inputRootNsName):
00132             # start recursive schema validation
00133             try:
00134                 self._checkElementTag (self.xsdElementDict[inputRootNsName], self.inputRoot, (self.inputRoot,), 0)
00135             except TagException, errInst:
00136                 self._addError (errInst.errstr, errInst.node, errInst.endTag)
00137 
00138             if not self.errorHandler.hasErrors():
00139                 # validate IDREFs
00140                 for idref in self.xsdIdRefDict.keys():
00141                     if not self.xsdIdDict.has_key(idref):
00142                         self._addError ("There is no ID/IDREF binding for IDREF %s" %repr(idref), self.xsdIdRefDict[idref])
00143 
00144                 # validate keyrefs
00145                 for inputElement, keyrefNode in self.checkKeyrefList:
00146                     self._checkKeyRefConstraint (keyrefNode, inputElement)
00147         else:
00148             self._raiseError ("Used root tag %s not found in schema file(s)!"
00149                               %repr(inputRootNsName), self.inputRoot)
00150         
00151 
00152     ########################################
00153     # include/import all files specified in the schema file
00154     # import well-known schemas
00155     #
00156     def _includeAndImport (self, baseTree, tree, includeDict, lookupDict):
00157         self._expandIncludes (baseTree, tree, includeDict, lookupDict)
00158         self._expandRedefines (baseTree, tree, includeDict, lookupDict)
00159         self._expandImports (baseTree, tree, includeDict, lookupDict)
00160 
00161 
00162     ########################################
00163     # expand include directives
00164     #
00165     def _expandIncludes (self, baseTree, tree, includeDict, lookupDict):
00166         rootNode = tree.getRootNode()
00167         namespaceURI  = rootNode.getNamespaceURI()
00168         for includeNode in rootNode.getChildrenNS(namespaceURI, "include"):
00169             includeUrl = includeNode.getAttribute("schemaLocation")
00170             expNamespace = rootNode.getAttributeOrDefault("targetNamespace", None)
00171             self._includeSchemaFile (baseTree, tree, includeNode, expNamespace, includeUrl, includeNode.getBaseUrl(), includeDict, lookupDict,
00172                                      adaptTargetNamespace=1)
00173             rootNode.removeChild (includeNode)
00174 
00175 
00176     ########################################
00177     # expand redefine directives
00178     #
00179     def _expandRedefines (self, baseTree, tree, includeDict, lookupDict):
00180         rootNode = tree.getRootNode()
00181         namespaceURI  = rootNode.getNamespaceURI()
00182 
00183         for redefineNode in rootNode.getChildrenNS(namespaceURI, "redefine"):
00184             redefineUrl = redefineNode.getAttribute("schemaLocation")
00185             expNamespace = rootNode.getAttributeOrDefault("targetNamespace", None)
00186             self._includeSchemaFile (baseTree, tree, redefineNode, expNamespace, redefineUrl, redefineNode.getBaseUrl(), includeDict, lookupDict,
00187                                      adaptTargetNamespace=1)
00188 
00189             # fill lookup tables with redefined definitions
00190             for childNode in redefineNode.getChildren():
00191                 redefineNode.removeChild(childNode)
00192                 rootNode.insertBefore(childNode, redefineNode)
00193 
00194                 if childNode.getLocalName() in ("complexType", "simpleType"):
00195                     xsdDict = self.xsdLookupDict["TypeDict"]
00196                 elif childNode.getLocalName() in ("attributeGroup"):
00197                     xsdDict = self.xsdLookupDict["AttrGroupDict"]
00198                 elif childNode.getLocalName() in ("group"):
00199                     xsdDict = self.xsdLookupDict["GroupDict"]
00200                 elif childNode.getLocalName() in ("annotation"):
00201                     continue
00202                 else:
00203                     self._addError ("%s not allowed as child of 'redefine'!" %repr(childNode.getLocalName()), childNode)
00204                     continue
00205 
00206                 redefType = NsNameTuple ( (expNamespace, childNode.getAttribute("name")) )
00207                 if xsdDict.has_key(redefType):
00208                     orgRedefType = NsNameTuple( (expNamespace, redefType[1]+"__ORG") )
00209                     if not xsdDict.has_key(orgRedefType):
00210                         xsdDict[orgRedefType] = xsdDict[redefType]
00211 #                    else:
00212 #                        self._addError ("Duplicate component %s found within 'redefine'!" %repr(redefType), childNode)
00213                     xsdDict[redefType] = childNode
00214                 else:
00215                     self._addError ("Type %s not found in imported schema file!" %(repr(redefType)), childNode)
00216 
00217                 dummy, attrNodes, attrNsNameFirst = childNode.getXPathList (".//@base | .//@ref" % vars())
00218                 for attrNode in attrNodes:
00219                     if attrNode.hasAttribute("base"):
00220                         attribute = "base"
00221                     elif attrNode.hasAttribute("ref"):
00222                         attribute = "ref"
00223                     if attrNode.getQNameAttribute(attribute) == redefType:
00224                         attrNode[attribute] = attrNode[attribute] + "__ORG"
00225                 
00226             rootNode.removeChild (redefineNode)
00227 
00228 
00229     ########################################
00230     # expand import directives
00231     #
00232     def _expandImports (self, baseTree, tree, includeDict, lookupDict):
00233         rootNode = tree.getRootNode()
00234         namespaceURI  = rootNode.getNamespaceURI()
00235 
00236         for includeNode in rootNode.getChildrenNS(namespaceURI, "import"):
00237             expNamespace = includeNode.getAttributeOrDefault("namespace", None)
00238             if expNamespace == self._getTargetNamespace(includeNode):
00239                 self._addError ("Target namespace and target namespace of imported schema must not be the same!",  includeNode)
00240                 continue
00241 
00242             includeUrl = includeNode.getAttributeOrDefault("schemaLocation", None)
00243             if expNamespace != None and includeUrl == None:
00244                 includeUrl = expNamespace + ".xsd"
00245             if includeUrl != None:            
00246                 if expNamespace not in (XML_NAMESPACE, XSI_NAMESPACE):
00247                     self._includeSchemaFile (baseTree, tree, includeNode, expNamespace, includeUrl, includeNode.getBaseUrl(), includeDict, lookupDict)
00248             else:
00249                 self._addError ("schemaLocation attribute for import directive missing!",  includeNode)
00250             rootNode.removeChild (includeNode)
00251 
00252 
00253     ########################################
00254     # import well-known schema files
00255     #
00256     def _importWellknownSchemas (self, lookupDict):
00257         global wxsdTree
00258         file = os.path.join (MINIXSV_DIR, "XMLSchema.xsd")
00259         wxsdTree = self.xmlIf.parse (file)
00260         self._initInternalAttributes (wxsdTree.getRootNode())
00261         self._updateLookupTables (wxsdTree.getRootNode(), lookupDict)
00262 
00263         for schemaFile in ("datatypes.xsd", "xml.xsd", "XMLSchema-instance.xsd"):
00264             file = os.path.join (MINIXSV_DIR, schemaFile)
00265             subTree = self._parseIncludeSchemaFile(wxsdTree, wxsdTree, None, file, None)
00266             self._updateLookupTables (subTree.getRootNode(), lookupDict)
00267 
00268 
00269     ########################################
00270     # include/import a schema file
00271     #
00272     def _includeSchemaFile (self, baseTree, tree, nextSibling, expNamespace, includeUrl, baseUrl, includeDict, lookupDict, 
00273                             adaptTargetNamespace=0):
00274         if includeUrl == None:
00275             self._raiseError ("Schema location attribute missing!", nextSibling)
00276         absUrl = convertToAbsUrl (includeUrl, baseUrl)
00277         if includeDict.has_key (absUrl):
00278             # file already included
00279             return
00280 
00281         if self.verbose:
00282             print "including %s..." %(includeUrl)
00283         rootNode = tree.getRootNode()
00284 
00285         subTree = self._parseIncludeSchemaFile(baseTree, tree, nextSibling, includeUrl, baseUrl)
00286         includeDict[absUrl] = 1
00287 
00288         stRootNode = subTree.getRootNode()
00289         if rootNode.getNsName() != stRootNode.getNsName():
00290             self._raiseError ("Root tag of file %s does not match!" %repr(includeUrl), nextSibling)
00291 
00292         if stRootNode.hasAttribute("targetNamespace"):
00293             if expNamespace != stRootNode["targetNamespace"]:
00294                 self._raiseError ("Target namespace of file %s does not match!" %repr(includeUrl), nextSibling)
00295         else:
00296            if expNamespace != None: 
00297                if adaptTargetNamespace:
00298                     # if no target namespace is specified in the included file
00299                     # the target namespace of the parent file is taken
00300                     stRootNode["targetNamespace"] = expNamespace
00301                     for stDescNode in stRootNode.getIterator():
00302                         stDescNode.curNs.append((EMPTY_PREFIX,expNamespace))
00303                else:
00304                    self._raiseError ("Target namespace of file %s does not match!" %repr(includeUrl), nextSibling)
00305                     
00306         self._updateLookupTables (subTree.getRootNode(), lookupDict)
00307         self._includeAndImport (baseTree, subTree, includeDict, lookupDict)
00308         if includeUrl not in (r"C:\Program Files\Python24\Lib\site-packages\minixsv\xml.xsd",
00309                               r"C:\Program Files\Python24\Lib\site-packages\minixsv\XMLSchema.xsd",
00310                               r"C:\Program Files\Python24\Lib\site-packages\minixsv\XMLSchema-instance.xsd"):
00311             rootNode.insertSubtree (nextSibling, subTree, insertSubTreeRootNode=0)
00312 
00313 
00314     def _parseIncludeSchemaFile (self, baseTree, tree, nextSibling, includeUrl, baseUrl):
00315         # try to parse included schema file
00316         try:
00317             subTree = self.xmlIf.parse (includeUrl, baseUrl, baseTree.getTree())
00318             self._initInternalAttributes (subTree.getRootNode())
00319         except IOError, errInst:
00320             self._raiseError ("%s" %str(errInst), nextSibling)
00321         except SyntaxError, e:
00322             # FIXME: sometimes an URLError is catched instead of a standard IOError
00323             try:
00324                 dummy = e.errno
00325             except: 
00326                 raise IOError, e
00327             
00328             if e.errno in (2, "socket error", "url error"): # catch IOError: No such file or directory
00329                 self._raiseError ("%s: '%s'" %(e.strerror, e.filename), nextSibling)
00330             else:
00331                 raise
00332         
00333         return subTree
00334 
00335     ########################################
00336     # update lookup dictionaries used during validation
00337     #
00338     def _updateLookupTables (self, rootNode, lookupDict):
00339         schemaTagDict = {"element"    : "ElementDict",
00340                          "complexType": "TypeDict",
00341                          "simpleType" : "TypeDict",
00342                          "group"      : "GroupDict",
00343                          "attributeGroup": "AttrGroupDict",
00344                          "attribute"     : "AttributeDict",
00345                         }
00346 
00347         # retrieve all schema tags
00348         for localName, lookupDictName in schemaTagDict.items():
00349             for node in rootNode.getChildrenNS(XSD_NAMESPACE, localName):
00350                 targetNamespace = self._getTargetNamespace(node)
00351                 if not lookupDict[lookupDictName].has_key((targetNamespace, node.getAttribute("name"))):
00352                     lookupDict[lookupDictName][(targetNamespace, node.getAttribute("name"))] = node
00353         
00354         # retrieve all identity constraints
00355         for identConstrTagName in ("unique", "key", "keyref"):
00356             identConstrNodeList = rootNode.getElementsByTagNameNS (XSD_NAMESPACE, identConstrTagName)
00357             for identConstrNode in identConstrNodeList:
00358                 targetNamespace = self._getTargetNamespace(identConstrNode)
00359                 identConstrNsLocalName = NsNameTupleFactory ( (targetNamespace, identConstrNode.getAttribute("name")) )
00360                 if not lookupDict["IdentityConstrDict"].has_key(identConstrNsLocalName):
00361                     lookupDict["IdentityConstrDict"][identConstrNsLocalName] = {"Node": identConstrNode, "ValueDict":{}}
00362 
00363 #                else:
00364 #                    self._addError ("Duplicate identity constraint name %s found!"
00365 #                                    %(repr(identConstrNsLocalName)), identConstrNode)
00366 
00367     ########################################
00368     # validate inputNode against complexType node
00369     #
00370     def _initInternalAttributes (self, rootNode):
00371         # set schema root node for all descendant nodes
00372         if not rootNode.getSchemaRootNode():
00373             for node in rootNode.getIterator():
00374                 node.setSchemaRootNode(rootNode)
00375 
00376 
00377     ########################################
00378     # validate inputNode against complexType node
00379     #
00380     def _checkComplexTypeTag (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType=None):
00381         baseTypeAttributes = {}
00382 
00383         complexContentNode = xsdNode.getFirstChildNS(self.xsdNsURI, "complexContent")
00384         simpleContentNode = xsdNode.getFirstChildNS(self.xsdNsURI, "simpleContent")
00385         if complexContentNode != None:
00386             inputChildIndex, baseTypeAttributes = self._checkComplexContentTag (xsdParentNode, complexContentNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00387         elif simpleContentNode != None:
00388             inputChildIndex, baseTypeAttributes = self._checkSimpleContentTag (xsdParentNode, simpleContentNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00389         else:
00390             inputChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00391             if usedAsBaseType == None:
00392                 self._checkMixed (xsdParentNode, xsdNode, inputNode)
00393         return inputChildIndex, baseTypeAttributes
00394 
00395     def _checkComplexContentTag (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00396         extensionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "extension")
00397         if extensionNode != None:
00398             inputChildIndex, baseTypeAttributes = self._checkExtensionComplexContent (xsdParentNode, extensionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00399         else:
00400             restrictionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "restriction")
00401             if restrictionNode != None:
00402                 inputChildIndex, baseTypeAttributes = self._checkRestrictionComplexContent (xsdParentNode, restrictionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00403             else:
00404                 raise AttributeError, "RestrictionNode not found!"
00405 
00406 #        if usedAsBaseType == None:
00407 #            self._checkMixed (xsdNode, inputNode)
00408         return inputChildIndex, baseTypeAttributes
00409 
00410     def _checkSimpleContentTag (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00411         if inputNode.getAttribute( (XSI_NAMESPACE, "nil") ) == "true":
00412             if inputNode.getChildren() != [] or collapseString(inputNode.getElementValue()) != "":
00413                 self._addError ("Element must be empty (xsi:nil='true')(1)!" , inputNode, 0)
00414 
00415         extensionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "extension")
00416         if extensionNode != None:
00417             inputChildIndex, baseTypeAttributes = self._checkExtensionSimpleContent (xsdParentNode, extensionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00418         else:
00419             restrictionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "restriction")
00420             if restrictionNode != None:
00421                 inputChildIndex, baseTypeAttributes = self._checkRestrictionSimpleContent (xsdParentNode, xsdNode, restrictionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00422         return inputChildIndex, baseTypeAttributes
00423 
00424     def _checkExtensionComplexContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00425         baseNsName = xsdNode.getQNameAttribute("base")
00426         if usedAsBaseType == None: 
00427             extUsedAsBaseType = "extension"
00428         else:
00429             extUsedAsBaseType = usedAsBaseType
00430         inputChildIndex, baseTypeAttributes = self._checkComplexTypeTag (xsdParentNode, self.xsdTypeDict[baseNsName], inputNode, inputChildIndex, extUsedAsBaseType)
00431 
00432         inputChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00433         return inputChildIndex, baseTypeAttributes
00434 
00435     def _checkExtensionSimpleContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00436         self._checkSimpleType (xsdNode, "base", inputNode, inputNode.getTagName(), inputNode.getElementValue(), None, checkAttribute=0)
00437         if xsdNode.hasAttribute("BaseTypes"):
00438             xsdParentNode["BaseTypes"] = xsdNode["BaseTypes"]
00439         inputChildIndex, baseTypeAttributes = self._checkSimpleTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00440         return inputChildIndex, baseTypeAttributes
00441 
00442     def _checkRestrictionComplexContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00443         # first check against base type (retrieve only the base type attributes)
00444         baseNsName = xsdNode.getQNameAttribute("base")
00445         inputChildIndex, baseTypeAttributes = self._checkComplexTypeTag (xsdParentNode, self.xsdTypeDict[baseNsName], inputNode, inputChildIndex, "restriction")
00446 
00447         # then check input against derived complex type
00448         inputChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00449         return inputChildIndex, baseTypeAttributes
00450 
00451     def _checkRestrictionSimpleContent (self, xsdParentNode, simpleContentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00452         try:
00453             simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
00454             self.simpleTypeVal.checkSimpleTypeDef (inputNode, simpleContentNode, inputNode.getTagName(), inputNode.getElementValue(), simpleTypeReturnDict, idCheck=1)
00455             xsdNode["BaseTypes"] = string.join (simpleTypeReturnDict["BaseTypes"], " ")
00456         except SimpleTypeError, errInst:
00457             self._addError (errInst.args[0], inputNode)
00458 
00459         inputChildIndex, baseTypeAttributes = self._checkSimpleTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
00460         return inputChildIndex, baseTypeAttributes
00461 
00462     def _checkComplexTypeContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00463         if inputNode.getAttribute((XSI_NAMESPACE, "nil")) == "true":
00464             if inputNode.getChildren() != [] or collapseString(inputNode.getElementValue()) != "":
00465                 self._addError ("Element must be empty (xsi:nil='true')(2)!" , inputNode, 0)
00466         else:
00467             childTags = inputNode.getChildren()
00468             if usedAsBaseType in (None, "extension"):
00469                 validChildTags = xsdNode.getChildren()
00470                 for validChildTag in validChildTags:
00471                     if validChildTag.getLocalName() not in ("attribute", "attributeGroup", "anyAttribute"):
00472                         inputChildIndex = self._checkParticle (validChildTag, inputNode, childTags, inputChildIndex)
00473 
00474                 if usedAsBaseType == None and inputChildIndex < len (childTags):
00475                     inputNsName = inputNode.getNsName()
00476                     childNsName = childTags[inputChildIndex].getNsName()
00477                     self._addError ("Unexpected or invalid child tag %s found in tag %s!"
00478                                     %(repr(childNsName), repr(inputNsName)), childTags[inputChildIndex])
00479 
00480         if usedAsBaseType in (None,):
00481             self._checkAttributeTags (xsdParentNode, xsdNode, inputNode, baseTypeAttributes)
00482 
00483         if usedAsBaseType in ("restriction", "extension"):
00484             self._updateAttributeDict (xsdNode, baseTypeAttributes)
00485 
00486         return inputChildIndex, baseTypeAttributes
00487 
00488     def _checkSimpleTypeContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
00489         if inputNode.getChildren() != []:
00490             raise TagException ("No child tags are allowed for element %s!" %repr(inputNode.getNsName()), inputNode)
00491 
00492         if usedAsBaseType in (None,):
00493             self._checkAttributeTags (xsdParentNode, xsdNode, inputNode, baseTypeAttributes)
00494 
00495         if usedAsBaseType in ("restriction", "extension"):
00496             self._updateAttributeDict (xsdNode, baseTypeAttributes)
00497 
00498         return inputChildIndex, baseTypeAttributes
00499 
00500 
00501     ########################################
00502     # validate mixed content (1)
00503     #
00504     def _checkMixed (self, xsdParentNode, xsdNode, inputNode):
00505         if xsdNode.getAttributeOrDefault ("mixed", "false") == "false":
00506             if not collapseString(inputNode.getElementValue()) in ("", " "):
00507                 self._addError ("Mixed content not allowed for %s!" %repr(inputNode.getTagName()), inputNode)
00508         else: # mixed = true
00509             self._checkUrType(xsdParentNode, inputNode)
00510 
00511 
00512     ########################################
00513     # check ur-type
00514     #
00515     def _checkUrType (self, xsdNode, inputNode):
00516         prefix = xsdNode.getPrefix()
00517         if prefix:
00518             xsdNode["__CONTENTTYPE__"] = "%s:string" %xsdNode.getPrefix()
00519         else:
00520             xsdNode["__CONTENTTYPE__"] = "string"
00521         self._checkElementValue (xsdNode, "__CONTENTTYPE__", inputNode)
00522         xsdNode.removeAttribute("__CONTENTTYPE__")
00523     
00524 
00525     ########################################
00526     # validate inputNodeList against xsdNode
00527     #
00528     def _checkList (self, elementMethod, xsdNode, inputParentNode, inputNodeList, currIndex):
00529         minOccurs = string.atoi(xsdNode.getAttributeOrDefault("minOccurs", "1"))
00530         maxOccurs = xsdNode.getAttributeOrDefault("maxOccurs", "1")
00531         if maxOccurs != "unbounded":
00532             maxOccurs = string.atoi(maxOccurs)
00533         else:
00534             maxOccurs = -1
00535         occurs = 0
00536         while maxOccurs == -1 or occurs < maxOccurs:
00537             try:
00538                 newIndex = elementMethod (xsdNode, inputParentNode, inputNodeList, currIndex)
00539                 occurs += 1
00540                 if newIndex > currIndex:
00541                     currIndex = newIndex
00542                 else:
00543                     break # no suitable element found
00544             except TagException, errInst:
00545                 break
00546 
00547         if occurs == 0 and minOccurs > 0:
00548             raise errInst
00549         elif occurs < minOccurs:
00550             expInputTagName = xsdNode.getAttribute("name")
00551             if expInputTagName == None:
00552                 expInputTagName = xsdNode.getQNameAttribute("ref")
00553             raise TagException ("minOccurs (%d) of child tag %s in tag %s not available (only %d)!"
00554                                 %(minOccurs, repr(expInputTagName), repr(inputParentNode.getTagName()), occurs), inputParentNode, 1)
00555 
00556         return currIndex
00557 
00558     ########################################
00559     # validate inputNode against element node
00560     #
00561     def _checkElementTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00562         if xsdNode.hasAttribute("ref"):
00563             refNsName = xsdNode.getQNameAttribute("ref")
00564             currIndex = self._checkElementTag (self.xsdElementDict[refNsName], inputParentNode, inputNodeList, currIndex)
00565         else:
00566             nameAttr = xsdNode.getAttribute ("name")
00567 
00568             if currIndex >= len (inputNodeList):
00569                 raise TagException ("Missing child tag %s in tag %s!" %(repr(nameAttr), repr(inputParentNode.getTagName())), inputParentNode, 1)
00570 
00571             inputNode = inputNodeList[currIndex]
00572             if nameAttr != inputNode.getLocalName():
00573                 raise TagException ("Missing child tag %s in tag %s!" %(repr(nameAttr), repr(inputParentNode.getTagName())), inputNode, 0)
00574 
00575             # store reference to XSD definition node
00576             inputNode.setXsdNode(xsdNode)
00577 
00578             currIndex = currIndex + 1
00579 
00580             self._checkInputElementForm (xsdNode, nameAttr, inputNode)
00581 
00582             if (xsdNode.getFirstChild() == None and 
00583                 not xsdNode.hasAttribute("type") and 
00584                 not inputNode.hasAttribute((XSI_NAMESPACE, "type")) ):
00585                 self._checkUrType(xsdNode, inputNode)
00586                 # ur-type => try to check children of input node
00587                 for inputChild in inputNode.getChildren():
00588                     try:
00589                         if self.xsdElementDict.has_key(inputChild.getNsName()):
00590                             self._checkElementTag (self.xsdElementDict[inputChild.getNsName()], inputNode, (inputChild,), 0)
00591                     except TagException, errInst:
00592                         self._addError (errInst.errstr, errInst.node, errInst.endTag)
00593                 return currIndex
00594             
00595             complexTypeNode = xsdNode.getFirstChildNS (self.xsdNsURI, "complexType")
00596             if not inputNode.hasAttribute((XSI_NAMESPACE, "type")):
00597                 typeNsName = xsdNode.getQNameAttribute ("type")
00598             else:
00599                 # overloaded type is used
00600                 typeNsName = inputNode.getQNameAttribute((XSI_NAMESPACE, "type"))
00601                 if not self.xsdTypeDict.has_key(typeNsName):
00602                     self._addError ("Unknown overloaded type %s!" %(repr(typeNsName)), inputNode, 0)
00603                     return currIndex
00604 
00605             if self.xsdTypeDict.has_key (typeNsName):
00606                 typeType = self.xsdTypeDict[typeNsName].getLocalName()
00607                 if typeType == "complexType":
00608                     complexTypeNode = self.xsdTypeDict[typeNsName]
00609                 # else simpleType => pass, handled later on
00610 
00611             if complexTypeNode != None:
00612                 try:
00613                     self._checkComplexTypeTag (xsdNode, complexTypeNode, inputNode, 0)
00614                 except TagException, errInst:
00615                     self._addError (errInst.errstr, errInst.node, errInst.endTag)
00616                     return currIndex
00617             else:
00618                 self._checkElementSimpleType (xsdNode, "type", inputNode)
00619 
00620             # check unique attributes and keys
00621             childUniqueDefList = xsdNode.getChildrenNS (self.xsdNsURI, "unique")
00622             for childUniqueDef in childUniqueDefList:
00623                 self._checkIdentityConstraint (childUniqueDef, inputNode)
00624 
00625             childKeyDefList = xsdNode.getChildrenNS (self.xsdNsURI, "key")
00626             for childKeyDef in childKeyDefList:
00627                 self._checkIdentityConstraint (childKeyDef, inputNode)
00628 
00629             childKeyrefDefList = xsdNode.getChildrenNS (self.xsdNsURI, "keyref")
00630             for childKeyrefDef in childKeyrefDefList:
00631                 self.checkKeyrefList.append ((inputNode, childKeyrefDef))
00632 
00633         return currIndex
00634 
00635 
00636     ########################################
00637     # validate element inputNode against simple type definition
00638     #
00639     def _checkElementSimpleType (self, xsdNode, xsdTypeAttr, inputNode):
00640         if inputNode.getChildren() != []:
00641             raise TagException ("No child tags are allowed for element %s!" %(repr(inputNode.getNsName())), inputNode)
00642 
00643         self._checkElementValue (xsdNode, xsdTypeAttr, inputNode)
00644 
00645         self._checkAttributeTags (xsdNode, xsdNode, inputNode, {})
00646 
00647 
00648     ########################################
00649     # validate inputNode against simple type definition
00650     #
00651     def _checkElementValue (self, xsdNode, xsdTypeAttr, inputNode):
00652         fixedValue = xsdNode.getAttribute("fixed")
00653         if inputNode.getAttribute((XSI_NAMESPACE, "nil")) == "true" and fixedValue != None:
00654             self._addError ("There must be no fixed value for Element because xsi:nil='true' is specified!" , inputNode)
00655 
00656         if inputNode.getAttribute((XSI_NAMESPACE, "nil")) != "true" and inputNode.getElementValue() == "":
00657             if xsdNode.hasAttribute("default"):
00658                 inputNode.setElementValue(xsdNode["default"])
00659             if fixedValue != None:
00660                 inputNode.setElementValue(fixedValue)
00661 
00662         self._checkSimpleType (xsdNode, xsdTypeAttr, inputNode, inputNode.getTagName(), inputNode.getElementValue(), fixedValue, checkAttribute=0)
00663 
00664 
00665     ########################################
00666     # validate inputNode against simple type definition
00667     #
00668     def _checkSimpleType (self, xsdNode, xsdTypeAttr, inputNode, attrName, attrValue, fixedValue, checkAttribute=0, checkId=1):
00669         retValue = None
00670 
00671         if checkAttribute == 0 and inputNode.hasAttribute((XSI_NAMESPACE, "nil")):
00672             if (inputNode[(XSI_NAMESPACE, "nil")] == "true" and
00673                 collapseString(inputNode.getElementValue()) != ""):
00674                 self._addError ("Element must be empty (xsi:nil='true')(3)!" , inputNode, 0)
00675             return retValue
00676         
00677         try:
00678             simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
00679             fixedValueReturnDict = {"BaseTypes":[], "primitiveType":None}
00680             simpleTypeNode  = xsdNode.getFirstChildNS (self.xsdNsURI, "simpleType")
00681             if simpleTypeNode != None:
00682                 self.simpleTypeVal.checkSimpleTypeDef (inputNode, simpleTypeNode, attrName, attrValue, simpleTypeReturnDict, checkId)
00683                 if fixedValue != None:
00684                     self.simpleTypeVal.checkSimpleTypeDef (inputNode, simpleTypeNode, attrName, fixedValue, fixedValueReturnDict, idCheck=0)
00685             elif (xsdNode.getFirstChildNS (self.xsdNsURI, "complexType") != None and
00686                   xsdNode.getFirstChildNS (self.xsdNsURI, "complexType").getAttribute("mixed") == "false"):
00687                 self._addError ("Attribute %s requires a simple or mixed type!" %repr(attrName), inputNode)
00688             else:
00689                 typeNsName = xsdNode.getQNameAttribute (xsdTypeAttr)
00690                 if typeNsName != (None, None):
00691                     self.simpleTypeVal.checkSimpleType (inputNode, attrName, typeNsName, attrValue, simpleTypeReturnDict, checkId)
00692                 # TODO: What to check if no type is specified for the element?
00693                     if fixedValue != None:
00694                         self.simpleTypeVal.checkSimpleType (inputNode, attrName, typeNsName, fixedValue, fixedValueReturnDict, idCheck=0)
00695             
00696             xsdNode["BaseTypes"] = string.join (simpleTypeReturnDict["BaseTypes"], " ")
00697             xsdNode["primitiveType"] = str(simpleTypeReturnDict["primitiveType"])
00698 
00699             retValue = simpleTypeReturnDict
00700             if simpleTypeReturnDict.has_key("wsAction"):
00701                 if checkAttribute:
00702                     attrValue = inputNode.processWsAttribute(attrName, simpleTypeReturnDict["wsAction"])
00703                 else:
00704                     attrValue = inputNode.processWsElementValue(simpleTypeReturnDict["wsAction"])
00705 
00706             if fixedValue != None:
00707                 if fixedValueReturnDict.has_key("orderedValue"):
00708                     fixedValue = fixedValueReturnDict["orderedValue"]
00709                 elif fixedValueReturnDict.has_key("adaptedAttrValue"):
00710                     fixedValue = fixedValueReturnDict["adaptedAttrValue"]
00711                 if simpleTypeReturnDict.has_key("orderedValue"):
00712                     attrValue = simpleTypeReturnDict["orderedValue"]
00713                 if attrValue != fixedValue:
00714                     if checkAttribute:
00715                         self._addError ("Attribute %s must have fixed value %s!" %(repr(attrName), repr(fixedValue)), inputNode)
00716                     else:
00717                         self._addError ("Element must have fixed value %s!" %repr(fixedValue), inputNode)
00718                         
00719         except SimpleTypeError, errInst:
00720             self._addError (errInst.args[0], inputNode)
00721 
00722         return retValue
00723 
00724     ########################################
00725     # validate inputNode against sequence node
00726     #
00727     def _checkSequenceTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00728         for xsdChildNode in xsdNode.getChildren():
00729             currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
00730         return currIndex
00731 
00732 
00733     ########################################
00734     # validate inputNode against choice node
00735     #
00736     def _checkChoiceTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00737         childFound = 0
00738         exceptionRaised = 0
00739         for xsdChildNode in xsdNode.getChildren():
00740             try:
00741                 newIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
00742                 if newIndex > currIndex:
00743                     currIndex = newIndex
00744                     childFound = 1
00745                     break
00746                 else:
00747                     exceptionRaised = 0
00748             except TagException, errInst:
00749                 exceptionRaised = 1
00750         else:
00751             if not childFound and exceptionRaised:
00752                 if currIndex < len(inputNodeList):
00753                     currNode = inputNodeList[currIndex]
00754                     endTag = 0
00755                 else:
00756                     currNode = inputParentNode
00757                     endTag = 1
00758                 raise TagException ("No suitable child tag for choice found!", currNode, endTag)
00759 
00760         return currIndex
00761 
00762 
00763     ########################################
00764     # validate inputNode against group node
00765     #
00766     def _checkGroupTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00767         if xsdNode.hasAttribute("ref"):
00768             refNsName = xsdNode.getQNameAttribute("ref")
00769             currIndex = self._checkGroupTag (self.xsdGroupDict[refNsName], inputParentNode, inputNodeList, currIndex)
00770         else:
00771             for xsdChildNode in xsdNode.getChildren():
00772                 currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
00773         return currIndex
00774 
00775 
00776     ########################################
00777     # validate inputNode against all node
00778     #
00779     def _checkAllTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00780         oldIndex = currIndex
00781         xsdChildDict = {}
00782         for xsdChildNode in xsdNode.getChildren():
00783             if xsdChildNode.getNsName() != (XSD_NAMESPACE, "annotation"):
00784                 xsdChildDict[xsdChildNode] = 0
00785         while (currIndex < len(inputNodeList)) and (0 in xsdChildDict.values()):
00786             currNode = inputNodeList[currIndex]
00787             for xsdChildNode in xsdChildDict.keys():
00788                 try:
00789                     newIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
00790                     if newIndex == currIndex:
00791                         continue
00792                 except TagException, errInst:
00793                     continue
00794 
00795                 if xsdChildDict[xsdChildNode] == 0:
00796                     xsdChildDict[xsdChildNode] = 1
00797                     currIndex = newIndex
00798                     break
00799                 else:
00800                     raise TagException ("Ambiguous child tag %s found in all-group!" %repr(currNode.getTagName()), currNode)
00801             else:
00802                 raise TagException ("Unexpected child tag %s for all-group found!" %repr(currNode.getTagName()), currNode)
00803 
00804         for xsdChildNode, occurs in xsdChildDict.items():
00805             if xsdChildNode.getAttributeOrDefault("minOccurs", "1") != "0" and occurs == 0:
00806                 raise TagException ("Child tag %s missing in all-group (%s)" %(repr(xsdChildNode.getAttribute("name")), repr(inputParentNode.getTagName())), inputParentNode)
00807 
00808         return currIndex
00809 
00810 
00811     ########################################
00812     # validate inputNode against any node
00813     #
00814     def _checkAnyTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00815         if currIndex >= len (inputNodeList):
00816             raise TagException ("Missing child tag (anyTag) in tag %s!" %repr(inputParentNode.getTagName()), inputParentNode, 1)
00817 
00818         inputNode = inputNodeList[currIndex]
00819         inputNamespace = inputNode.getNamespaceURI()
00820         self._checkWildcardElement (xsdNode, inputNode, inputNamespace)
00821 
00822         currIndex = currIndex + 1
00823         return currIndex
00824 
00825 
00826     ########################################
00827     # validate inputNode against particle
00828     #
00829     def _checkParticle (self, xsdNode, inputParentNode, inputNodeList, currIndex):
00830         xsdTagName = xsdNode.getLocalName()
00831         if xsdTagName == "element":
00832             currIndex = self._checkList (self._checkElementTag, xsdNode, inputParentNode, inputNodeList, currIndex)
00833         elif xsdTagName == "choice":
00834             currIndex = self._checkList (self._checkChoiceTag, xsdNode, inputParentNode, inputNodeList, currIndex)
00835         elif xsdTagName == "sequence":
00836             currIndex = self._checkList (self._checkSequenceTag, xsdNode, inputParentNode, inputNodeList, currIndex)
00837         elif xsdTagName == "group":
00838             currIndex = self._checkList (self._checkGroupTag, xsdNode, inputParentNode, inputNodeList, currIndex)
00839         elif xsdTagName == "all":
00840             currIndex = self._checkList (self._checkAllTag, xsdNode, inputParentNode, inputNodeList, currIndex)
00841         elif xsdTagName == "any":
00842             currIndex = self._checkList (self._checkAnyTag, xsdNode, inputParentNode, inputNodeList, currIndex)
00843         elif xsdTagName == "annotation":
00844             # TODO: really nothing to check??
00845             pass
00846         else:
00847             self._addError ("Internal error: Invalid tag %s found!" %repr(xsdTagName))
00848         return currIndex
00849 
00850 
00851     ########################################
00852     # validate attributes of inputNode against complexType node
00853     #
00854     def _checkAttributeTags (self, parentNode, xsdNode, inputNode, validAttrDict):
00855         # retrieve all valid attributes for this element from the schema file
00856         self._updateAttributeDict (xsdNode, validAttrDict)
00857         inputAttrDict = {}
00858         for iAttrName, iAttrValue in inputNode.getAttributeDict().items():
00859             # skip namespace declarations
00860             if iAttrName[0] != XMLNS_NAMESPACE and iAttrName[1] != "xmlns":
00861                 inputAttrDict[iAttrName] = iAttrValue
00862 
00863         for qAttrName, validAttrEntry in validAttrDict.items():
00864             attrRefNode = validAttrEntry["RefNode"]
00865             # global attributes use always form "qualified"
00866             if self.xsdAttributeDict.has_key(qAttrName) and self.xsdAttributeDict[qAttrName] == attrRefNode:
00867                 attributeForm = "qualified"
00868             else:
00869                 attributeForm = attrRefNode.getAttributeOrDefault ("form", self._getAttributeFormDefault(xsdNode))
00870             attrRefNode.setAttribute ("form", attributeForm)
00871             self._checkAttributeTag (qAttrName, validAttrEntry["Node"], attrRefNode, inputNode, inputAttrDict)
00872 
00873         for inputAttribute in inputAttrDict.keys():
00874             if inputAttribute == (XSI_NAMESPACE, "type"):
00875                 pass # for attribute xsi:type refer _checkElementTag
00876             elif inputAttribute == (XSI_NAMESPACE, "nil"):
00877                 if parentNode.getAttributeOrDefault ("nillable", "false") == "false":
00878                     self._addError ("Tag %s hasn't been defined as nillable!" %repr(inputNode.getTagName()), inputNode)
00879             elif inputNode == self.inputRoot and inputAttribute in ((XSI_NAMESPACE, "noNamespaceSchemaLocation"), (XSI_NAMESPACE, "schemaLocation")):
00880                 pass
00881             elif validAttrDict.has_key("__ANY_ATTRIBUTE__"):
00882                 xsdNode = validAttrDict["__ANY_ATTRIBUTE__"]["Node"]
00883                 try:
00884                     inputNamespace = inputAttribute[0]
00885                     if inputAttribute[0] == None and xsdNode.getAttribute("form") == "unqualified":
00886                         # TODO: Check: If only local namespace is allowed, do not use target namespace???
00887                         if xsdNode.getAttribute("namespace") != "##local":
00888                             inputNamespace = self._getTargetNamespace(xsdNode)
00889                     self._checkWildcardAttribute (xsdNode, inputNode, inputAttribute, inputNamespace, inputAttrDict)
00890                 except TagException:
00891                     self._addError ("Unexpected attribute %s in Tag %s!" %(repr(inputAttribute), repr(inputNode.getTagName())), inputNode)
00892             else:
00893                 self._addError ("Unexpected attribute %s in Tag %s!" %(repr(inputAttribute), repr(inputNode.getTagName())), inputNode)
00894 
00895 
00896     ########################################
00897     # validate one attribute (defined by xsdNode) of inputNode
00898     #
00899     def _checkAttributeTag (self, qAttrName, xsdAttrNode, xsdAttrRefNode, inputNode, inputAttrDict):
00900         targetNamespace = self._getTargetNamespace(xsdAttrNode)
00901         if qAttrName[0] == targetNamespace and xsdAttrRefNode.getAttribute("form") == "unqualified":
00902             qAttrName = NsNameTupleFactory( (None, qAttrName[1]) )
00903         
00904         use = xsdAttrNode.getAttribute("use")
00905         if use == None: use = xsdAttrRefNode.getAttributeOrDefault ("use", "optional")
00906         fixedValue = xsdAttrNode.getAttribute("fixed")
00907         if fixedValue == None: 
00908             fixedValue = xsdAttrRefNode.getAttribute("fixed")
00909 
00910         if inputAttrDict.has_key(qAttrName):
00911             if use == "prohibited":
00912                 self._addError ("Attribute %s is prohibited in this context!" %repr(qAttrName[1]), inputNode)
00913         elif inputAttrDict.has_key((targetNamespace, qAttrName[1])):
00914             self._addError ("Local attribute %s must be unqualified!" %(repr(qAttrName)), inputNode)
00915             del inputAttrDict[(targetNamespace, qAttrName[1])]
00916         elif inputAttrDict.has_key((None, qAttrName[1])) and qAttrName[0] == targetNamespace:
00917             self._addError ("Attribute %s must be qualified!" %repr(qAttrName[1]), inputNode)
00918             del inputAttrDict[(None, qAttrName[1])]
00919         else:
00920             if use == "required":
00921                 self._addError ("Attribute %s is missing!" %(repr(qAttrName)), inputNode)
00922             elif use == "optional":
00923                 if xsdAttrRefNode.hasAttribute("default"):
00924                     if not (inputNode.getNsName() == (XSD_NAMESPACE, "element") and
00925                             inputNode.hasAttribute("ref") and
00926                             xsdAttrRefNode.getAttribute("name") == "nillable"):
00927                         defaultValue = xsdAttrRefNode.getAttribute("default")
00928                         inputNode.setAttribute(qAttrName, defaultValue)
00929                         inputAttrDict[qAttrName] = defaultValue
00930                 elif fixedValue != None:
00931                     inputNode.setAttribute(qAttrName, fixedValue)
00932                     inputAttrDict[qAttrName] = fixedValue
00933 
00934         if inputAttrDict.has_key(qAttrName):
00935             attributeValue = inputAttrDict[qAttrName]
00936             self._checkSimpleType (xsdAttrRefNode, "type", inputNode, qAttrName, attributeValue, fixedValue, 1)
00937             del inputAttrDict[qAttrName]
00938             inputNode.setXsdAttrNode(qAttrName, xsdAttrRefNode)
00939 
00940 
00941     ########################################
00942     # update dictionary of valid attributes
00943     #
00944     def _updateAttributeDict (self, xsdNode, validAttrDict, checkForDuplicateAttr=0, recursionKeys=None):
00945         # TODO: Why can recursionKeys not be initialized by default variable??
00946         if recursionKeys == None: recursionKeys = {} 
00947         validAttributeNodes = xsdNode.getChildrenNS(self.xsdNsURI, "attribute")
00948         for validAttrGroup in xsdNode.getChildrenNS(self.xsdNsURI, "attributeGroup"):
00949             refNsName = validAttrGroup.getQNameAttribute("ref")
00950             if self.xsdAttrGroupDict.has_key(refNsName):
00951                 if recursionKeys.has_key(refNsName):
00952                     self._addError ("Circular definition for attribute group %s detected!" %(repr(refNsName)), validAttrGroup)
00953                     continue
00954                 recursionKeys[refNsName] = 1
00955                 self._updateAttributeDict(self.xsdAttrGroupDict[refNsName], validAttrDict, checkForDuplicateAttr, recursionKeys)
00956                
00957 
00958         for validAttributeNode in validAttributeNodes:
00959             if validAttributeNode.hasAttribute("ref"):
00960                 attrKey = validAttributeNode.getQNameAttribute("ref")
00961                 attributeRefNode = self.xsdAttributeDict[attrKey]
00962             else:
00963                 attrKey = validAttributeNode.getQNameAttribute("name")
00964                 attrKey = (self._getTargetNamespace(validAttributeNode), validAttributeNode.getAttribute("name"))
00965                 attributeRefNode = validAttributeNode
00966                 
00967             if checkForDuplicateAttr and validAttrDict.has_key(attrKey):
00968                 self._addError ("Duplicate attribute %s found!" %repr(attrKey), validAttributeNode)
00969             else:
00970                 validAttrDict[attrKey] = {"Node":validAttributeNode, "RefNode":attributeRefNode}
00971 
00972         anyAttributeNode = xsdNode.getFirstChildNS(self.xsdNsURI, "anyAttribute")
00973         if anyAttributeNode != None:
00974             validAttrDict["__ANY_ATTRIBUTE__"] = {"Node":anyAttributeNode, "RefNode":anyAttributeNode}
00975 
00976 
00977     ########################################
00978     # validate wildcard specification of anyElement
00979     #
00980     def _checkWildcardElement (self, xsdNode, inputNode, inputNamespace):
00981         processContents = xsdNode.getAttributeOrDefault("processContents", "lax")
00982 
00983         self._checkInputNamespace (xsdNode, inputNode, inputNamespace)
00984 
00985         inputNsName = inputNode.getNsName()
00986         if processContents == "skip":
00987             pass
00988         else:
00989             if inputNode.hasAttribute((XSI_NAMESPACE, "type")):
00990                 # overloaded type is used
00991                 typeNsName = inputNode.getQNameAttribute((XSI_NAMESPACE, "type"))
00992                 if not self.xsdTypeDict.has_key(typeNsName):
00993                     self._addError ("Unknown overloaded type %s!" %(repr(typeNsName)), inputNode, 0)
00994                 else:
00995                     typeType = self.xsdTypeDict[typeNsName].getLocalName()
00996                     if typeType == "complexType":
00997                         try:
00998                             self._checkComplexTypeTag (None, self.xsdTypeDict[typeNsName], inputNode, 0)
00999                         except TagException, errInst:
01000                             self._addError (errInst.errstr, errInst.node, errInst.endTag)
01001                     else:
01002                         simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
01003                         try:
01004                             self.simpleTypeVal.checkSimpleType (inputNode, inputNode.getLocalName(), typeNsName, inputNode.getElementValue(), simpleTypeReturnDict, idCheck=1)
01005                         except SimpleTypeError, errInst:
01006                             self._addError (errInst.args[0], inputNode)
01007 
01008             elif self.xsdElementDict.has_key(inputNsName):
01009                 self._checkElementTag (self.xsdElementDict[inputNsName], None, (inputNode,), 0)
01010 
01011             elif processContents == "strict":
01012                 self._addError ("Element definition %s not found in schema file!" %repr(inputNsName), inputNode)
01013                 
01014 
01015     ########################################
01016     # validate wildcard specification of anyElement/anyAttribute
01017     #
01018     def _checkWildcardAttribute (self, xsdNode, inputNode, qAttrName, inputNamespace, inputAttrDict):
01019         processContents = xsdNode.getAttributeOrDefault("processContents", "strict")
01020 
01021         self._checkInputNamespace (xsdNode, inputNode, inputNamespace)
01022 
01023         if processContents == "skip":
01024             pass
01025         elif processContents == "lax":
01026             if self.xsdAttributeDict.has_key(qAttrName):
01027                 attrNode = self.xsdAttributeDict[qAttrName]
01028                 self._checkAttributeTag (qAttrName, attrNode, attrNode, inputNode, inputAttrDict)
01029         elif processContents == "strict":
01030             if self.xsdAttributeDict.has_key(qAttrName):
01031                 attrNode = self.xsdAttributeDict[qAttrName]
01032                 self._checkAttributeTag (qAttrName, attrNode, attrNode, inputNode, inputAttrDict)
01033             else:
01034                 self._addError ("Attribute definition %s not found in schema file!" %repr(qAttrName), inputNode)
01035                 
01036 
01037     ########################################
01038     # validate wildcard specification of anyElement/anyAttribute
01039     #
01040     def _checkInputNamespace (self, xsdNode, inputNode, inputNamespace):
01041         targetNamespace = self._getTargetNamespace(xsdNode)
01042         namespaces = xsdNode.getAttributeOrDefault("namespace", "##any")
01043         if namespaces == "##any":
01044             pass   # nothing to check
01045         elif namespaces == "##other":
01046             if inputNamespace == targetNamespace or inputNamespace == None:
01047                 raise TagException ("Node or attribute must not be part of target namespace or local!", inputNode)
01048         else:
01049             for namespace in string.split(collapseString(namespaces), " "):
01050                 if namespace == "##local" and inputNamespace == None:
01051                     break
01052                 elif namespace == "##targetNamespace" and inputNamespace == targetNamespace:
01053                     break
01054                 elif namespace == inputNamespace:
01055                     break
01056             else:
01057                 raise TagException ("Node or attribute is not part of namespace %s!" %repr(namespaces), inputNode)
01058 
01059 
01060     ########################################
01061     # validate unique and key definition
01062     #
01063     def _checkIdentityConstraint (self, identityConstrNode, inputNode):
01064         identConstrTag = identityConstrNode.getLocalName()
01065         identConstrName = identityConstrNode.getAttribute ("name")
01066         identConstrNsLocalName = (self._getTargetNamespace(identityConstrNode), identConstrName)
01067         selectorXPathNode = identityConstrNode.getFirstChildNS (self.xsdNsURI, "selector")
01068         selectorNodeList, dummy, dummy = self._getXPath (inputNode, selectorXPathNode)
01069         
01070         valueDict = {}
01071         for selectorNode in selectorNodeList:
01072             fieldXPathNodeList = identityConstrNode.getChildrenNS (self.xsdNsURI, "field")
01073             keyValue = []
01074             baseTypesList = []
01075             for fieldXPathNode in fieldXPathNodeList:
01076                 fieldChildList, attrNodeList, attrName = self._getXPath (selectorNode, fieldXPathNode, identConstrTag)
01077                 if len(fieldChildList) > 1:
01078                     self._addError ("The field xPath %s of %s %s must evaluate to exactly 0 or 1 node!" %(repr(fieldXPathNode["xpath"]), repr(identConstrTag), repr(identConstrName)), selectorNode)
01079                     return
01080 
01081                 for fieldChild in fieldChildList:
01082                     if attrNodeList == []:
01083                         inputChild = fieldChild
01084                         try:
01085                             baseTypes = self._setBaseTypes(fieldChild.getXsdNode())
01086                         except:
01087                             baseTypes = ((XSD_NAMESPACE, "anyType"),)
01088                         value = fieldChild.getElementValue()
01089                     else:
01090                         inputChild = attrNodeList[0]
01091                         try:
01092                             baseTypes = self._setBaseTypes(attrNodeList[0].getXsdAttrNode(attrName))
01093                         except:
01094                             baseTypes = ((XSD_NAMESPACE, "anyType"),)
01095                         value = fieldChild
01096                     if baseTypes != None:
01097                         if baseTypes[0] in ((XSD_NAMESPACE, "anyType"), (XSD_NAMESPACE, "anySimpleType")):
01098                             overloadedType = inputChild.getQNameAttribute((XSI_NAMESPACE, "type"))
01099                             if overloadedType != (None, None):
01100                                 baseTypes = [inputChild.getQNameAttribute((XSI_NAMESPACE, "type")),]
01101                     else:
01102                         self._addError ("Identity constraint does not have a simple type!", inputChild)
01103                         continue
01104                         
01105                     baseTypesList.append(baseTypes)
01106                     for baseType in baseTypes:
01107                         try:
01108                             value = self._getOrderedValue (inputChild, attrName, baseType, value)
01109                             break
01110                         except SimpleTypeError, errInst:
01111                             pass
01112                     keyValue.append (value)
01113 
01114             if keyValue != []:
01115                 keyValue = tuple(keyValue)
01116                 if not valueDict.has_key (keyValue):
01117                     valueDict[keyValue] = 1
01118                     self.xsdIdentityConstrDict[identConstrNsLocalName]["ValueDict"][keyValue] = baseTypesList
01119                 else:
01120                     if len(keyValue) == 1:
01121                         self._addError ("Duplicate identity constraint values %s found for identity contraint %s!" %(repr(keyValue[0]), repr(identConstrName)), selectorNode)
01122                     else:
01123                         self._addError ("Duplicate identity constraint values %s found for identity contraint %s!" %(repr(keyValue), repr(identConstrName)), selectorNode)
01124 
01125     ########################################
01126     # validate unique and key definition
01127     #
01128     def _checkKeyRefConstraint (self, keyrefNode, inputNode):
01129         keyRefName = keyrefNode.getAttribute ("name")
01130         keyReference = keyrefNode.getQNameAttribute ("refer")
01131 
01132         selectorXPathNode = keyrefNode.getFirstChildNS (self.xsdNsURI, "selector")
01133         selectorNodeList, dummy, dummy = self._getXPath (inputNode, selectorXPathNode)
01134         for selectorNode in selectorNodeList:
01135             fieldXPathNodeList = keyrefNode.getChildrenNS(self.xsdNsURI, "field")
01136             keyValue = []
01137             for fieldXPathNode in fieldXPathNodeList:
01138                 fieldChildList, attrNodeList, attrName = self._getXPath (selectorNode, fieldXPathNode, "keyref")
01139                 if len(fieldChildList) > 1:
01140                     self._addError ("The field xPath of keyref %s must evaluate to exactly 0 or 1 node!" %repr(keyRefName), fieldXPathNode)
01141                     return
01142 
01143                 for fieldChild in fieldChildList:
01144                     if attrNodeList == []:
01145                         inputChild = fieldChild
01146                         baseTypes = self._setBaseTypes(fieldChild.getXsdNode())
01147                         value = fieldChild.getElementValue()
01148                     else:
01149                         inputChild = attrNodeList[0]
01150                         baseTypes = self._setBaseTypes(attrNodeList[0].getXsdAttrNode(attrName))
01151                         value = fieldChild
01152 
01153                     if baseTypes != None:
01154                         for baseType in baseTypes:
01155                             try:
01156                                 value = self._getOrderedValue (inputChild, attrName, baseType, value)
01157                                 break
01158                             except SimpleTypeError, errInst:
01159                                 pass
01160                     keyValue.append (value)
01161 
01162             keyValue = tuple(keyValue)
01163             if keyValue != ():
01164                 if not self.xsdIdentityConstrDict[keyReference]["ValueDict"].has_key (keyValue):
01165                     self._addError ("Key reference value %s is undefined for key type %s!" %(repr(keyValue), repr(keyReference)), selectorNode)
01166                 else:
01167                     baseTypesList = self.xsdIdentityConstrDict[keyReference]["ValueDict"][keyValue]
01168                     for fieldXPathNode, baseTypes in zip(fieldXPathNodeList, baseTypesList):
01169                         fieldChildList, attrNodeList, attrName = self._getXPath (selectorNode, fieldXPathNode, "keyref")
01170                         if attrNodeList == []:
01171                             inputChild = fieldChildList[0]
01172                             refBaseTypes = self._setBaseTypes(fieldChildList[0].getXsdNode())
01173                         else:
01174                             inputChild = attrNodeList[0]
01175                             refBaseTypes = self._setBaseTypes(inputChild.getXsdAttrNode(attrName))
01176                         if baseTypes[0] not in refBaseTypes and refBaseTypes[0] not in baseTypes:
01177                             if baseTypes[0] != (XSD_NAMESPACE, "anyType") and refBaseTypes[0] != (XSD_NAMESPACE, "anyType"):
01178                                 self._addError ("Key type and key reference type does not match (%s != %s)!" %(repr(baseTypes[0]), repr(refBaseTypes[0])), inputChild)
01179                     
01180     
01181     ########################################
01182     # check input element form
01183     #
01184     def _checkInputElementForm (self, xsdNode, xsdNodeNameAttr, inputNode):
01185         targetNamespace = self._getTargetNamespace(xsdNode)
01186         nsNameAttr = (targetNamespace, xsdNodeNameAttr)
01187         if self.xsdElementDict.has_key(nsNameAttr) and self.xsdElementDict[nsNameAttr] == xsdNode:
01188             elementForm = "qualified"
01189         else:
01190             elementForm = xsdNode.getAttributeOrDefault ("form", self._getElementFormDefault(xsdNode))
01191         if elementForm == "qualified":
01192             if inputNode.getNamespaceURI() == None:
01193                 if targetNamespace != None:
01194                     self._addError ("Element %s must be qualified!" %repr(xsdNodeNameAttr), inputNode)
01195             elif inputNode.getNamespaceURI() != targetNamespace:
01196                 self._addError ("%s undefined in specified namespace!" %repr(xsdNodeNameAttr), inputNode)
01197         elif elementForm == "unqualified" and inputNode.getNamespaceURI() != None:
01198             self._addError ("Local element %s must be unqualified!" %repr(xsdNodeNameAttr), inputNode)
01199 
01200 
01201     ########################################
01202     # retrieve ordered value and base types of given typeNsName
01203     #
01204     def _getOrderedValue (self, inputNode, attrName, typeNsName, attrValue):
01205         simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
01206         self.simpleTypeVal.checkSimpleType (inputNode, attrName, typeNsName, attrValue, simpleTypeReturnDict, idCheck=1)
01207         if simpleTypeReturnDict.has_key("orderedValue"):
01208             attrValue = simpleTypeReturnDict["orderedValue"]
01209         return attrValue
01210 
01211 
01212     ########################################
01213     # retrieve nodes/attributes specified by given xPath
01214     #
01215     def _getXPath (self, node, xPathNode, identityConstraint=None):
01216         xPath = xPathNode.getAttribute("xpath")
01217         try:
01218             attrIgnoreList = [(XSI_NAMESPACE, "nil")]
01219             childList, attrNodeList, attrName = node.getXPathList (xPath, namespaceRef=xPathNode, useDefaultNs=0, attrIgnoreList=attrIgnoreList)
01220         except Exception, errInst:
01221             self._addError (errInst.args, node)
01222             childList = []
01223             attrNodeList = []
01224             attrName = None
01225 
01226         if childList == []:
01227             if identityConstraint == "key":
01228                 self.errorHandler.addError ("Key is missing! XPath = %s!" %repr(xPath), node)
01229             elif identityConstraint in ("unique", "keyref"):
01230                 self.errorHandler.addWarning ("Identity constraint is missing! XPath = %s!" %repr(xPath), node)
01231         return childList, attrNodeList, attrName
01232 
01233 
01234     ########################################
01235     # retrieve basetypes from XML attribute (string format)
01236     #
01237     def _setBaseTypes (self, xsdNode):
01238         if xsdNode.getAttribute("BaseTypes") != None:
01239             baseTypes = string.split(xsdNode["BaseTypes"])
01240             baseTypeList = map (lambda basetype: NsNameTupleFactory(basetype), baseTypes)
01241             if baseTypeList != []:
01242                 return baseTypeList
01243             else:
01244                 return None
01245         else:
01246             return None
01247     
01248     ########################################
01249     # retrieve target namespace attribute for given node
01250     #
01251     def _getTargetNamespace(self, node):
01252         schemaRootNode = node.getSchemaRootNode()
01253         return schemaRootNode.getAttribute("targetNamespace")
01254 
01255 
01256     ########################################
01257     # retrieve element form default attribute for given node
01258     #
01259     def _getElementFormDefault(self, node):
01260         schemaRootNode = node.getSchemaRootNode()
01261         return schemaRootNode.getAttributeOrDefault("elementFormDefault", "unqualified")
01262 
01263     ########################################
01264     # retrieve element form default attribute for given node
01265     #
01266     def _getAttributeFormDefault(self, node):
01267         schemaRootNode = node.getSchemaRootNode()
01268         return schemaRootNode.getAttributeOrDefault("attributeFormDefault", "unqualified")
01269 
01270 
01271 ########################################
01272 # define own exception for XML schema validation errors
01273 #
01274 class TagException (StandardError):
01275     def __init__ (self, errstr="", node=None, endTag=0):
01276         self.node   = node
01277         self.errstr = errstr
01278         self.endTag = endTag
01279         StandardError.__init__(self)
01280 


mavlink
Author(s): Lorenz Meier
autogenerated on Thu Jun 6 2019 19:01:57