From b0bfb51a1b7909b59c23e2222d40b5b61088c9af Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 18 Sep 2020 13:23:37 +0100 Subject: [PATCH] Adding XSD testing --- testing/check_xsd.py | 155 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 testing/check_xsd.py diff --git a/testing/check_xsd.py b/testing/check_xsd.py new file mode 100644 index 0000000..db4ee8c --- /dev/null +++ b/testing/check_xsd.py @@ -0,0 +1,155 @@ +import logging + +import glob +import sys +import argparse +from pathlib import Path +from pprint import pprint +import os + +from lxml import etree +from xml.etree.ElementTree import ParseError +from xmlschema import XMLSchema, XMLSchemaParseError + + +def BuildSchemaDictonary (fileList): + if len(fileList) == 0: + logging.info("No schema files provided") + return [] + + logging.info("Schema locations:") + schemaLocations = [] + for schemaFile in fileList: + try: + xs = XMLSchema(schemaFile, validation='skip') + schemaLocations.append((xs.default_namespace, str(Path(schemaFile).resolve()))) + logging.info(" [ {0} -> {1} ]".format(xs.default_namespace, schemaFile)) + except ParseError as ex: + logging.warning (" [ {0} failed to parse: {1} ]".format(schemaFile, ex)) + return schemaLocations + + +def BuildSchema (coreFile, fileList = None): + schemaLocations = [] + if fileList and len(fileList) > 0: + schemaLocations = BuildSchemaDictonary(fileList) + + coreSchema = XMLSchema(str(Path(coreFile)), locations=schemaLocations) + return coreSchema + +def ValidateSingleFile (schemaFile): + try: + xs = XMLSchema(schemaFile, validation='skip') + except ParseError as ex: + logging.warning (" [ {0} failed to parse: {1} ]".format(schemaFile, ex)) + return ex + return None + + +def ValidateXSDFiles (fileList): + if len(fileList) == 0: + logging.info("No schema files provided") + return {} + + schemaLocations = BuildSchemaDictonary(fileList) + errors = {} + + logging.info("Schema validation:") + for schemaFile in fileList: + try: + schema = XMLSchema(schemaFile, locations = schemaLocations) + logging.info(schemaFile + ": OK") + errors[schemaFile] = [] + except XMLSchemaParseError as ex: + if (ex.schema_url) and (ex.schema_url != ex.origin_url): + logging.info(" Error {1} comes from {0}, suppressing".format(ex.schema_url, ex.message)) + errors[schemaFile] = [] + else: + logging.warning(schemaFile + ": Failed validation ({0})".format(ex)) + errors[schemaFile] = [ex.message] + return errors + + +def ValidateInstanceDocuments (coreFile, supportingSchemas, instanceDocs): + if (instanceDocs is None) or len(instanceDocs) == 0: + logging.warning ("No instance documents provided") + return [] + + schema = BuildSchema(coreFile, supportingSchemas) + errors = [] + for instanceDoc in instanceDocs: + try: + schema.validate(instanceDoc) + logging.info ("{0} passed validation".format(instanceDoc)) + except Exception as ex: + logging.error ("{0} failed validation: {1}".format(instanceDoc, ex)) + return errors + + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbosity", help="verbosity level", action="count", default=0) + parser.add_argument("input", help="include a directory or file", action="append", nargs="+") + args = parser.parse_args() + + logging.getLogger().setLevel(logging.WARNING) + if (args.verbosity >= 1): + logging.getLogger().setLevel(logging.INFO) + if (args.verbosity >= 2): + logging.getLogger().setLevel(logging.DEBUG) + logging.debug("Very verbose selected") + + logging.debug(f"Path: {args.input}") + includeFileList = [] + for path in args.input[0]: + p = Path(path) + if not p.exists(): + logging.error(f"Include path {path} not found") + exit(1) + if p.is_dir(): + logging.debug(f"Expanding directory") + for g in glob.glob(os.path.join(str(p), "*.xsd")): + logging.info(f">Including {g}") + includeFileList.append(g) + else: + logging.info(f"Including {p.absolute()}") + includeFileList.append(p.absolute()) + + syntaxErrors = 0 + + print ("XSD syntax checks:") + print ("-----------------------------") + for file in includeFileList: + error = ValidateSingleFile(file) + if (error): + print (f" {file} : Syntax error [{error}]") + syntaxErrors += 1 + else: + print (f" {file} : OK") + + print ("-----------------------------") + if (syntaxErrors > 0): + print (f"{syntaxErrors} syntax errors detected") + exit(syntaxErrors) + + results = ValidateXSDFiles(includeFileList) + + print ("XSD build checks:") + print ("-----------------------------") + errorCount = 0 + for fileName, errors in results.items(): + if len(errors) > 0: + errorCount += len(errors) + print (f" {fileName}: {len(errors)} errors") + for error in errors: + if isinstance(error, XMLSchemaParseError): + print (error.msg) + else: + print (f" {str(error.strip())}") + else: + print (f" {fileName}: OK") + + print ("-----------------------------") + print (f"{errorCount} build errors detected") + exit(errorCount) \ No newline at end of file -- GitLab