From bd76bbd625059c4d05693d853c98348ac7b63678 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 14 Oct 2019 22:56:03 +0200 Subject: [PATCH] Add an XSD validation scheme and implement ParameterManager::CheckDocument(), function is used in the parameter editor --- src/Base/CMakeLists.txt | 2 + src/Base/Parameter.cpp | 76 ++++++++++++++++++++++++++++++++++++- src/Base/Parameter.xsd | 57 ++++++++++++++++++++++++++++ src/Base/PreCompiled.h | 2 + src/Gui/DlgParameterImp.cpp | 1 + 5 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/Base/Parameter.xsd diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index 790262ac93..be5bbc4944 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -89,6 +89,7 @@ generate_from_xml(PlacementPy) generate_from_xml(AxisPy) generate_from_xml(UnitPy) generate_from_xml(QuantityPy) +generate_from_any(Parameter.xsd Parameter.inl xmlSchemeString) if(SWIG_FOUND) # Create the file swigpyrun.hh and then compare with the file swigpyrun.h. @@ -254,6 +255,7 @@ SET(FreeCADBase_CPP_SRCS Matrix.cpp MatrixPyImp.cpp MemDebug.cpp + Parameter.xsd Parameter.cpp ParameterPy.cpp Persistence.cpp diff --git a/src/Base/Parameter.cpp b/src/Base/Parameter.cpp index f633e604e7..bfab1492fb 100644 --- a/src/Base/Parameter.cpp +++ b/src/Base/Parameter.cpp @@ -39,6 +39,8 @@ # include # include # include +# include +# include # include # include # include @@ -62,6 +64,7 @@ #endif #include "Parameter.h" +#include "Parameter.inl" #include "Exception.h" #include "Console.h" @@ -1369,6 +1372,7 @@ void ParameterManager::SaveDocument(XMLFormatTarget* pFormatTarget) const #else try { std::unique_ptr myFilter; + std::unique_ptr myErrorHandler; // get a serializer, an instance of DOMWriter XMLCh tempStr[100]; @@ -1378,8 +1382,7 @@ void ParameterManager::SaveDocument(XMLFormatTarget* pFormatTarget) const // set user specified end of line sequence and output encoding theSerializer->setNewLine(gMyEOLSequence); - DOMConfiguration* config = theSerializer->getDomConfig(); - config->setParameter(XStr("format-pretty-print").unicodeForm(),true); + // // do the serialization through DOMWriter::writeNode(); @@ -1396,8 +1399,25 @@ void ParameterManager::SaveDocument(XMLFormatTarget* pFormatTarget) const theSerializer->setFilter(myFilter.get()); } + // plug in user's own error handler + myErrorHandler.reset(new DOMPrintErrorHandler()); + DOMConfiguration* config = theSerializer->getDomConfig(); + config->setParameter(XMLUni::fgDOMErrorHandler, myErrorHandler.get()); + + // set feature if the serializer supports the feature/mode + if (config->canSetParameter(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections)) + config->setParameter(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections); + + if (config->canSetParameter(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent)) + config->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent); + + if (config->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint)) + config->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint); + theOutput->setByteStream(pFormatTarget); theSerializer->write(_pDocument, theOutput); + + theOutput->release(); } theSerializer->release(); @@ -1429,7 +1449,59 @@ void ParameterManager::CreateDocument(void) void ParameterManager::CheckDocument() const { + if (!_pDocument) + return; + try { + // + // Plug in a format target to receive the resultant + // XML stream from the serializer. + // + // LocalFileFormatTarget prints the resultant XML stream + // to a file once it receives any thing from the serializer. + // + MemBufFormatTarget myFormTarget; + SaveDocument(&myFormTarget); + + // Either use the file saved on disk or write the current XML into a buffer in memory + // const char* xmlFile = "..."; + MemBufInputSource xmlFile(myFormTarget.getRawBuffer(), myFormTarget.getLen(), "(memory)"); + + // Either load the XSD file from disk or use the built-in string + // const char* xsdFile = "..."; + std::string xsdStr(xmlSchemeString); + MemBufInputSource xsdFile(reinterpret_cast(xsdStr.c_str()), xsdStr.size(), "Parameter.xsd"); + + // See http://apache-xml-project.6118.n7.nabble.com/validating-xml-with-xsd-schema-td17515.html + // + XercesDOMParser parser; + Grammar* grammar = parser.loadGrammar(xsdFile, Grammar::SchemaGrammarType, true); + if (!grammar) { + Base::Console().Error("Grammar file cannot be loaded.\n"); + return; + } + + parser.setExternalNoNamespaceSchemaLocation("Parameter.xsd"); + //parser.setExitOnFirstFatalError(true); + //parser.setValidationConstraintFatal(true); + parser.cacheGrammarFromParse(true); + parser.setValidationScheme(XercesDOMParser::Val_Auto); + parser.setDoNamespaces(true); + parser.setDoSchema(true); + + DOMTreeErrorReporter errHandler; + parser.setErrorHandler(&errHandler); + parser.parse(xmlFile); + + if (parser.getErrorCount() > 0) { + Base::Console().Error("Unexpected XML structure detected: %d errors\n", parser.getErrorCount()); + } + } + catch (XMLException& e) { + std::cerr << "An error occurred while checking document. Msg is:" + << std::endl + << StrX(e.getMessage()) << std::endl; + } } diff --git a/src/Base/Parameter.xsd b/src/Base/Parameter.xsd new file mode 100644 index 0000000000..fdd765ae57 --- /dev/null +++ b/src/Base/Parameter.xsd @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Base/PreCompiled.h b/src/Base/PreCompiled.h index 8dda7676a6..d47a553087 100644 --- a/src/Base/PreCompiled.h +++ b/src/Base/PreCompiled.h @@ -84,6 +84,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/src/Gui/DlgParameterImp.cpp b/src/Gui/DlgParameterImp.cpp index 766ad5ab98..eb09ecc2e7 100644 --- a/src/Gui/DlgParameterImp.cpp +++ b/src/Gui/DlgParameterImp.cpp @@ -266,6 +266,7 @@ void DlgParameterImp::onChangeParameterSet(int index) if (!rcParMngr) return; + rcParMngr->CheckDocument(); ui->buttonSaveToDisk->setEnabled(rcParMngr->HasSerializer()); // remove all labels