xsvalSchema.py
Go to the documentation of this file.
00001 #
00002 # minixsv, Release 0.9.0
00003 # file: xsvalSchema.py
00004 #
00005 # Derived validator class (for validation of schema files)
00006 #
00007 # history:
00008 # 2004-10-07 rl   created
00009 # 2006-08-18 rl   W3C testsuite passed for supported features
00010 # 2007-05-24 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 
00043 import string
00044 import re
00045 import os
00046 from decimal             import Decimal
00047 from ..genxmlif.xmlifUtils import collapseString
00048 from ..minixsv             import *
00049 from xsvalBase           import XsValBase, TagException
00050 from xsvalUtils          import substituteSpecialEscChars
00051 
00052 _localFacetDict = {(XSD_NAMESPACE,"list"): ("length", "minLength", "maxLength", "enumeration", "pattern", "whiteSpace"),
00053                    (XSD_NAMESPACE,"union"): ("enumeration", "pattern", "whiteSpace"),
00054                    (XSD_NAMESPACE,"anySimpleType"): ("whiteSpace"),}
00055 ###########################################################
00056 #  Derived validator class for validating one input schema file against the XML rules file
00057 
00058 class XsValSchema (XsValBase):
00059 
00060     ########################################
00061     # overloaded validate method
00062     #
00063     def validate (self, inputTree, xsdTree):
00064         XsValBase.validate(self, inputTree, xsdTree)
00065     
00066         self._initInternalAttributes (self.inputRoot)
00067         self._updateLookupTables (self.inputRoot, self.xsdLookupDict)
00068 
00069         self._includeAndImport (self.inputTree, self.inputTree, self.xsdIncludeDict, self.xsdLookupDict)
00070 
00071         if not self.errorHandler.hasErrors():
00072             # IDs must be unique within a schema file
00073             self.xsdIdDict = {}
00074 
00075             self._checkSchemaSecondLevel()
00076 
00077         # FIXME: Wellknown schemas are not included in the input tree although the internal attribute has been set!
00078         #        Better solution required than this workaround!
00079         self.inputRoot["__WellknownSchemasImported__"] = "false"
00080 
00081 
00082     ########################################
00083     # additional checks for schema files which are not covered by "xsStructs.xsd"
00084     #
00085     def _checkSchemaSecondLevel(self):
00086 
00087         targetNamespace = self.inputRoot.getAttribute("targetNamespace")
00088         if targetNamespace == "":
00089             self.errorHandler.raiseError("Empty string not allowed for target namespace!", self.inputRoot)
00090 
00091         self._checkElementNodesSecondLevel()
00092         self._checkNotationNodesSecondLevel()
00093         self._checkAnyNodesSecondLevel()
00094         self._checkGroupNodesSecondLevel()
00095         self._checkAttrGroupNodesSecondLevel()
00096         self._checkAttributeNodesSecondLevel()
00097         self._checkAnyAttributesSecondLevel()
00098 
00099         if self.errorHandler.hasErrors():
00100             return
00101 
00102         self._checkComplexTypesSecondLevel()
00103         self._checkSimpleTypesSecondLevel()
00104 
00105         self._checkParticlesSecondLevel()
00106 
00107         self._checkIdentityConstraintsSecondLevel()
00108         self._checkKeysSecondLevel()
00109         self._checkKeyRefsSecondLevel()
00110 
00111     ########################################
00112     # additional checks for element nodes
00113     #
00114     def _checkElementNodesSecondLevel(self):
00115         elementNodes = self.inputRoot.getElementsByTagNameNS (self.inputNsURI, "element")
00116         for elementNode in elementNodes:
00117             if not elementNode.hasAttribute("name") and not elementNode.hasAttribute("ref"):
00118                 self._addError ("Element must have 'name' or 'ref' attribute!", elementNode)
00119                 continue
00120 
00121             if elementNode.hasAttribute("ref"):
00122                 for attrName in ("name", "type", "form"):
00123                     if elementNode.hasAttribute(attrName):
00124                         self._addError ("Element with 'ref' attribute must not have %s attribute!" %repr(attrName), elementNode)
00125                         continue
00126 
00127             complexTypeNode = elementNode.getFirstChildNS (self.inputNsURI, "complexType")
00128             simpleTypeNode = elementNode.getFirstChildNS (self.inputNsURI, "simpleType")
00129             if elementNode.hasAttribute("ref") and (complexTypeNode != None or simpleTypeNode != None):
00130                 self._addError ("Element with 'ref' attribute must not have type definition!", elementNode)
00131                 continue
00132             if elementNode.hasAttribute("type") and (complexTypeNode != None or simpleTypeNode != None):
00133                 self._addError ("Element with 'type' attribute must not have type definition!", elementNode)
00134                 continue
00135             
00136             if elementNode.hasAttribute("ref"):
00137                 for forbiddenAttr in ("block", "nillable", "default", "fixed"):
00138                     if elementNode.hasAttribute(forbiddenAttr):
00139                         self._addError ("Element with 'ref' attribute must not have %s attribute!" %repr(forbiddenAttr), elementNode)
00140 
00141                 self._checkReference (elementNode, self.xsdElementDict)
00142 
00143             if elementNode.hasAttribute("type"):
00144                 self._checkType (elementNode, "type", self.xsdTypeDict)
00145 
00146             self._checkNodeId(elementNode)
00147             self._checkOccurs (elementNode)
00148             self._checkFixedDefault(elementNode)
00149 
00150 
00151     ########################################
00152     # additional checks for notation nodes
00153     #
00154     def _checkNotationNodesSecondLevel(self):
00155         notationNodes = self.inputRoot.getElementsByTagNameNS (self.inputNsURI, "notation")
00156         for notationNode in notationNodes:
00157             if not notationNode.hasAttribute("public") and not notationNode.hasAttribute("system"):
00158                 self._addError ("Notation must have 'public' or 'system' attribute!", notationNode)
00159     
00160     
00161     ########################################
00162     # additional checks for anyNodes
00163     #
00164     def _checkAnyNodesSecondLevel(self):
00165         anyNodes = self.inputRoot.getElementsByTagNameNS (self.inputNsURI, "any")
00166         for anyNode in anyNodes:
00167             self._checkOccurs (anyNode)
00168             # check for unique ID
00169             self._checkNodeId (anyNode)
00170 
00171 
00172     ########################################
00173     # additional checks for group nodes
00174     #
00175     def _checkGroupNodesSecondLevel(self):
00176         groupNodes = self.inputRoot.getElementsByTagNameNS (self.inputNsURI, "group")
00177         for groupNode in groupNodes:
00178             self._checkNodeId(groupNode)
00179             if groupNode.hasAttribute("ref"):
00180                 self._checkReference (groupNode, self.xsdGroupDict)
00181                 self._checkOccurs (groupNode)
00182         if self.errorHandler.hasErrors():
00183             return
00184 #        for groupNode in groupNodes:
00185 #            if groupNode.hasAttribute("name"):
00186 #                self._checkGroupNodeCircularDef(groupNode, {groupNode["name"]:1})
00187     
00188     def _checkGroupNodeCircularDef(self, groupNode, groupNameDict):
00189         childGroupsRefNodes, dummy, dummy = groupNode.getXPathList (".//%sgroup" %(self.inputNsPrefixString))
00190         for childGroupRefNode in childGroupsRefNodes:
00191             if childGroupRefNode.hasAttribute("ref"):
00192                 childGroupNode = self.xsdGroupDict[childGroupRefNode.getQNameAttribute("ref")]
00193                 if not groupNameDict.has_key(childGroupNode["name"]):
00194                     groupNameDict[childGroupNode["name"]] = 1
00195                     self._checkGroupNodeCircularDef(childGroupNode, groupNameDict)
00196                 else:
00197                     self._addError ("Circular definition of group %s!" %repr(childGroupNode["name"]), childGroupNode)
00198                 
00199 
00200     ########################################
00201     # additional checks for attributeGroup nodes
00202     #
00203     def _checkAttrGroupNodesSecondLevel(self):
00204         attributeGroupNodes = self.inputRoot.getElementsByTagNameNS (self.inputNsURI, "attributeGroup")
00205         for attributeGroupNode in attributeGroupNodes:
00206             if attributeGroupNode.hasAttribute("ref"):
00207                 self._checkReference (attributeGroupNode, self.xsdAttrGroupDict)
00208 
00209             self._checkNodeId(attributeGroupNode)
00210 
00211     ########################################
00212     # additional checks for attribute nodes
00213     #
00214     def _checkAttributeNodesSecondLevel(self):
00215         attributeNodes = self.inputRoot.getElementsByTagNameNS (XSD_NAMESPACE, "attribute")
00216         for attributeNode in attributeNodes:
00217             if os.path.basename(attributeNode.getFilePath()) != "XMLSchema-instance.xsd":
00218                 # global attributes must always be "qualified"
00219                 if (attributeNode.getParentNode() == self.inputRoot or
00220                     self._getAttributeFormDefault(attributeNode) == "qualified"):
00221                     if self._getTargetNamespace(attributeNode) == XSI_NAMESPACE:
00222                         self._addError ("Target namespace of an attribute must not match '%s'!" %XSI_NAMESPACE, attributeNode)
00223                 
00224             if not attributeNode.hasAttribute("name") and not attributeNode.hasAttribute("ref"):
00225                 self._addError ("Attribute must have 'name' or 'ref' attribute!", attributeNode)
00226                 continue
00227 
00228             if attributeNode.getAttribute("name") == "xmlns":
00229                 self._addError ("Attribute must not match 'xmlns'!", attributeNode)
00230 
00231             if attributeNode.hasAttribute("ref"):
00232                 if attributeNode.hasAttribute("name"):
00233                     self._addError ("Attribute may have 'name' OR 'ref' attribute!", attributeNode)
00234                 if attributeNode.hasAttribute("type"):
00235                     self._addError ("Attribute may have 'type' OR 'ref' attribute!", attributeNode)
00236                 if attributeNode.hasAttribute("form"):
00237                     self._addError ("Attribute 'form' is not allowed in this context!", attributeNode)
00238 
00239                 if attributeNode.getFirstChildNS(XSD_NAMESPACE, "simpleType") != None:
00240                     self._addError ("Attribute may only have 'ref' attribute OR 'simpleType' child!", attributeNode)
00241                 
00242                 self._checkReference (attributeNode, self.xsdAttributeDict)
00243 
00244             if attributeNode.hasAttribute("type"):
00245                 if attributeNode.getFirstChildNS(XSD_NAMESPACE, "simpleType") != None:
00246                     self._addError ("Attribute may only have 'type' attribute OR 'simpleType' child!", attributeNode)
00247 
00248                 self._checkType (attributeNode, "type", self.xsdTypeDict, (XSD_NAMESPACE, "simpleType"))
00249 
00250             use = attributeNode.getAttribute("use")
00251             if use in ("required", "prohibited") and attributeNode.hasAttribute("default"):
00252                 self._addError ("Attribute 'default' is not allowed, because 'use' is '%s'!" %(use), attributeNode)
00253 
00254             self._checkNodeId(attributeNode, unambiguousPerFile=0)
00255 
00256             self._checkFixedDefault(attributeNode)
00257 
00258 
00259     ########################################
00260     # additional checks for attribute wildcards
00261     #
00262     def _checkAnyAttributesSecondLevel(self):
00263         anyAttributeNodes, dummy, dummy = self.inputRoot.getXPathList (".//%sanyAttribute" %(self.inputNsPrefixString))
00264         for anyAttributeNode in anyAttributeNodes:
00265             # check for unique ID
00266             self._checkNodeId (anyAttributeNode)
00267 
00268 
00269     ########################################
00270     # additional checks for complex types
00271     #
00272     def _checkComplexTypesSecondLevel(self):
00273         prefix = self.inputNsPrefixString
00274         contentNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)scomplexContent/%(prefix)srestriction | .//%(prefix)scomplexContent/%(prefix)sextension" % vars())
00275         for contentNode in contentNodes:
00276             self._checkType(contentNode, "base", self.xsdTypeDict, (XSD_NAMESPACE, "complexType"))
00277 
00278         contentNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)ssimpleContent/%(prefix)srestriction | .//%(prefix)ssimpleContent/%(prefix)sextension" % vars())
00279         for contentNode in contentNodes:
00280             baseNsName = contentNode.getQNameAttribute("base")
00281             if baseNsName != (XSD_NAMESPACE, "anyType"):
00282                 typeNsName = contentNode.getParentNode().getNsName()
00283                 self._checkBaseType(contentNode, baseNsName, self.xsdTypeDict, typeNsName)
00284             else:
00285                 self._addError ("Referred type must not be 'anyType'!", contentNode)
00286             # check for unique ID
00287             self._checkNodeId (contentNode)
00288 
00289         complexTypeNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)scomplexType | .//%(prefix)sextension" % vars())
00290         for complexTypeNode in complexTypeNodes:
00291             validAttrDict = {}
00292             # check for duplicate attributes
00293             self._updateAttributeDict (complexTypeNode, validAttrDict, 1)
00294             # check for duplicate ID attributes
00295             idAttrNode = None
00296             for key, val in validAttrDict.items():
00297                 attrType = val["RefNode"].getQNameAttribute("type")
00298                 if attrType == (XSD_NAMESPACE, "ID"):
00299                     if not idAttrNode:
00300                         idAttrNode = val["Node"]
00301                     else:
00302                         # TODO: check also if attribute has a type which is derived from ID!
00303                         self._addError ("Two attribute declarations of complex type are IDs!", val["Node"])
00304                         
00305             # check for unique ID
00306             self._checkNodeId (complexTypeNode)
00307 
00308         contentNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)scomplexType/%(prefix)s*" % vars())
00309         for contentNode in contentNodes:
00310             self._checkOccurs (contentNode)
00311 
00312         contentNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)scomplexContent | .//%(prefix)ssimpleContent" % vars())
00313         for contentNode in contentNodes:
00314             # check for unique ID
00315             self._checkNodeId (contentNode)
00316 
00317 
00318     ########################################
00319     # additional checks for simple types
00320     #
00321     def _checkParticlesSecondLevel(self):
00322         prefix = self.inputNsPrefixString
00323         # check for duplicate element names
00324         particleNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)sall | .//%(prefix)schoice | .//%(prefix)ssequence" % vars())
00325         for particleNode in particleNodes:
00326             elementTypeDict = {}
00327             elementNameDict = {}
00328             groupNameDict = {}
00329             self._checkContainedElements (particleNode, particleNode.getLocalName(), elementNameDict, elementTypeDict, groupNameDict)
00330             self._checkOccurs (particleNode)
00331             # check for unique ID
00332             self._checkNodeId (particleNode)
00333                 
00334 
00335     def _checkContainedElements (self, node, particleType, elementNameDict, elementTypeDict, groupNameDict):
00336         prefix = self.inputNsPrefixString
00337         for childNode in node.getChildren():
00338             childParticleType = childNode.getLocalName()
00339             if childParticleType in ("sequence", "choice", "all"):
00340                 dummy = {}
00341                 self._checkContainedElements (childNode, childParticleType, dummy, elementTypeDict, groupNameDict)
00342             elif childParticleType in ("group"):
00343                 if childNode["ref"] != None:
00344                     childGroupNode = self.xsdGroupDict[childNode.getQNameAttribute("ref")]
00345                     if not groupNameDict.has_key(childGroupNode["name"]):
00346                         groupNameDict[childGroupNode["name"]] = 1
00347                         for cChildNode in childGroupNode.getChildren():
00348                             if cChildNode.getLocalName() != "annotation":
00349                                 self._checkContainedElements (cChildNode, particleType, elementNameDict, elementTypeDict, groupNameDict)
00350                     else:
00351                         self._addError ("Circular definition of group %s!" %repr(childGroupNode["name"]), childNode)
00352                 else:
00353                     for cChildNode in childNode.getChildren():
00354                         if cChildNode.getLocalName() != "annotation":
00355                             self._checkContainedElements (cChildNode, particleType, elementNameDict, elementTypeDict, groupNameDict)
00356             else:
00357                 if childNode.getLocalName() == "any":
00358                     elementName = childNode.getAttribute("namespace")
00359                 else:
00360                     elementName = childNode.getAttributeOrDefault("name", childNode.getAttribute("ref"))
00361 
00362                 if childNode.hasAttribute("type"):
00363                     if not elementTypeDict.has_key(elementName):
00364                         elementTypeDict[elementName] = childNode["type"]
00365                     elif childNode["type"] != elementTypeDict[elementName]:
00366                         self._addError ("Element %s has identical name and different types within %s!" %(repr(elementName), repr(particleType)), childNode)
00367                 if particleType != "sequence":
00368                     if not elementNameDict.has_key(elementName):
00369                         elementNameDict[elementName] = 1
00370                     else:
00371                         self._addError ("Element %s is not unique within %s!" %(repr(elementName), repr(particleType)), childNode)
00372 
00373 
00374     ########################################
00375     # additional checks for simple types
00376     #
00377     def _checkSimpleTypesSecondLevel(self):
00378         prefix = self.inputNsPrefixString
00379 
00380         simpleTypeNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)ssimpleType" % vars())
00381         for simpleTypeNode in simpleTypeNodes:
00382             # check for unique ID
00383             self._checkNodeId (simpleTypeNode)
00384         
00385         restrictionNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)ssimpleType/%(prefix)srestriction" % vars())
00386         for restrictionNode in restrictionNodes:
00387 
00388             # check for unique ID
00389             self._checkNodeId (restrictionNode)
00390 
00391             if not restrictionNode.hasAttribute("base") and restrictionNode.getFirstChildNS (self.inputNsURI, "simpleType") == None:
00392                 self._addError ("Simple type restriction must have 'base' attribute or 'simpleType' child tag!", restrictionNode)
00393 
00394             if restrictionNode.hasAttribute("base") and restrictionNode.getFirstChildNS (self.inputNsURI, "simpleType") != None:
00395                 self._addError ("Simple type restriction must not have 'base' attribute and 'simpleType' child tag!", restrictionNode)
00396 
00397             if restrictionNode.hasAttribute("base"):
00398                 self._checkType(restrictionNode, "base", self.xsdTypeDict)
00399 
00400             minExcl = restrictionNode.getFirstChildNS(self.inputNsURI, "minExclusive")
00401             minIncl = restrictionNode.getFirstChildNS(self.inputNsURI, "minInclusive")
00402             if minExcl != None and minIncl != None:
00403                 self._addError ("Restriction attributes 'minExclusive' and 'minInclusive' cannot be defined together!", restrictionNode)
00404             maxExcl = restrictionNode.getFirstChildNS(self.inputNsURI, "maxExclusive")
00405             maxIncl = restrictionNode.getFirstChildNS(self.inputNsURI, "maxInclusive")
00406             if maxExcl != None and maxIncl != None:
00407                 self._addError ("Restriction attributes 'maxExclusive' and 'maxInclusive' cannot be defined together!", restrictionNode)
00408 
00409         # check facets of associated primitive type
00410         for restrictionNode in restrictionNodes:
00411             try:
00412                 if restrictionNode.hasAttribute("base"):
00413                     facetNsName = self._getFacetType (restrictionNode, [restrictionNode.getParentNode(),], self.xsdTypeDict)
00414                     if not facetNsName:
00415                         continue
00416                     if _localFacetDict.has_key(facetNsName):
00417                         suppFacets = _localFacetDict[facetNsName]
00418                     else:
00419                         suppFacets, dummy, dummy = self.xsdTypeDict[facetNsName].getXPathList (".//hfp:hasFacet/@name" % vars())
00420 
00421                     specifiedFacets = {"length":None, "minLength":None, "maxLength":None,
00422                                        "minExclusive":None, "minInclusive":None, "maxExclusive":None, "maxInclusive":None,
00423                                        "totalDigits": None, "fractionDigits":None}
00424                     for childNode in restrictionNode.getChildren():
00425                         if childNode.getLocalName() in suppFacets:
00426                             if specifiedFacets.has_key(childNode.getLocalName()):
00427                                 specifiedFacets[childNode.getLocalName()] = childNode["value"]
00428                             facetElementNode = self.xsdElementDict[childNode.getNsName()]
00429                             try:
00430                                 self._checkElementTag (facetElementNode, restrictionNode, (childNode,), 0)
00431                             except TagException, errInst:
00432                                 self._addError (errInst.errstr, errInst.node, errInst.endTag)
00433                             if childNode.getLocalName() in ("enumeration", "minExclusive", "minInclusive", "maxExclusive", "maxInclusive"):
00434                                 simpleTypeReturnDict = self._checkSimpleType (restrictionNode, "base", childNode, "value", childNode["value"], None, checkAttribute=1)
00435                                 if simpleTypeReturnDict != None and simpleTypeReturnDict.has_key("orderedValue"):
00436                                     if childNode.getLocalName() != "enumeration":
00437                                         specifiedFacets[childNode.getLocalName()] = simpleTypeReturnDict["orderedValue"]
00438                         elif childNode.getLocalName() == "enumeration":
00439                             self._checkSimpleType (restrictionNode, "base", childNode, "value", childNode["value"], None, checkAttribute=1)
00440                         elif childNode.getLocalName() != "annotation":
00441                             self._addError ("Facet %s not allowed for base type %s!" %(childNode.getLocalName(), repr(restrictionNode["base"])), childNode)
00442                     if specifiedFacets["length"] != None:
00443                         if specifiedFacets["minLength"] != None or specifiedFacets["maxLength"] != None:
00444                             self._addError ("Facet 'minLength' and 'maxLength' not allowed if facet 'length' is specified!", restrictionNode)
00445                     else:
00446                         if specifiedFacets["maxLength"] != None and specifiedFacets["minLength"] != None:
00447                             if int(specifiedFacets["maxLength"]) < int(specifiedFacets["minLength"]):
00448                                 self._addError ("Facet 'maxLength' < facet 'minLength'!", restrictionNode)
00449 
00450                     if specifiedFacets["totalDigits"] != None and specifiedFacets["fractionDigits"] != None:
00451                         if int(specifiedFacets["totalDigits"]) < int(specifiedFacets["fractionDigits"]):
00452                             self._addError ("Facet 'totalDigits' must be >= 'fractionDigits'!", restrictionNode)
00453 
00454                     if specifiedFacets["minExclusive"] != None and specifiedFacets["minInclusive"] != None:
00455                         self._addError ("Facets 'minExclusive' and 'minInclusive' are mutually exclusive!", restrictionNode)
00456                     if specifiedFacets["maxExclusive"] != None and specifiedFacets["maxInclusive"] != None:
00457                         self._addError ("Facets 'maxExclusive' and 'maxInclusive' are mutually exclusive!", restrictionNode)
00458 
00459                     minValue = specifiedFacets["minExclusive"]
00460                     if specifiedFacets["minInclusive"] != None:
00461                         minValue = specifiedFacets["minInclusive"]
00462                     maxValue = specifiedFacets["maxExclusive"]
00463                     if specifiedFacets["maxInclusive"] != None:
00464                         maxValue = specifiedFacets["maxInclusive"]
00465                     # TODO: use orderedValue for '<' check!!
00466                     if minValue != None and maxValue != None and maxValue < minValue:
00467                         self._addError ("maxValue facet < minValue facet!", restrictionNode)
00468 
00469             except TagException:
00470                 self._addError ("Primitive type for base type not found!", restrictionNode)
00471 
00472         listNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)slist" % vars())
00473         for listNode in listNodes:
00474             # check for unique ID
00475             self._checkNodeId (listNode)
00476 
00477             if not listNode.hasAttribute("itemType") and listNode.getFirstChildNS (self.inputNsURI, "simpleType") == None:
00478                 self._addError ("List type must have 'itemType' attribute or 'simpleType' child tag!", listNode)
00479             elif listNode.hasAttribute("itemType") and listNode.getFirstChildNS (self.inputNsURI, "simpleType") != None:
00480                 self._addError ("List type must not have 'itemType' attribute and 'simpleType' child tag!", listNode)
00481             elif listNode.hasAttribute("itemType"):
00482                 itemType = self._checkType(listNode, "itemType", self.xsdTypeDict)
00483                 if self.xsdTypeDict.has_key(itemType):
00484                     if self.xsdTypeDict[itemType].getLocalName() != "simpleType":
00485                         self._addError ("ItemType %s must be a simple type!" %(repr(itemType)), listNode)
00486                     elif self.xsdTypeDict[itemType].getFirstChild().getLocalName() == "list":
00487                         self._addError ("ItemType %s must not be a list type!" %(repr(itemType)), listNode)
00488 
00489         unionNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)ssimpleType/%(prefix)sunion" % vars())
00490         for unionNode in unionNodes:
00491             # check for unique ID
00492             self._checkNodeId (unionNode)
00493 
00494             if not unionNode.hasAttribute("memberTypes"):
00495                 for childNode in unionNode.getChildren():
00496                     if childNode.getLocalName() != "annotation":
00497                         break
00498                 else:
00499                     self._addError ("Union must not be empty!", unionNode)
00500             else:
00501                 for memberType in string.split(unionNode["memberTypes"]):
00502                     memberNsName = unionNode.qName2NsName(memberType, 1)
00503                     self._checkBaseType(unionNode, memberNsName, self.xsdTypeDict)
00504                     if self.xsdTypeDict.has_key(memberNsName):
00505                         if self.xsdTypeDict[memberNsName].getLocalName() != "simpleType":
00506                             self._addError ("MemberType %s must be a simple type!" %(repr(memberNsName)), unionNode)
00507 
00508         patternNodes, dummy, dummy = self.inputRoot.getXPathList (".//%(prefix)spattern" % vars())
00509         for patternNode in patternNodes:
00510             pattern = patternNode["value"]
00511             try:
00512                 pattern = substituteSpecialEscChars (pattern)
00513                 try:
00514                     test = re.compile(pattern)
00515                 except Exception, errstr:
00516                     self._addError (str(errstr), patternNode)
00517                     self._addError ("%s is not a valid regular expression!" %(repr(patternNode["value"])), patternNode)
00518             except SyntaxError, errInst:
00519                     self._addError (repr(errInst[0]), patternNode)
00520 
00521 
00522     ########################################
00523     # additional checks for keyrefs
00524     #
00525     def _checkIdentityConstraintsSecondLevel(self):
00526         identityConstraintNodes, dummy, dummy = self.inputRoot.getXPathList (".//%sunique" %(self.inputNsPrefixString))
00527         for identityConstraintNode in identityConstraintNodes:
00528             # check for unique ID
00529             self._checkNodeId (identityConstraintNode)
00530 
00531             selectorNode = identityConstraintNode.getFirstChildNS(XSD_NAMESPACE, "selector")
00532             self._checkNodeId (selectorNode)
00533             try:
00534                 completeChildList, attrNodeList, attrNsNameFirst = identityConstraintNode.getParentNode().getXPathList (selectorNode["xpath"], selectorNode)
00535                 if attrNsNameFirst != None:
00536                     self._addError ("Selection of attributes is not allowed for selector!", selectorNode)
00537             except Exception, errstr:
00538                 self._addError (errstr, selectorNode)
00539 
00540             try:
00541                 fieldNode = identityConstraintNode.getFirstChildNS(XSD_NAMESPACE, "field")
00542                 identityConstraintNode.getParentNode().getXPathList (fieldNode["xpath"], fieldNode)
00543                 self._checkNodeId (fieldNode)
00544             except Exception, errstr:
00545                 self._addError (errstr, fieldNode)
00546 
00547 
00548     ########################################
00549     # additional checks for keyrefs
00550     #
00551     def _checkKeysSecondLevel(self):
00552         keyNodes, dummy, dummy = self.inputRoot.getXPathList (".//%skey" %(self.inputNsPrefixString))
00553         for keyNode in keyNodes:
00554             # check for unique ID
00555             self._checkNodeId (keyNode)
00556 
00557             fieldNode = keyNode.getFirstChildNS(XSD_NAMESPACE, "field")
00558             if fieldNode != None:
00559                 self._checkNodeId (fieldNode)
00560                 
00561 
00562     ########################################
00563     # additional checks for keyrefs
00564     #
00565     def _checkKeyRefsSecondLevel(self):
00566         keyrefNodes, dummy, dummy = self.inputRoot.getXPathList (".//%skeyref" %(self.inputNsPrefixString))
00567         for keyrefNode in keyrefNodes:
00568             # check for unique ID
00569             self._checkNodeId (keyrefNode)
00570 
00571             self._checkKeyRef(keyrefNode, self.xsdIdentityConstrDict)
00572                 
00573 
00574     ########################################
00575     # helper methods
00576     #
00577 
00578     def _checkFixedDefault(self, node):
00579         if node.hasAttribute("default") and node.hasAttribute("fixed"):
00580             self._addError ("%s may have 'default' OR 'fixed' attribute!" %repr(node.getLocalName()), node)
00581         if  node.hasAttribute("default"):
00582             self._checkSimpleType (node, "type", node, "default", node["default"], None, checkAttribute=1)
00583         if  node.hasAttribute("fixed"):
00584             self._checkSimpleType (node, "type", node, "fixed", node["fixed"], None, checkAttribute=1)
00585     
00586     
00587     def _checkReference(self, node, dict):
00588         baseNsName = node.getQNameAttribute("ref")
00589         if dict.has_key(baseNsName):
00590             refNode = dict[baseNsName]
00591             fixedValue = node.getAttribute("fixed")
00592             fixedRefValue = refNode.getAttribute("fixed")
00593             if fixedValue != None and fixedRefValue != None and fixedValue != fixedRefValue:
00594                 self._addError ("Fixed value %s of attribute does not match fixed value %s of reference!" %(repr(fixedValue), repr(fixedRefValue)), node)
00595                 
00596         else:
00597             self._addError ("Reference %s not found!" %(repr(baseNsName)), node)
00598 
00599     def _checkType(self, node, typeAttrName, dict, typeNsName=None):
00600         baseNsName = node.getQNameAttribute(typeAttrName)
00601         self._checkBaseType(node, baseNsName, dict, typeNsName)
00602         return baseNsName
00603     
00604     def _checkBaseType(self, node, baseNsName, dict, typeNsName=None):
00605         if not dict.has_key(baseNsName) and baseNsName != (XSD_NAMESPACE, "anySimpleType"):
00606             self._addError ("Definition of type %s not found!" %(repr(baseNsName)), node)
00607         elif typeNsName != None:
00608             if typeNsName == (XSD_NAMESPACE, "simpleContent"):
00609                 if node.getNsName() == (XSD_NAMESPACE, "restriction"):
00610                     if (baseNsName != (XSD_NAMESPACE, "anySimpleType") and
00611                         dict[baseNsName].getNsName() == (XSD_NAMESPACE, "complexType") and
00612                         dict[baseNsName].getFirstChild().getNsName() == typeNsName):
00613                         pass
00614                     else:
00615                         self._addError ("Referred type %s must be a complex type with simple content!" %(repr(baseNsName)), node)
00616                 else: # extension
00617                     if (baseNsName == (XSD_NAMESPACE, "anySimpleType") or
00618                         dict[baseNsName].getNsName() == (XSD_NAMESPACE, "simpleType") or
00619                        (dict[baseNsName].getNsName() == (XSD_NAMESPACE, "complexType") and
00620                         dict[baseNsName].getFirstChild().getNsName() == typeNsName)):
00621                         pass
00622                     else:
00623                         self._addError ("Referred type %s must be a simple type or a complex type with simple content!" %(repr(baseNsName)), node)
00624             else:
00625                 if typeNsName == (XSD_NAMESPACE, "simpleType") and baseNsName == (XSD_NAMESPACE, "anySimpleType"):
00626                     pass
00627                 elif dict[baseNsName].getNsName() != typeNsName:
00628                     self._addError ("Referred type %s must be a %s!" %(repr(baseNsName), repr(typeNsName)), node)
00629 
00630 
00631     def _checkKeyRef(self, keyrefNode, dict):
00632         baseNsName = keyrefNode.getQNameAttribute("refer")
00633         if not dict.has_key(baseNsName):
00634             self._addError ("keyref refers unknown key %s!" %(repr(baseNsName)), keyrefNode)
00635         else:
00636             keyNode = dict[baseNsName]["Node"]
00637             if keyNode.getNsName() not in ((XSD_NAMESPACE, "key"), (XSD_NAMESPACE, "unique")):
00638                 self._addError ("reference to non-key constraint %s!" %(repr(baseNsName)), keyrefNode)
00639             if len(keyrefNode.getChildrenNS(XSD_NAMESPACE, "field")) != len(keyNode.getChildrenNS(XSD_NAMESPACE, "field")):
00640                 self._addError ("key/keyref field size mismatch!", keyrefNode)
00641                 
00642             
00643     def _checkOccurs (self, node):
00644         minOccurs = node.getAttributeOrDefault("minOccurs", "1")
00645         maxOccurs = node.getAttributeOrDefault("maxOccurs", "1")
00646         if maxOccurs != "unbounded":
00647             if string.atoi(minOccurs) > string.atoi(maxOccurs):
00648                 self._addError ("Attribute minOccurs > maxOccurs!", node)
00649 
00650 
00651     def _checkNodeId (self, node, unambiguousPerFile=1):
00652         if node.hasAttribute("id"):
00653             # id must only be unambiguous within one file
00654             if unambiguousPerFile:
00655                 nodeId = (node.getAbsUrl(), collapseString(node["id"]))
00656             else:
00657                 nodeId = collapseString(node["id"])
00658             if not self.xsdIdDict.has_key(nodeId):
00659                 self.xsdIdDict[nodeId] = node
00660             else:
00661                 self._addError ("There are multiple occurences of ID value %s!" %repr(nodeId), node)
00662 
00663 
00664     def _getFacetType(self, node, parentNodeList, xsdTypeDict):
00665             baseNsName = node.getQNameAttribute("base")
00666             try:
00667                 baseNode = xsdTypeDict[baseNsName]
00668             except:
00669                 self._addError ("Base type %s must be an atomic simple type definition or a builtin type!" %repr(baseNsName), node)
00670                 return None
00671 
00672             if baseNode in parentNodeList:
00673                 self._addError ("Circular type definition (type is contained in its own type hierarchy)!", node)
00674                 return None
00675                 
00676             if baseNode.getNsName() == (XSD_NAMESPACE, "simpleType"):
00677                 if baseNode.getAttribute("facetType") != None:
00678                     facetType = baseNode.qName2NsName(baseNode["facetType"], 1)
00679                     node.getParentNode()["facetType"] = node.nsName2QName(facetType)
00680                     return facetType
00681                 else:
00682                     for baseNodeType in ("list", "union"):
00683                         if baseNode.getFirstChildNS (XSD_NAMESPACE, baseNodeType) != None:
00684                             return (XSD_NAMESPACE, baseNodeType)
00685                     else:
00686                         parentNodeList.append(node)
00687                         return self._getFacetType(baseNode.getFirstChildNS(XSD_NAMESPACE, "restriction"), parentNodeList, xsdTypeDict)    
00688             else:
00689                 self._addError ("Base type %s must be an atomic simple type definition or a builtin type!" %repr(baseNsName), node)
00690                 return None
00691             
00692 


mavlink
Author(s): Lorenz Meier
autogenerated on Sun May 22 2016 04:05:43