diff -r aaa80b48bead -r dcfe7c07ba1c minixsv/xsvalBase.py --- a/minixsv/xsvalBase.py Tue Jan 22 10:57:41 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,602 +0,0 @@ -# -# minixsv, Release 0.3 -# file: xsvalBase.py -# -# XML schema validator base class -# -# history: -# 2004-10-07 rl created -# -# Copyright (c) 2004 by Roland Leuthe. All rights reserved. -# -# -------------------------------------------------------------------- -# The minixsv XML schema validator is -# -# Copyright (c) 2004 by Roland Leuthe -# -# By obtaining, using, and/or copying this software and/or its -# associated documentation, you agree that you have read, understood, -# and will comply with the following terms and conditions: -# -# Permission to use, copy, modify, and distribute this software and -# its associated documentation for any purpose and without fee is -# hereby granted, provided that the above copyright notice appears in -# all copies, and that both that copyright notice and this permission -# notice appear in supporting documentation, and that the name of -# the author not be used in advertising or publicity -# pertaining to distribution of the software without specific, written -# prior permission. -# -# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD -# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- -# ABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE -# OF THIS SOFTWARE. -# -------------------------------------------------------------------- - -from xsvalErrorHandler import * -import xsvalSimpleTypes - -########################################################### -# Validator class for validating one input file against one XML schema file - -class XsValBase: - - def __init__(self, xmlIf, errorHandler): - self.xmlIf = xmlIf - self.errorHandler = errorHandler - - self._raiseError = self.errorHandler.raiseError - self._addError = self.errorHandler.addError - self._addWarning = self.errorHandler.addWarning - - self.checkKeyrefList = [] - - - ######################################## - # validate inputTree against xsdTree - # - def validate (self, inputTree, xsdTree): - self.inputTree = inputTree - self.xsdTree = xsdTree - - self.xsdRoot = self.xsdTree.getRootNode() - self.xsdNSAlias = self.xmlIf.extractNamespaceAlias(self.xsdRoot.getTagName()) - self.inputRoot = self.inputTree.getRootNode() - self.inputNSAlias = self.xmlIf.extractNamespaceAlias(self.inputRoot.getTagName()) - - self.simpleTypeVal = xsvalSimpleTypes.XsSimpleTypeVal(self) - - self._setupLookupTables() - - inputRootTagName = self.inputRoot.getTagName() - inputRootLocalName = self.inputRoot.getLocalName() - if self.xsdElementDict.has_key(inputRootLocalName): - # start recursive schema validation - try: - self._checkElementTag (self.xsdElementDict[inputRootLocalName], inputRootTagName, (self.inputRoot,), 0) - except TagException, errInst: - self._addError (errInst.errstr, errInst.node, errInst.endTag) - - # validate keyrefs - for inputElement, keyrefNode in self.checkKeyrefList: - self._checkKeyRefConstraint (keyrefNode, inputElement) - else: - self._raiseError ("Used root tag %s not found in schema file!" %(inputRootTagName), self.inputRoot) - - - ######################################## - # setup lookup dictionaries used during validation - # - def _setupLookupTables (self): - # retrieve all elements - self.xsdElementDict = {} - for xsdTypeNode in self.xsdRoot.getChildrenNS(self.xsdNSAlias, "element"): - self.xsdElementDict[xsdTypeNode.getAttribute("name")] = xsdTypeNode - - # retrieve all type definitions (complex and simple types) - self.xsdTypeDict = {} - for xsdTypeNode in self.xsdRoot.getChildrenNS(self.xsdNSAlias, "complexType"): - self.xsdTypeDict[xsdTypeNode.getAttribute("name")] = xsdTypeNode - - for xsdTypeNode in self.xsdRoot.getChildrenNS(self.xsdNSAlias, "simpleType"): - self.xsdTypeDict[xsdTypeNode.getAttribute("name")] = xsdTypeNode - - # retrieve all group definitions - self.xsdGroupDict = {} - for xsdTypeNode in self.xsdRoot.getChildrenNS(self.xsdNSAlias, "group"): - self.xsdGroupDict[xsdTypeNode.getAttribute("name")] = xsdTypeNode - - # retrieve all attribute group definitions - self.xsdAttributeGroupDict = {} - for xsdTypeNode in self.xsdRoot.getChildrenNS(self.xsdNSAlias, "attributeGroup"): - self.xsdAttributeGroupDict[xsdTypeNode.getAttribute("name")] = xsdTypeNode - - # retrieve all identity constraints - self.xsdIdentityConstrDict = {} - for identConstrTagName in ("unique", "key", "keyref"): - identConstrNodeList = self.xsdRoot.getElementsByTagNameNS (self.xsdNSAlias, identConstrTagName) - for identConstrNode in identConstrNodeList: - identConstrName = identConstrNode.getAttribute("name") - if not self.xsdIdentityConstrDict.has_key(identConstrName): - self.xsdIdentityConstrDict[identConstrName] = {"Node": identConstrNode, "ValueDict":{}} - else: - self._raiseError ("Duplicate identity constraint name '%s' found in schema definition!" %(identConstrName), identConstrNode) - - - ######################################## - # validate inputElement against complexType node - # - def _checkComplexTypeTag (self, xsdParentElementNode, xsdElement, inputElement, inputElementChildIndex, usedAsBaseType=None): - baseTypeAttributes = {"__SPECIAL_ATTRS__":{}} - if xsdParentElementNode.getAttribute ("nillable") == "true": - baseTypeAttributes["__SPECIAL_ATTRS__"]["nil"] = "xsd:boolean" - - complexContentElement = xsdElement.getFirstChildNS(self.xsdNSAlias, "complexContent") - if complexContentElement != None: - inputElementChildIndex, baseTypeAttributes = self._checkComplexContentTag (xsdParentElementNode, complexContentElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes) - else: - inputElementChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes) - return inputElementChildIndex, baseTypeAttributes - - def _checkComplexContentTag (self, xsdParentElementNode, xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes): - extensionElement = xsdElement.getFirstChildNS(self.xsdNSAlias, "extension") - if extensionElement != None: - inputElementChildIndex, baseTypeAttributes = self._checkExtensionComplexContent (xsdParentElementNode, extensionElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes) - else: - restrictionElement = xsdElement.getFirstChildNS(self.xsdNSAlias, "restriction") - if restrictionElement != None: - inputElementChildIndex, baseTypeAttributes = self._checkRestrictionComplexContent (xsdParentElementNode, restrictionElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes) - return inputElementChildIndex, baseTypeAttributes - - def _checkExtensionComplexContent (self, xsdParentElementNode, xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes): - baseType = self.xmlIf.extractLocalName(xsdElement.getAttribute("base")) - inputElementChildIndex, baseTypeAttributes = self._checkComplexTypeTag (xsdParentElementNode, self.xsdTypeDict[baseType], inputElement, inputElementChildIndex, "extension") - - inputElementChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes) - return inputElementChildIndex, baseTypeAttributes - - def _checkRestrictionComplexContent (self, xsdParentElementNode, xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes): - # first check against base type (retrieve only the base type attributes) - baseType = self.xmlIf.extractLocalName(xsdElement.getAttribute("base")) - inputElementChildIndex, baseTypeAttributes = self._checkComplexTypeTag (xsdParentElementNode, self.xsdTypeDict[baseType], inputElement, inputElementChildIndex, "restriction") - - # then check input against derived complex type - inputElementChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes) - return inputElementChildIndex, baseTypeAttributes - - def _checkComplexTypeContent (self, xsdElement, inputElement, inputElementChildIndex, usedAsBaseType, baseTypeAttributes): - inputTagName = inputElement.getTagName() - childTags = inputElement.getChildren() - if usedAsBaseType in (None, "extension"): - validChildTags = xsdElement.getChildren() - for validChildTag in validChildTags: - if validChildTag.getLocalName() not in ("attribute", "attributeGroup", "anyAttribute"): - inputElementChildIndex = self._checkParticle (validChildTag, inputElement, childTags, inputElementChildIndex) - - if usedAsBaseType == None and inputElementChildIndex < len (childTags): - self._addError ("Unexpected child tag '%s' in tag '%s' found!" %(childTags[inputElementChildIndex].getTagName(), inputTagName), childTags[inputElementChildIndex]) - - if usedAsBaseType in (None,): - self._checkAttributeTags (xsdElement, inputElement, baseTypeAttributes) - - if usedAsBaseType in ("restriction", "extension"): - validAttributes = xsdElement.getChildrenNS(self.xsdNSAlias, "attribute") - for validAttrGroup in xsdElement.getChildrenNS(self.xsdNSAlias, "attributeGroup"): - attributeGroupRef = self.xmlIf.extractLocalName(validAttrGroup.getAttribute("ref")) - validAttributes.extend (self.xsdAttributeGroupDict[attributeGroupRef].getChildrenNS(self.xsdNSAlias, "attribute")) - for validAttribute in validAttributes: - baseTypeAttributes[validAttribute.getAttribute("name")] = validAttribute - return inputElementChildIndex, baseTypeAttributes - - - ######################################## - # validate inputNodeList against xsdNode - # - def _checkList (self, elementMethod, xsdNode, inputParentNode, inputNodeList, currIndex): - if not xsdNode.hasAttribute("minOccurs"): - xsdNode.setAttribute("minOccurs", "1") # default - if not xsdNode.hasAttribute("maxOccurs"): - xsdNode.setAttribute("maxOccurs", "1") # default - - minOccurs = string.atoi(xsdNode.getAttribute("minOccurs")) - maxOccurs = -1 - if xsdNode.getAttribute("maxOccurs") != "unbounded": - maxOccurs = string.atoi(xsdNode.getAttribute("maxOccurs")) - occurs = 0 - while maxOccurs == -1 or occurs < maxOccurs: - try: - newIndex = elementMethod (xsdNode, inputParentNode, inputNodeList, currIndex) - occurs += 1 - if newIndex > currIndex: - currIndex = newIndex - else: - break # no suitable element found - except TagException, errInst: - break - - if occurs == 0 and minOccurs > 0: - raise errInst - elif occurs < minOccurs: - expInputTagName = xsdNode.getAttribute("name") - if expInputTagName == None: - expInputTagName = self.xmlIf.extractLocalName(xsdNode.getAttribute("ref")) - - errInst.errstr = "Minimum number (%d) of child tags '%s' in tag '%s' not available (only %d)!" %(minOccurs, expInputTagName, inputParentNode.getTagName(), occurs) - raise errInst - - return currIndex - - ######################################## - # validate inputNode against element node - # - def _checkElementTag (self, xsdNode, inputParentNode, inputNodeList, currIndex): - if xsdNode.hasAttribute("ref"): - refAttr = self.xmlIf.extractLocalName(xsdNode.getAttribute("ref")) - currIndex = self._checkElementTag (self.xsdElementDict[refAttr], inputParentNode, inputNodeList, currIndex) - - else: - nameAttr = xsdNode.getAttribute ("name") - if currIndex >= len (inputNodeList): - raise TagException ("Missing child tag '%s' in tag '%s'!" %(nameAttr, inputParentNode.getTagName()), inputParentNode, 1) - - inputNode = inputNodeList[currIndex] - if nameAttr != inputNode.getLocalName(): - raise TagException ("Missing child tag '%s' in tag '%s'!" %(nameAttr, inputParentNode.getTagName()), inputNode, 0) - - simpleType = None - complexTypeNode = xsdNode.getFirstChildNS (self.xsdNSAlias, "complexType") - simpleTypeNode = xsdNode.getFirstChildNS (self.xsdNSAlias, "simpleType") - if xsdNode.hasAttribute("type"): - typeAttr = xsdNode.getAttribute ("type") - localTypeAttr = self.xmlIf.extractLocalName(typeAttr) - if self.xsdTypeDict.has_key (localTypeAttr) and self.xsdTypeDict[localTypeAttr].getLocalName() == "complexType": - complexTypeNode = self.xsdTypeDict[localTypeAttr] - else: - simpleType = typeAttr - - if complexTypeNode != None: - try: - self._checkComplexTypeTag (xsdNode, complexTypeNode, inputNode, 0) - except TagException, errInst: - self._addError (errInst.errstr, errInst.node, errInst.endTag) - else: - try: - simpleTypeReturnDict = {} - if simpleTypeNode != None: - self.simpleTypeVal.checkSimpleTypeDef (simpleTypeNode, inputNode.getTagName(), inputNode.getElementValue(), simpleTypeReturnDict) - elif simpleType != None: - self.simpleTypeVal.checkSimpleType (inputNode.getTagName(), simpleType, inputNode.getElementValue(), simpleTypeReturnDict) - # TODO: What to check if np type is specified for the element? - - if simpleTypeReturnDict.has_key("adaptedAttrValue"): - inputNode.setElementValue(simpleTypeReturnDict["adaptedAttrValue"]) - - except xsvalSimpleTypes.SimpleTypeError, errstr: - self._addError (str(errstr), inputNode) - - currIndex += 1 - - # check unique attributes and keys - childUniqueDefList = xsdNode.getChildrenNS (self.xsdNSAlias, "unique") - for childUniqueDef in childUniqueDefList: - self._checkIdentityConstraint (childUniqueDef, inputNode, "unique") - - childKeyDefList = xsdNode.getChildrenNS (self.xsdNSAlias, "key") - for childKeyDef in childKeyDefList: - self._checkIdentityConstraint (childKeyDef, inputNode, "key") - - childKeyrefDefList = xsdNode.getChildrenNS (self.xsdNSAlias, "keyref") - for childKeyrefDef in childKeyrefDefList: - self.checkKeyrefList.append ((inputNode, childKeyrefDef)) - - return currIndex - - - ######################################## - # validate inputNode against sequence node - # - def _checkSequenceTag (self, xsdNode, inputParentNode, inputNodeList, currIndex): - for xsdChildNode in xsdNode.getChildren(): - currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex) - return currIndex - - ######################################## - # validate inputNode against choice node - # - def _checkChoiceTag (self, xsdNode, inputParentNode, inputNodeList, currIndex): - for xsdChildNode in xsdNode.getChildren(): - try: - currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex) - break - except TagException, errInst: - pass - else: - if currIndex < len(inputNodeList): - currNode = inputNodeList[currIndex] - endTag = 0 - else: - currNode = inputParentNode - endTag = 1 - raise TagException ("No suitable child tag for choice found!", currNode, endTag) - - return currIndex - - ######################################## - # validate inputNode against group node - # - def _checkGroupTag (self, xsdNode, inputParentNode, inputNodeList, currIndex): - if xsdNode.hasAttribute("ref"): - refAttr = self.xmlIf.extractLocalName(xsdNode.getAttribute("ref")) - currIndex = self._checkGroupTag (self.xsdGroupDict[refAttr], inputParentNode, inputNodeList, currIndex) - else: - for xsdChildNode in xsdNode.getChildren(): - currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex) - return currIndex - - ######################################## - # validate inputNode against all node - # - def _checkAllTag (self, xsdNode, inputParentNode, inputNodeList, currIndex): - oldIndex = currIndex - xsdChildDict = {} - for xsdChildNode in xsdNode.getChildren(): - xsdChildDict[xsdChildNode] = 0 - while currIndex < len(inputNodeList): - currNode = inputNodeList[currIndex] - for xsdChildNode in xsdChildDict.keys(): - try: - newIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex) - except TagException, errInst: - continue - - if xsdChildDict[xsdChildNode] == 0: - xsdChildDict[xsdChildNode] = 1 - currIndex = newIndex - break - else: - raise TagException ("Ambiguous child tag '%s' found in all-group!" %(currNode.getTagName()), currNode) - else: - raise TagException ("Unexpected child tag '%s' for all-group found!" %(currNode.getTagName()), currNode) - - for xsdChildNode, occurs in xsdChildDict.items(): - if xsdChildNode.getAttribute("minOccurs") != "0" and occurs == 0: - raise TagException ("Child tag '%s' missing in all-group (%s)" %(xsdChildNode.getAttribute("name"), inputParentNode.getTagName()), inputNodeList[oldIndex]) - - return currIndex - - - ######################################## - # validate inputNode against any node - # - def _checkAnyTag (self, xsdNode, inputParentNode, inputNodeList, currIndex): - processContents = xsdNode.getAttribute("processContents") - if processContents == "skip": - pass - elif processContents == "lax": - # TODO: Was muss hier gecheckt werden? - pass - elif processContents == "strict": - # TODO: Was muss hier gecheckt werden? - pass - - if currIndex < len(inputNodeList): - currIndex = currIndex + 1 - - return currIndex - - ######################################## - # validate inputNode against particle - # - def _checkParticle (self, xsdNode, inputParentNode, inputNodeList, currIndex): - xsdTagName = xsdNode.getTagName() - if xsdTagName == self.xsdNSAlias + "element": - currIndex = self._checkList (self._checkElementTag, xsdNode, inputParentNode, inputNodeList, currIndex) - elif xsdTagName == self.xsdNSAlias + "choice": - currIndex = self._checkList (self._checkChoiceTag, xsdNode, inputParentNode, inputNodeList, currIndex) - elif xsdTagName == self.xsdNSAlias + "sequence": - currIndex = self._checkList (self._checkSequenceTag, xsdNode, inputParentNode, inputNodeList, currIndex) - elif xsdTagName == self.xsdNSAlias + "group": - currIndex = self._checkList (self._checkGroupTag, xsdNode, inputParentNode, inputNodeList, currIndex) - elif xsdTagName == self.xsdNSAlias + "all": - currIndex = self._checkList (self._checkAllTag, xsdNode, inputParentNode, inputNodeList, currIndex) - elif xsdTagName == self.xsdNSAlias + "any": - currIndex = self._checkList (self._checkAnyTag, xsdNode, inputParentNode, inputNodeList, currIndex) - elif xsdTagName == self.xsdNSAlias + "annotation": - pass # nothing to check - else: - self._addError ("Internal error: Invalid tag %s found!" %(xsdTagName)) - return currIndex - - - ######################################## - # validate attributes of inputNode against complexType node - # - def _checkAttributeTags (self, xsdNode, inputNode, validAttrDict): - validAttributes = xsdNode.getChildrenNS(self.xsdNSAlias, "attribute") - for validAttrGroup in xsdNode.getChildrenNS(self.xsdNSAlias, "attributeGroup"): - attributeGroupRef = self.xmlIf.extractLocalName(validAttrGroup.getAttribute("ref")) - validAttributes.extend (self.xsdAttributeGroupDict[attributeGroupRef].getChildrenNS(self.xsdNSAlias, "attribute")) - for validAttribute in validAttributes: - if validAttribute.hasAttribute("name"): - keyAttr = validAttribute.getAttribute("name") - else: - keyAttr = self.xmlIf.extractLocalName(validAttribute.getAttribute("ref")) - validAttrDict[keyAttr] = validAttribute - - inputAttrDict = {} - for iAttrName, iAttrValue in inputNode.getAttributeDict().items(): - if self.xmlIf.extractNamespaceAlias (iAttrName) != "xmlns:" and iAttrName != "xmlns": - inputAttrDict[self.xmlIf.extractLocalName(iAttrName)] = iAttrValue - - for attrKey, validAttribute in validAttrDict.items(): - # handle special attributes, e.g. xsi:nil - if attrKey == "__SPECIAL_ATTRS__": - for specialAttrName, specialAttrType in validAttribute.items(): - if inputAttrDict.has_key(specialAttrName): - simpleTypeReturnDict = {} - try: - self.simpleTypeVal.checkSimpleType (specialAttrName, specialAttrType, inputAttrDict[specialAttrName], simpleTypeReturnDict) - except xsvalSimpleTypes.SimpleTypeError, errstr: - self._addError (str(errstr), inputNode) - - del inputAttrDict[specialAttrName] - continue - - attrDict = validAttribute.getAttributeDict() - if attrDict.has_key("ref"): - # TODO: What to do here?? - attrRef = self.xmlIf.extractLocalName(attrDict["ref"]) - if inputAttrDict.has_key(attrRef): - del inputAttrDict[attrRef] - else: - attrName = attrDict["name"] - if not attrDict.has_key("use"): - attrDict["use"] = "optional" - - if inputAttrDict.has_key(attrName): - del inputAttrDict[attrName] - else: - if attrDict["use"] == "required": - self._addError ("Attribute '%s' is missing for tag %s!" %(attrName, inputNode.getTagName()), inputNode) - elif attrDict["use"] == "optional": - if attrDict.has_key("default"): - inputNode.setAttribute(attrName, attrDict["default"]) - if attrDict.has_key("fixed"): - if inputNode.getAttribute(attrName) != attrDict["fixed"]: - self._addError ("Attribute '%s' must have fixed value '%s'!" %(attrName, attrDict["fixed"]), inputNode) - - if inputNode.hasAttribute(attrName): - if attrDict["use"] == "prohibited": - self._addError ("Attribute '%s' is prohibited in this context!" %(attrName), inputNode) - else: - attributeValue = inputNode.getAttribute(attrName) - try: - simpleTypeReturnDict = {} - if attrDict.has_key("type"): - self.simpleTypeVal.checkSimpleType (attrName, attrDict["type"], attributeValue, simpleTypeReturnDict) - else: - typedefNode = validAttribute.getFirstChildNS(self.xsdNSAlias, "simpleType") - if typedefNode != None: - self.simpleTypeVal.checkSimpleTypeDef (typedefNode, attrName, attributeValue, simpleTypeReturnDict) - else: - pass # default if no type attribute is specified - - if simpleTypeReturnDict.has_key("adaptedAttrValue"): - inputNode.setAttribute(attrName, simpleTypeReturnDict["adaptedAttrValue"]) - - except xsvalSimpleTypes.SimpleTypeError, errstr: - self._addError (str(errstr), inputNode) - - for inputAttribute in inputAttrDict.keys(): - # TODO: adapt for using namespaces!! - if self.xmlIf.extractLocalName(inputAttribute) in ("noNamespaceSchemaLocation", "schemaLocation"): - del inputAttrDict[inputAttribute] - - for inputAttribute in inputAttrDict.keys(): - if inputAttribute == "nil": - self._addError ("Tag '%s' hasn't been defined as nillable!" %(inputNode.getTagName()), inputNode) - else: - self._addError ("Unexpected attribute '%s' in Tag '%s'!" %(inputAttribute, inputNode.getTagName()), inputNode) - - - ######################################## - # validate unique and key definition - # - def _checkIdentityConstraint (self, identityConstrNode, inputElement, isKey): - identConstrName = identityConstrNode.getAttribute ("name") - selectorXPathNode = identityConstrNode.getFirstChildNS (self.xsdNSAlias, "selector") - selectorNodeList, dummy = self._getXPath (inputElement, selectorXPathNode.getAttribute("xpath"), self.inputNSAlias) - - valueDict = {} - for selectorNode in selectorNodeList: - fieldXPathNodeList = identityConstrNode.getChildrenNS (self.xsdNSAlias, "field") - keyValue = [] - for fieldXPathNode in fieldXPathNodeList: - fieldXPath = fieldXPathNode.getAttribute("xpath") - fieldNodeList, fieldAttributeList = self._getXPath (selectorNode, fieldXPath, self.inputNSAlias, isKey) - if len(fieldNodeList) > 1 or len(fieldAttributeList) > 1: - self._addError ("The field xPath of identity constraint '%s' must evaluate to exactly 0 or 1 node!" %(identConstrName), fieldXPathNode) - return - - # TODO: unique and key check currently only on string base - for fieldNode in fieldNodeList: - keyValue.append (fieldNode.getElementValue ()) - - for attrValue in fieldAttributeList: - keyValue.append (attrValue) - - if keyValue != []: - keyValue = tuple(keyValue) - if not valueDict.has_key (keyValue): - valueDict[keyValue] = 1 - self.xsdIdentityConstrDict[identConstrName]["ValueDict"][keyValue] = 1 - else: - self._addError ("Duplicate identity constraint values '%s' found for identity contraint '%s'!" %(keyValue, identConstrName), selectorNode) - - ######################################## - # validate unique and key definition - # - def _checkKeyRefConstraint (self, keyrefNode, inputElement): - keyRefName = keyrefNode.getAttribute ("name") - keyReference = keyrefNode.getAttribute ("refer") - if not self.xsdIdentityConstrDict.has_key (keyReference): - self._addError ("keyref refers unknown key '%s'!" %(keyReference), keyrefNode) - return - - selectorXPathNode = keyrefNode.getFirstChildNS (self.xsdNSAlias, "selector") - selectorNodeList, dummy = self._getXPath (inputElement, selectorXPathNode.getAttribute("xpath"), self.inputNSAlias) - - for selectorNode in selectorNodeList: - fieldXPathNodeList = keyrefNode.getChildrenNS(self.xsdNSAlias, "field") - keyValue = [] - for fieldXPathNode in fieldXPathNodeList: - fieldXPath = fieldXPathNode.getAttribute("xpath") - fieldNodeList, fieldAttributeList = self._getXPath (selectorNode, fieldXPath, self.inputNSAlias, "keyref") - if len(fieldNodeList) > 1 or len(fieldAttributeList) > 1: - self._addError ("The field xPath of keyref '%s' must evaluate to exactly 0 or 1 node!" %(keyRefName), fieldXPathNode) - return - - # TODO: unique and key check currently only on string base - for fieldNode in fieldNodeList: - keyValue.append(fieldNode.getElementValue()) - - for attrValue in fieldAttributeList: - keyValue.append(attrValue) - - keyValue = tuple(keyValue) - if not self.xsdIdentityConstrDict[keyReference]["ValueDict"].has_key (keyValue): - self._addError ("Element value '%s' does not match key type '%s'!" %(keyValue, keyReference), selectorNode) - - ######################################## - # retrieve nodes/attributes specified by given xPath - # - def _getXPath (self, node, xPath, defaultNamespace, identityConstraint=None): - try: - nodeList, attributeList = node.getXPathList (xPath, defaultNamespace) - except IOError, errstr: - self._addError (errstr, node) - nodeList = attributeList = [] - - if nodeList == [] and attributeList == []: - if identityConstraint == "key": - self.errorHandler.addError ("Key is missing! XPath = '%s'!" %(xPath), node) - elif identityConstraint in ("unique", "keyref"): - self.errorHandler.addWarning ("Identity constraint is missing! XPath = '%s'!" %(xPath), node) - - return nodeList, attributeList - - -######################################## -# define own exception for XML schema validation errors -# -class TagException (StandardError): - def __init__ (self, errstr="", node=None, endTag=0): - self.node = node - self.errstr = errstr - self.endTag = endTag - StandardError.__init__(self) -