diff -r aaa80b48bead -r dcfe7c07ba1c minixsv/xsvalSimpleTypes.py --- a/minixsv/xsvalSimpleTypes.py Tue Jan 22 10:57:41 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,332 +0,0 @@ -# -# # minixsv, Release 0.3 -# file: xsvalSimpleTypes.py -# -# class for validation of XML schema simple types -# -# history: -# 2004-09-09 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. -# -------------------------------------------------------------------- - - -import sys -import string -import re - - -class XsSimpleTypeVal: - - def __init__ (self, parent): - self.parent = parent - self.xmlIf = parent.xmlIf - self.xsdNSAlias = parent.xsdNSAlias - self.xsdTree = parent.xsdTree - - - ######################################## - # validate given value against simpleType - # - def checkSimpleType (self, attrName, typeName, attributeValue, returnDict): - localTypeName = self.xmlIf.extractLocalName(typeName) - if self.parent.xsdTypeDict.has_key(localTypeName): - typedefNode = self.parent.xsdTypeDict[localTypeName] - if typedefNode.getTagName () == self.xsdNSAlias + "simpleType": - self.checkSimpleTypeDef (typedefNode, attrName, attributeValue, returnDict) - else: - raise SimpleTypeError("Type '%s' must be simple type!" %(typeName)) - else: - try: - validateBaseType (typeName, attributeValue, returnDict) - except BaseTypeError, errstr: - raise SimpleTypeError("Value of '%s' (%s) %s" %(attrName, attributeValue, errstr)) - - - ######################################## - # validate given value against simpleType node - # - def checkSimpleTypeDef (self, xsdElement, attrName, attributeValue, returnDict): - restrictionElement = xsdElement.getFirstChildNS(self.xsdNSAlias, "restriction") - listElement = xsdElement.getFirstChildNS(self.xsdNSAlias, "list") - unionElement = xsdElement.getFirstChildNS(self.xsdNSAlias, "union") - if restrictionElement != None: - self._checkRestrictionTag (restrictionElement, attrName, attributeValue, returnDict) - elif listElement != None: - self._checkListTag (listElement, attrName, attributeValue, returnDict) - elif unionElement != None: - self._checkUnionTag (unionElement, attrName, attributeValue, returnDict) - - ######################################## - # validate given value against restriction node - # - def _checkRestrictionTag (self, xsdElement, attrName, attributeValue, returnDict): - # first check against base type - baseType = xsdElement.getAttribute("base") - if baseType != None: - self.checkSimpleType (attrName, baseType, attributeValue, returnDict) - else: - baseTypeNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "simpleType") - self.checkSimpleTypeDef (baseTypeNode, attrName, attributeValue, returnDict) - - minExcl = xsdElement.getFirstChildNS(self.xsdNSAlias, "minExclusive") - minIncl = xsdElement.getFirstChildNS(self.xsdNSAlias, "minInclusive") - maxExcl = xsdElement.getFirstChildNS(self.xsdNSAlias, "maxExclusive") - maxIncl = xsdElement.getFirstChildNS(self.xsdNSAlias, "maxInclusive") - - if minExcl != None: - minExclReturnDict = {} - minExclValue = minExcl.getAttribute("value") - self.checkSimpleType (attrName, baseType, minExclValue, minExclReturnDict) - if returnDict.has_key("orderedValue") and minExclReturnDict.has_key("orderedValue"): - if returnDict["orderedValue"] <= minExclReturnDict["orderedValue"]: - raise SimpleTypeError ("Value of %s (%s) is <= minExclusive (%s)" %(attrName, attributeValue, minExclValue)) - elif minIncl != None: - minInclReturnDict = {} - minInclValue = minIncl.getAttribute("value") - self.checkSimpleType (attrName, baseType, minInclValue, minInclReturnDict) - if returnDict.has_key("orderedValue") and minInclReturnDict.has_key("orderedValue"): - if returnDict["orderedValue"] < minInclReturnDict["orderedValue"]: - raise SimpleTypeError ("Value of %s (%s) is < minInclusive (%s)" %(attrName, attributeValue, minInclValue)) - if maxExcl != None: - maxExclReturnDict = {} - maxExclValue = maxExcl.getAttribute("value") - self.checkSimpleType (attrName, baseType, maxExclValue, maxExclReturnDict) - if returnDict.has_key("orderedValue") and maxExclReturnDict.has_key("orderedValue"): - if returnDict["orderedValue"] >= maxExclReturnDict["orderedValue"]: - raise SimpleTypeError ("Value of %s (%s) is >= maxExclusive (%s)" %(attrName, attributeValue, maxExclValue)) - elif maxIncl != None: - maxInclReturnDict = {} - maxInclValue = maxIncl.getAttribute("value") - self.checkSimpleType (attrName, baseType, maxInclValue, maxInclReturnDict) - if returnDict.has_key("orderedValue") and maxInclReturnDict.has_key("orderedValue"): - if returnDict["orderedValue"] > maxInclReturnDict["orderedValue"]: - raise SimpleTypeError ("Value of %s (%s) is > maxInclusive (%s)" %(attrName, attributeValue, maxInclValue)) - - totalDigitsNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "totalDigits") - if totalDigitsNode != None: - totalDigitsValue = totalDigitsNode.getAttribute("value") - if totalDigitsNode.getAttribute("fixed") == "true": - if len(re.findall("\d" ,attributeValue)) != string.atoi(totalDigitsValue): - raise SimpleTypeError ("Total number of digits != %s for %s (%s)" %(totalDigitsValue, attrName, attributeValue)) - else: - if len(re.findall("\d" ,attributeValue)) > string.atoi(totalDigitsValue): - raise SimpleTypeError ("Total number of digits > %s for %s (%s)" %(totalDigitsValue, attrName, attributeValue)) - fractionDigitsNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "fractionDigits") - if fractionDigitsNode != None: - fractionDigitsValue = fractionDigitsNode.getAttribute("value") - result = re.search("(?P\d+)(?P\.)(?P\d+)" ,attributeValue) - if result != None: - numberOfFracDigits = len (result.group('fracDigits')) - else: - numberOfFracDigits = 0 - if fractionDigitsNode.getAttribute("fixed") == "true" and numberOfFracDigits != string.atoi(fractionDigitsValue): - raise SimpleTypeError ("Fraction number of digits != %s for %s (%s)" %(fractionDigitsValue, attrName, attributeValue)) - elif numberOfFracDigits > string.atoi(fractionDigitsValue): - raise SimpleTypeError ("Fraction number of digits > %s for %s (%s)" %(fractionDigitsValue, attrName, attributeValue)) - - if returnDict.has_key("length"): - lengthNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "length") - if lengthNode != None: - length = string.atoi(lengthNode.getAttribute("value")) - if returnDict["length"] != length: - raise SimpleTypeError ("Length of %s (%s) must be %d!" %(attrName, attributeValue, length)) - minLengthNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "minLength") - if minLengthNode != None: - minLength = string.atoi(minLengthNode.getAttribute("value")) - if returnDict["length"] < minLength: - raise SimpleTypeError ("Length of %s (%s) must be >= %d!" %(attrName, attributeValue, minLength)) - maxLengthNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "maxLength") - if maxLengthNode != None: - maxLength = string.atoi(maxLengthNode.getAttribute("value")) - if returnDict["length"] > maxLength: - raise SimpleTypeError ("Length of %s (%s) must be <= %d!" %(attrName, attributeValue, maxLength)) - - enumerationElementList = xsdElement.getChildrenNS(self.xsdNSAlias, "enumeration") - if enumerationElementList != []: - for enumeration in enumerationElementList: - if enumeration.getAttribute ("value") == attributeValue: - break - else: - raise SimpleTypeError ("Enumeration value '%s' not allowed!" %(attributeValue)) - - patternNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "pattern") - if patternNode != None: - rePattern = patternNode.getAttribute("value") - regexObj = re.match(rePattern, attributeValue) - if not regexObj or regexObj.end() != len(attributeValue): - raise SimpleTypeError ("Attribute value '%s' does not match pattern '%s'!" %(attributeValue, rePattern)) - - whiteSpace = xsdElement.getFirstChildNS(self.xsdNSAlias, "whiteSpace") - if whiteSpace != None: - wsAction = whiteSpace.getAttribute("value") - if wsAction == "replace": - normalizedValue = self._normalizeString(attributeValue) - if normalizedValue != attributeValue: - returnDict["adaptedAttrValue"] = normalizedValue - elif wsAction == "collapse": - collapsedValue = self._collapseString(attributeValue) - if collapsedValue != attributeValue: - returnDict["adaptedAttrValue"] = collapsedValue - - - ######################################## - # validate given value against list node - # - def _checkListTag (self, xsdElement, attrName, attributeValue, returnDict): - if attributeValue != "": - itemType = xsdElement.getAttribute ("itemType") - # substitute multiple whitespace characters by a single ' ' - collapsedValue = self._collapseString(attributeValue) - if collapsedValue != attributeValue: - returnDict["adaptedAttrValue"] = collapsedValue - - # divide up attributeValue => store it into list - attributeList = string.split(collapsedValue, " ") - for attrValue in attributeList: - elementReturnDict = {} - if itemType != None: - self.checkSimpleType (attrName, itemType, attrValue, elementReturnDict) - else: - itemTypeNode = xsdElement.getFirstChildNS(self.xsdNSAlias, "simpleType") - self.checkSimpleTypeDef (itemTypeNode, attrName, attrValue, elementReturnDict) - - returnDict["length"] = len(attributeList) - else: - returnDict["length"] = 0 - - - ######################################## - # validate given value against union node - # - def _checkUnionTag (self, xsdElement, attrName, attributeValue, returnDict): - memberTypes = xsdElement.getAttribute ("memberTypes") - if memberTypes != None: - # substitute multiple whitespace characters by a single ' ' - # divide up attributeValue => store it into list - for memberType in string.split(self._collapseString(memberTypes), " "): - try: - self.checkSimpleType (attrName, memberType, attributeValue, returnDict) - return - except SimpleTypeError, errstr: - pass - - # memberTypes and additional type definitions is legal! - for childSimpleType in xsdElement.getChildrenNS(self.xsdNSAlias, "simpleType"): - try: - self.checkSimpleTypeDef (childSimpleType, attrName, attributeValue, returnDict) - return - except SimpleTypeError, errstr: - pass - - raise SimpleTypeError ("%s (%s) is no valid union member type (%s)!" %(attrName, attributeValue, memberTypes)) - - - ######################################## - # substitute multiple whitespace characters by a single ' ' - # - def _collapseString (self, strValue): - return re.sub('\s+', ' ', strValue) - - ######################################## - # substitute each whitespace characters by a single ' ' - # - def _normalizeString (self, strValue): - return re.sub('\s', ' ', strValue) - - - - -def validateBaseType (simpleType, attributeValue, returnDict): -# TODO: Many base types are not completely defined by datatypes.xsd - simpleTypeDict = {"xsd:string": _checkStringType, - "xsd:hexBinary": _checkHexBinaryType, - "xsd:integer": _checkIntegerType, - "xsd:boolean": _checkBooleanType, - "xsd:QName": _checkQNameType, - } - - simpleType = string.replace(simpleType, "xs:", "xsd:") - if simpleTypeDict.has_key (simpleType): - simpleTypeDict[simpleType] (simpleType, attributeValue, returnDict) - - elif simpleType != "xsd:anySimpleType": - if simpleType in ("xsd:decimal", "xsd:float", "xsd:double", "xsd:base64Binary", "xsd:anyURI", "xsd:NOTATION", - "xsd:duration", "xsd:dateTime", "xsd:time", "xsd:date", - "xsd:gYearMonth", "xsd:gMonthDay", "xsd:gYear", "xsd:gMonth", "xsd:gDay"): - print "INFO: Check of simple type '%s' currently not supported!" %(simpleType) - else: - # TODO: Fehler im XSD-File => Check muss an anderer Stelle erfolgen - raise BaseTypeError("uses unknown type '%s'!" %(simpleType)) - - -def _checkStringType (simpleType, attributeValue, returnDict): - # all valid?? - returnDict["length"] = len(attributeValue) - -def _checkHexBinaryType (simpleType, attributeValue, returnDict): - _checkIntegerRange (attributeValue, 16, 0, sys.maxint, returnDict) - returnDict["length"] = len(attributeValue) - -def _checkIntegerType (simpleType, attributeValue, returnDict): - _checkIntegerRange (attributeValue, 10, -sys.maxint-1, sys.maxint, returnDict) - -def _checkBooleanType (simpleType, attributeValue, returnDict): - if attributeValue not in ("true", "false", "1", "0"): - raise BaseTypeError("is not a boolean value!") - -def _checkQNameType (simpleType, attributeValue, returnDict): - # TODO: fill - returnDict["length"] = len(attributeValue) - -def _checkIntegerRange (attributeValue, base, minBase, maxBase, returnDict): - try: - value = string.atoi (attributeValue, base=base) - except: - if base == 16: - raise BaseTypeError("is not a hexadecimal value!") - else: - raise BaseTypeError("is not an integer!") - - if value < minBase or value > maxBase: - raise BaseTypeError("is out of range (%d..%d)!" %(minBase, maxBase)) - - returnDict["orderedValue"] = value - - - -######################################## -# define own exception for XML schema validation errors -# -class SimpleTypeError (StandardError): - pass - -class BaseTypeError (StandardError): - pass