pyxsval.py
Go to the documentation of this file.
00001 #
00002 # minixsv, Release 0.9.0
00003 # file: pyxsval.py
00004 #
00005 # API for XML schema validator
00006 #
00007 # history:
00008 # 2004-09-09 rl   created
00009 # 2004-09-29 rl   adapted to re-designed XML interface classes,
00010 #                 ErrorHandler separated, URL processing added, some bugs fixed
00011 # 2004-10-07 rl   Validator classes extracted into separate files
00012 # 2004-10-12 rl   API re-worked, XML text processing added
00013 # 2007-05-15 rl   Handling of several schema files added,
00014 #                 schema references in the input file have now priority (always used if available!)
00015 # 2008-08-01 rl   New optional parameter 'useCaching=1' and 'processXInclude=1' to XsValidator class added
00016 #
00017 # Copyright (c) 2004-2008 by Roland Leuthe.  All rights reserved.
00018 #
00019 # --------------------------------------------------------------------
00020 # The minixsv XML schema validator is
00021 #
00022 # Copyright (c) 2004-2008 by Roland Leuthe
00023 #
00024 # By obtaining, using, and/or copying this software and/or its
00025 # associated documentation, you agree that you have read, understood,
00026 # and will comply with the following terms and conditions:
00027 #
00028 # Permission to use, copy, modify, and distribute this software and
00029 # its associated documentation for any purpose and without fee is
00030 # hereby granted, provided that the above copyright notice appears in
00031 # all copies, and that both that copyright notice and this permission
00032 # notice appear in supporting documentation, and that the name of
00033 # the author not be used in advertising or publicity
00034 # pertaining to distribution of the software without specific, written
00035 # prior permission.
00036 #
00037 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
00038 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
00039 # ABILITY AND FITNESS.  IN NO EVENT SHALL THE AUTHOR
00040 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
00041 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00042 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00043 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
00044 # OF THIS SOFTWARE.
00045 # --------------------------------------------------------------------
00046 
00047 __all__ = [
00048     # public symbols
00049     "addUserSpecXmlIfClass",
00050     "parseAndValidate",
00051     "parseAndValidateString",
00052     "parseAndValidateXmlInput",
00053     "parseAndValidateXmlInputString",
00054     "parseAndValidateXmlSchema",
00055     "parseAndValidateXmlSchemaString",
00056     "XsValidator",
00057     ]
00058 
00059 
00060 import string
00061 from .. import genxmlif
00062 from ..minixsv           import *
00063 from xsvalErrorHandler import ErrorHandler
00064 from xsvalXmlIf        import XsvXmlElementWrapper
00065 from xsvalBase         import XsValBase
00066 from xsvalSchema       import XsValSchema
00067 
00068 
00069 __author__  = "Roland Leuthe <roland@leuthe-net.de>"
00070 __date__    = "08. August 2008"
00071 __version__ = "0.9.0"
00072 
00073 
00074 _XS_VAL_DEFAULT_ERROR_LIMIT = 20
00075 
00076 rulesTreeWrapper = None   # XML tree cache for "XMLSchema.xsd"
00077 
00078 
00079 ########################################
00080 # retrieve version of minixsv
00081 #
00082 def getVersion ():
00083     return __version__
00084 
00085 
00086 ########################################
00087 # access function for adding a user specific XML interface class
00088 #
00089 def addUserSpecXmlIfClass (xmlIfKey, factory):
00090     if not _xmlIfDict.has_key(xmlIfKey):
00091         _xmlIfDict[xmlIfKey] = factory
00092     else:
00093         raise KeyError, "xmlIfKey %s already implemented!" %(xmlIfKey)
00094 
00095 
00096 ########################################
00097 # convenience function for validating
00098 # 1. XML schema file
00099 # 2. XML input file
00100 # If xsdFile is specified, it will ONLY be used for validation if no schema file 
00101 # is specified in the input file
00102 # If xsdFile=None, the schemaLocation attribute is expected in the root tag of the XML input file
00103 #
00104 def parseAndValidate (inputFile, xsdFile=None, **kw):
00105     return parseAndValidateXmlInput (inputFile, xsdFile, 1, **kw)
00106 
00107 
00108 ########################################
00109 # convenience function for validating
00110 # 1. text string containing the XML schema
00111 # 2. text string containing the XML input
00112 # If xsdText is given, it will ONLY be used for validation if no schema file
00113 # is specified in the input text
00114 # If xsdText=None, the schemaLocation attribute is expected in the root tag of the XML input
00115 #
00116 def parseAndValidateString (inputText, xsdText=None, **kw):
00117     return parseAndValidateXmlInputString (inputText, xsdText, 1, **kw)
00118 
00119 
00120 ########################################
00121 # factory for validating
00122 # 1. XML schema file (only if validateSchema=1)
00123 # 2. XML input file
00124 # If xsdFile is specified, it will ONLY be used for validation if no schema file 
00125 # is specified in the input file
00126 # If xsdFile=None, the schemaLocation attribute is expected in the root tag of the XML input file
00127 #
00128 def parseAndValidateXmlInput (inputFile, xsdFile=None, validateSchema=0, **kw):
00129     xsValidator = XsValidator (**kw)
00130     # parse XML input file
00131     inputTreeWrapper = xsValidator.parse (inputFile)
00132     # validate XML input file
00133     return xsValidator.validateXmlInput (inputFile, inputTreeWrapper, xsdFile, validateSchema)
00134 
00135 
00136 ########################################
00137 # factory for validating
00138 # 1. text string containing the XML schema (only if validateSchema=1)
00139 # 2. text string containing the XML input
00140 # If xsdText is given, it will ONLY be used for validation if no schema file
00141 # is specified in the input text
00142 # If xsdText=None, the schemaLocation attribute is expected in the root tag of the XML input
00143 #
00144 def parseAndValidateXmlInputString (inputText, xsdText=None, baseUrl="", validateSchema=0, **kw):
00145     xsValidator = XsValidator (**kw)
00146     # parse XML input text string
00147     inputTreeWrapper = xsValidator.parseString (inputText, baseUrl)
00148     # validate XML input text string
00149     return xsValidator.validateXmlInputString (inputTreeWrapper, xsdText, validateSchema)
00150 
00151 
00152 ########################################
00153 # factory for validating only given XML schema file
00154 #
00155 def parseAndValidateXmlSchema (xsdFile, **kw):
00156     xsValidator = XsValidator (**kw)
00157     # parse XML schema file
00158     xsdTreeWrapper = xsValidator.parse (xsdFile)
00159     # validate XML schema file
00160     return xsValidator.validateXmlSchema (xsdFile, xsdTreeWrapper)
00161 
00162 
00163 ########################################
00164 # factory for validating only given XML schema file
00165 #
00166 def parseAndValidateXmlSchemaString (xsdText, **kw):
00167     xsValidator = XsValidator (**kw)
00168     # parse XML schema
00169     xsdTreeWrapper = xsValidator.parseString (xsdText)
00170     # validate XML schema
00171     return xsValidator.validateXmlSchema ("", xsdTreeWrapper)
00172 
00173 
00174 ########################################
00175 # XML schema validator class
00176 #
00177 class XsValidator:
00178     def __init__(self, xmlIfClass=XMLIF_MINIDOM,
00179                  elementWrapperClass=XsvXmlElementWrapper,
00180                  warningProc=IGNORE_WARNINGS, errorLimit=_XS_VAL_DEFAULT_ERROR_LIMIT, 
00181                  verbose=0, useCaching=1, processXInclude=1):
00182 
00183         self.warningProc    = warningProc
00184         self.errorLimit     = errorLimit
00185         self.verbose        = verbose
00186 
00187         # select XML interface class
00188         self.xmlIf = _xmlIfDict[xmlIfClass](verbose, useCaching, processXInclude)
00189         self.xmlIf.setElementWrapperClass (elementWrapperClass)
00190 
00191         # create error handler
00192         self.errorHandler  = ErrorHandler (errorLimit, warningProc, verbose)
00193 
00194         self.schemaDependancyList = []
00195 
00196 
00197     ########################################
00198     # retrieve current version
00199     #
00200     def getVersion (self):
00201         return __version__
00202         
00203 
00204     ########################################
00205     # parse XML file
00206     # 'file' may be a filepath or an URI
00207     #
00208     def parse (self, file, baseUrl="", ownerDoc=None):
00209         self._verbosePrint ("Parsing %s..." %(file))
00210         return self.xmlIf.parse(file, baseUrl, ownerDoc)
00211 
00212 
00213     ########################################
00214     # parse text string containing XML
00215     #
00216     def parseString (self, text, baseUrl=""):
00217         self._verbosePrint ("Parsing XML text string...")
00218         return self.xmlIf.parseString(text, baseUrl)
00219 
00220 
00221     ########################################
00222     # validate XML input
00223     #
00224     def validateXmlInput (self, xmlInputFile, inputTreeWrapper, xsdFile=None, validateSchema=0):
00225         # if the input file contains schema references => use these
00226         xsdTreeWrapperList = self._readReferencedXsdFiles(inputTreeWrapper, validateSchema)
00227         if xsdTreeWrapperList == []:
00228             # if the input file doesn't contain schema references => use given xsdFile
00229             if xsdFile != None:
00230                 xsdTreeWrapper = self.parse (xsdFile)
00231                 xsdTreeWrapperList.append(xsdTreeWrapper)
00232                 # validate XML schema file if requested
00233                 if validateSchema:
00234                     self.validateXmlSchema (xsdFile, xsdTreeWrapper)
00235             else:
00236                 self.errorHandler.raiseError ("No schema file specified!")
00237 
00238         self._validateXmlInput (xmlInputFile, inputTreeWrapper, xsdTreeWrapperList)
00239         for xsdTreeWrapper in xsdTreeWrapperList:
00240             xsdTreeWrapper.unlink()
00241         return inputTreeWrapper
00242 
00243     ########################################
00244     # validate XML input
00245     #
00246     def validateXmlInputString (self, inputTreeWrapper, xsdText=None, validateSchema=0):
00247         # if the input file contains schema references => use these
00248         xsdTreeWrapperList = self._readReferencedXsdFiles(inputTreeWrapper, validateSchema)
00249         if xsdTreeWrapperList == []:
00250             # if the input file doesn't contain schema references => use given xsdText
00251             if xsdText != None:
00252                 xsdFile = "schema text"
00253                 xsdTreeWrapper = self.parseString (xsdText)
00254                 xsdTreeWrapperList.append(xsdTreeWrapper)
00255                 # validate XML schema file if requested
00256                 if validateSchema:
00257                     self.validateXmlSchema (xsdFile, xsdTreeWrapper)
00258             else:
00259                 self.errorHandler.raiseError ("No schema specified!")
00260 
00261         self._validateXmlInput ("input text", inputTreeWrapper, xsdTreeWrapperList)
00262         for xsdTreeWrapper in xsdTreeWrapperList:
00263             xsdTreeWrapper.unlink()
00264         return inputTreeWrapper
00265 
00266 
00267     ########################################
00268     # validate XML schema separately
00269     #
00270     def validateXmlSchema (self, xsdFile, xsdTreeWrapper):
00271         # parse minixsv internal schema
00272         global rulesTreeWrapper
00273         if rulesTreeWrapper == None:
00274             rulesTreeWrapper = self.parse(os.path.join (MINIXSV_DIR, "XMLSchema.xsd"))
00275 
00276         self._verbosePrint ("Validating %s..." %(xsdFile))
00277         xsvGivenXsdFile = XsValSchema (self.xmlIf, self.errorHandler, self.verbose)
00278         xsvGivenXsdFile.validate(xsdTreeWrapper, [rulesTreeWrapper,])
00279         self.schemaDependancyList.append (xsdFile)
00280         self.schemaDependancyList.extend (xsvGivenXsdFile.xsdIncludeDict.keys())
00281         xsvGivenXsdFile.unlink()
00282         self.errorHandler.flushOutput()
00283         return xsdTreeWrapper
00284 
00285 
00286     ########################################
00287     # validate XML input tree and xsd tree if requested
00288     #
00289     def _validateXmlInput (self, xmlInputFile, inputTreeWrapper, xsdTreeWrapperList):
00290         self._verbosePrint ("Validating %s..." %(xmlInputFile))
00291         xsvInputFile = XsValBase (self.xmlIf, self.errorHandler, self.verbose)
00292         xsvInputFile.validate(inputTreeWrapper, xsdTreeWrapperList)
00293         xsvInputFile.unlink()
00294         self.errorHandler.flushOutput()
00295 
00296 
00297     ########################################
00298     # retrieve XML schema location from XML input tree
00299     #
00300     def _readReferencedXsdFiles (self, inputTreeWrapper, validateSchema):
00301         xsdTreeWrapperList = []
00302         # a schemaLocation attribute is expected in the root tag of the XML input file
00303         xsdFileList = self._retrieveReferencedXsdFiles (inputTreeWrapper)
00304         for namespace, xsdFile in xsdFileList:
00305             try:
00306                 xsdTreeWrapper = self.parse (xsdFile, inputTreeWrapper.getRootNode().getAbsUrl())
00307             except IOError, e:
00308                 if e.errno == 2: # catch IOError: No such file or directory
00309                     self.errorHandler.raiseError ("XML schema file %s not found!" %(xsdFile), inputTreeWrapper.getRootNode())
00310                 else:
00311                     raise IOError(e.errno, e.strerror, e.filename)
00312 
00313             xsdTreeWrapperList.append(xsdTreeWrapper)
00314             # validate XML schema file if requested
00315             if validateSchema:
00316                 self.validateXmlSchema (xsdFile, xsdTreeWrapper)
00317 
00318             if namespace != xsdTreeWrapper.getRootNode().getAttributeOrDefault("targetNamespace", None):
00319                 self.errorHandler.raiseError ("Namespace of 'schemaLocation' attribute doesn't match target namespace of %s!" %(xsdFile), inputTreeWrapper.getRootNode())
00320             
00321         return xsdTreeWrapperList
00322 
00323 
00324     ########################################
00325     # retrieve XML schema location from XML input tree
00326     #
00327     def _retrieveReferencedXsdFiles (self, inputTreeWrapper):
00328         # a schemaLocation attribute is expected in the root tag of the XML input file
00329         inputRootNode = inputTreeWrapper.getRootNode()
00330         xsdFileList = []
00331 
00332         if inputRootNode.hasAttribute((XSI_NAMESPACE, "schemaLocation")):
00333             attributeValue = inputRootNode.getAttribute((XSI_NAMESPACE, "schemaLocation"))
00334             attrValList = string.split(attributeValue)
00335             if len(attrValList) % 2 == 0:
00336                 for i in range(0, len(attrValList), 2):
00337                     xsdFileList.append((attrValList[i], attrValList[i+1]))
00338             else:
00339                 self.errorHandler.raiseError ("'schemaLocation' attribute must have even number of URIs (pairs of namespace and xsdFile)!")
00340 
00341         if inputRootNode.hasAttribute((XSI_NAMESPACE, "noNamespaceSchemaLocation")):
00342             attributeValue = inputRootNode.getAttribute((XSI_NAMESPACE, "noNamespaceSchemaLocation"))
00343             attrValList = string.split(attributeValue)
00344             for attrVal in attrValList:
00345                 xsdFileList.append ((None, attrVal))
00346 
00347         return xsdFileList
00348 
00349     ########################################
00350     # print if verbose flag is set
00351     #
00352     def _verbosePrint (self, text):
00353         if self.verbose:
00354             print text
00355 
00356 
00357 ########################################
00358 # factory functions for enabling the selected XML interface class
00359 #
00360 def _interfaceFactoryMinidom (verbose, useCaching, processXInclude):
00361     return genxmlif.chooseXmlIf(genxmlif.XMLIF_MINIDOM, verbose, useCaching, processXInclude)
00362 
00363 def _interfaceFactory4Dom (verbose, useCaching, processXInclude):
00364     return genxmlif.chooseXmlIf(genxmlif.XMLIF_4DOM, verbose, useCaching, processXInclude)
00365 
00366 def _interfaceFactoryElementTree (verbose, useCaching, processXInclude):
00367     return genxmlif.chooseXmlIf(genxmlif.XMLIF_ELEMENTTREE, verbose, useCaching, processXInclude)
00368 
00369 
00370 _xmlIfDict = {XMLIF_MINIDOM    :_interfaceFactoryMinidom,
00371               XMLIF_4DOM       :_interfaceFactory4Dom,
00372               XMLIF_ELEMENTTREE:_interfaceFactoryElementTree}
00373 


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