diff -r 000000000000 -r b622defdfd98 minixsv/pyxsval.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/minixsv/pyxsval.py Wed Jan 31 16:31:39 2007 +0100 @@ -0,0 +1,283 @@ +# +# minixsv, Release 0.3 +# file: pyxsval.py +# +# API for XML schema validator +# +# history: +# 2004-09-09 rl created +# 2004-09-29 rl adapted to re-designed XML interface classes, +# ErrorHandler separated, URL processing added, some bugs fixed +# 2004-10-07 rl Validator classes extracted into separate files +# 2004-10-12 rl API re-worked, XML text processing added +# +# 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. +# -------------------------------------------------------------------- + +__all__ = [ + # public symbols + "parseAndValidate", + "parseAndValidateString", + "parseAndValidateXmlInput", + "parseAndValidateXmlInputString", + "parseAndValidateXmlSchema", + "parseAndValidateXmlSchemaString", + "XsValidator", + "XMLIF_MINIDOM", + "XMLIF_ELEMENTTREE" + ] + + +from xsvalErrorHandler import * +from xsvalBase import XsValBase +from xsvalSchema import XsValSchema + + +XMLIF_MINIDOM = "XMLIF_MINIDOM" +XMLIF_ELEMENTTREE = "XMLIF_ELEMENTTREE" + + +_XS_VAL_DEFAULT_ERROR_LIMIT = 20 + +_OWNDIR = os.path.dirname(__file__) + + +######################################## +# convenience function for validating +# 1. XML schema file +# 2. XML input file +# If xsdFile is specified, it will be used for validation +# If xsdFile=None, the schemaLocation attribute is expected in the root tag of the XML input file +# +def parseAndValidate (inputFile, xsdFile=None, **kw): + return parseAndValidateXmlInput (inputFile, xsdFile, 1, **kw) + + +######################################## +# convenience function for validating +# 1. text string containing the XML schema +# 2. text string containing the XML input +# If xsdText is given, it will be used for validation +# If xsdText=None, the schemaLocation attribute is expected in the root tag of the XML input +# +def parseAndValidateString (inputText, xsdText=None, **kw): + return parseAndValidateXmlInputString (inputText, xsdText, 1, **kw) + + +######################################## +# factory for validating +# 1. XML schema file (only if validateSchema=1) +# 2. XML input file +# If xsdFile is specified, it will be used for validation +# If xsdFile=None, the schemaLocation attribute is expected in the root tag of the XML input file +# +def parseAndValidateXmlInput (inputFile, xsdFile=None, validateSchema=0, **kw): + xsValidator = XsValidator (**kw) + # parse XML input file + inputTreeWrapper = xsValidator.parse (inputFile) + # validate XML input file + return xsValidator.validateXmlInput (inputFile, inputTreeWrapper, xsdFile, validateSchema) + + +######################################## +# factory for validating +# 1. text string containing the XML schema (only if validateSchema=1) +# 2. text string containing the XML input +# If xsdText is given, it will be used for validation +# If xsdText=None, the schemaLocation attribute is expected in the root tag of the XML input +# +def parseAndValidateXmlInputString (inputText, xsdText=None, validateSchema=0, **kw): + xsValidator = XsValidator (**kw) + # parse XML input text string + inputTreeWrapper = xsValidator.parseString (inputText) + # validate XML input text string + return xsValidator.validateXmlInputString (inputTreeWrapper, xsdText, validateSchema) + + +######################################## +# factory for validating only given XML schema file +# +def parseAndValidateXmlSchema (xsdFile, **kw): + xsValidator = XsValidator (**kw) + # parse XML schema file + xsdTreeWrapper = xsValidator.parse (xsdFile) + # validate XML schema file + return xsValidator.validateXmlSchema (xsdFile, xsdTreeWrapper) + + +######################################## +# factory for validating only given XML schema file +# +def parseAndValidateXmlSchemaString (xsdText, **kw): + xsValidator = XsValidator (**kw) + # parse XML schema + xsdTreeWrapper = xsValidator.parseString (xsdText) + # validate XML schema + return xsValidator.validateXmlSchema ("", xsdTreeWrapper) + + +######################################## +# XML schema validator class +# +class XsValidator: + def __init__(self, xmlIfClass=XMLIF_MINIDOM, + warningProc=IGNORE_WARNINGS, errorLimit=_XS_VAL_DEFAULT_ERROR_LIMIT, verbose=0): + + self.warningProc = warningProc + self.errorLimit = errorLimit + self.verbose = verbose + + # enable interface to minidom + if xmlIfClass == XMLIF_MINIDOM: + import minidomif + self.xmlIf = minidomif.MiniDomInterface(verbose) + + # enable interface to elementtree + elif xmlIfClass == XMLIF_ELEMENTTREE: + import elemtreeif + self.xmlIf = elemtreeif.ElementTreeInterface(verbose) + + # create error handler + self.errorHandler = ErrorHandler (errorLimit, warningProc, verbose) + + + ######################################## + # parse XML file + # 'file' may be a filepath or an URI + # + def parse (self, file, baseUrl=""): + try: + self._verbosePrint ("Parsing %s..." %(file)) + treeWrapper = self.xmlIf.extParse(file, baseUrl) + except AssertionError, errstr: + self.errorHandler.raiseError (errstr) + return treeWrapper + + + ######################################## + # parse text string containing XML + # + def parseString (self, text): + try: + self._verbosePrint ("Parsing XML text string...") + treeWrapper = self.xmlIf.extParseString(text) + except AssertionError, errstr: + self.errorHandler.raiseError (errstr) + return treeWrapper + + + ######################################## + # validate XML input + # + def validateXmlInput (self, xmlInputFile, inputTreeWrapper, xsdFile=None, validateSchema=0): + # parse XML schema file + if xsdFile != None: + xsdTreeWrapper = self.parse (xsdFile) + else: + # a schemaLocation attribute is expected in the root tag of the XML input file + xsdFile = self._retrieveReferencedXsdFile (inputTreeWrapper) + xsdTreeWrapper = self.parse (xsdFile, inputTreeWrapper.getRootNode().getAbsUrl()) + + return self._validateXmlInput (xmlInputFile, xsdFile, inputTreeWrapper, xsdTreeWrapper, validateSchema) + + + ######################################## + # validate XML input + # + def validateXmlInputString (self, inputTreeWrapper, xsdText=None, validateSchema=0): + # parse XML schema file + if xsdText != None: + xsdFile = "schema text" + xsdTreeWrapper = self.parseString (xsdText) + else: + # a schemaLocation attribute is expected in the root tag of the XML input file + xsdFile = self._retrieveReferencedXsdFile (inputTreeWrapper) + xsdTreeWrapper = self.parse (xsdFile, inputTreeWrapper.getRootNode().getAbsUrl()) + + return self._validateXmlInput ("input text", xsdFile, inputTreeWrapper, xsdTreeWrapper, validateSchema) + + + ######################################## + # validate XML schema separately + # + def validateXmlSchema (self, xsdFile, xsdTreeWrapper): + # parse minixsv internal schema + rulesTreeWrapper = self.parse(os.path.join (_OWNDIR, "xsStructs.xsd")) + + self._verbosePrint ("Validating %s..." %(xsdFile)) + xsvGivenXsdFile = XsValSchema (self.xmlIf, self.errorHandler) + xsvGivenXsdFile.validate(xsdTreeWrapper, rulesTreeWrapper) + self.errorHandler.flushOutput() + return xsdTreeWrapper + + + ######################################## + # validate XML input tree and xsd tree if requested + # + def _validateXmlInput (self, xmlInputFile, xsdFile, inputTreeWrapper, xsdTreeWrapper, validateSchema=0): + # validate XML schema file if requested + if validateSchema: + self.validateXmlSchema (xsdFile, xsdTreeWrapper) + + try: + xsdTreeWrapper.insertSubtree (xsdTreeWrapper.getRootNode().getFirstChild(), os.path.join (_OWNDIR, "datatypes2.xsd"), None) + except AssertionError, errstr: + self.errorHandler.raiseError (errstr) + + self._verbosePrint ("Validating %s..." %(xmlInputFile)) + xsvInputFile = XsValBase (self.xmlIf, self.errorHandler) + xsvInputFile.validate(inputTreeWrapper, xsdTreeWrapper) + self.errorHandler.flushOutput() + return inputTreeWrapper + + + ######################################## + # retrieve XML schema location from XML input tree + # + def _retrieveReferencedXsdFile (self, inputTreeWrapper): + # a schemaLocation attribute is expected in the root tag of the XML input file + for attributeName, attributeValue in inputTreeWrapper.getRootNode().getAttributeDict().items(): + if self.xmlIf.extractLocalName(attributeName) in ("noNamespaceSchemaLocation", "schemaLocation"): + xsdFile = attributeValue + return xsdFile + else: + self.errorHandler.raiseError ("No schema file specified!") + + + ######################################## + # print if verbose flag is set + # + def _verbosePrint (self, text): + if self.verbose: + print text + + + +