conflict LibXML2 validation with qt application
-
Hello,
i have a problem validating a xml file against a xsd schema within my qt gui application.
First i used Qt XML Patterns but i need to upgrade the program to Qt 6.6.1. As the required functions where unfortunatly deprecated i now go with LibXML.
Validating my XML results in this error message:
Obviously this is a false negative. Using datatype "decimal" instead of "float" is a workaround to successfully validate the xml file. But this is not an option for me as the xsd is part of an bigger project where the xsd is autogenerated and also used for code generation. Changing float to decimal would come with hugh extra work.
XML file:
<tns:Root xmlns:tns="XXX" xmlns:xsi="XXX"> <Class id="1"> <Value>0.04</Value> </Class> </tns:Root>
XSD file:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="XXX" xmlns:p="XXX" xmlns:p1="XXX" targetNamespace="XXX"> <element name="Root"> <complexType> <sequence> <element name="Class" type="tns:ClassType" maxOccurs="unbounded" minOccurs="0"> <annotation> <documentation/> </annotation> </element> </sequence> </complexType> </element> <complexType name="ClassType"> <sequence> <element name="Value" minOccurs="0" maxOccurs="1"> <annotation> <documentation>blabla</documentation> <appinfo> <p:default>0.040</p:default> </appinfo> </annotation> <simpleType> <restriction base="float"> <minExclusive value="0"/> <maxExclusive value="1"/> </restriction> </simpleType> </element> </sequence> <attribute name="id" type="int" use="required"/> </complexType> </schema>
Now, why do i post this in the Qt forum? Well, when i created a simplified project for the libxml community the issue was gone. It turned out that the issue does only occure AFTER either QCoreApplication or QApplication where instantiated.
This code snippet
XMLValidator validator("SchemaSimple.xsd"); cout << "Test 1" << endl << validator.validateXML("SimpleConfig.xml") << endl; cout << "Test 2" << endl << validator.validateXML("SimpleConfig.xml") << endl; QCoreApplication a(argc, argv); cout << "Test 3" << endl << validator.validateXML("SimpleConfig.xml") << endl;
results in
Test 1 1 Test2 1 Test 3 0
So after QCoreApplication the exact same xml that was valid before becomes invalid.
A small example cmake project is updloaded here: https://gitlab.gnome.org
-
@hskoglund system language is english. i just changed the Creator language to german. I tried to set it to system language and the issue still occurs.
Also tried to change the . to , in the xml but this breaks the xml format. -
@QT-static-prgm
Then this is a perplexing question/behaviour, I had hoped @hskoglund's suggestion might have been relevant.So that I understand: LibXML is some external library, nothing to do with Qt. And
XMLvalidator
is some class in that library. Right?And you are showing that behaves differently before vs after
QCoreApplication a(argc, argv);
. So something that does seems to affect the behaviour of LibXML even though that has nothing to do with Qt. And you want to know what that could be, right...?P.S.
i just changed the Creator language to german
I don't know how you do that, but changing language in Creator will not necessarily have any effect on programs you execute from it. To be sure you should change the language/locale in your program code. But if you are saying/implying you have nothing to with a language like German which uses
,
in numbers and everything on your system is already English and using.
then this should not be relevant.Just in case, instead of trying to change language please temporarily change your input XML to have
<Value>0,04</Value>
and just verify that does not help. OIC:Also tried to change the . to , in the xml but this breaks the xml format.
so you have already tried that.
-
@JonB XMLValidator is a self written C++ class. It's in the uploaded zip. libxml2 is an external library that i use within that class.
And yes the behaviour changes when qt application is started.
Suggestion of libxml community is that Qt source uses libxml too that somehow conflicts?
Can someone maybe download the example project and confirm the same behavior? Just to make sure it is not just with my setup.
-
@QT-static-prgm said in conflict LibXML2 validation with qt application:
Suggestion of libxml community is that Qt source uses libxml too that somehow conflicts?
It is used here at least: https://doc.qt.io/qt-6/qtwebengine-3rdparty-libxml.html. Do you use QtWebEngine in your project?
I note that seems to be libXML and you are using libXML2. Is it easy for you to fetch libXML (or use the one apparently supplied with Qt, or at least with WebEngine) instead and just see whether that solves? Having a program using both versions might not be a good idea....
-
@JonB do you know the version QtWebEngine uses? I tried libxml2.9.13 and 2.12.13.
But anyhow i don't use webengine.
This is the whole program that i was able to break the issue down to:
main.cpp
#include "xmlvalidator.h" #include <QCoreApplication> #include <iostream> using namespace std; int main(int argc, char* argv[]) { cout << "Hello World!" << endl; XMLValidator validator("/home/developer/workspace/XMLValidatorExample/SchemaSimple.xsd"); cout << "Test 1" << endl << validator.validateXML("/home/developer/workspace/XMLValidatorExample/SimpleConfig.xml") << endl; cout << "Test 2" << endl << validator.validateXML("/home/developer/workspace/XMLValidatorExample/SimpleConfig.xml") << endl; QCoreApplication a(argc, argv); cout << "Test 3" << endl << validator.validateXML("/home/developer/workspace/XMLValidatorExample/SimpleConfig.xml") << endl; return a.exec(); }
CMakeLists.txt:
cmake_minimum_required(VERSION 3.14) project(XMLValidatorExample LANGUAGES CXX) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(LibXml2 REQUIRED) add_executable(XMLValidatorExample main.cpp xmlvalidator.cpp xmlvalidator.h ) target_link_libraries(XMLValidatorExample Qt${QT_VERSION_MAJOR}::Core) target_link_libraries(XMLValidatorExample ${LIBXML2_LIBRARY}) include(GNUInstallDirs) include_directories(${LIBXML2_INCLUDE_DIR}) install(TARGETS XMLValidatorExample LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
xmlvalidator.cpp
#include "xmlvalidator.h" #include <libxml/xmlreader.h> #include <libxml/xmlschemas.h> class XMLValidatorPrivate { public: xmlSchemaPtr m_schema = nullptr; std::string m_xmlFile = ""; XMLValidator::Error* m_error; }; XMLValidator::XMLValidator(std::string xsdFile) { m_private = std::make_unique<XMLValidatorPrivate>(); setXsdFile(xsdFile); } XMLValidator::~XMLValidator() { if (m_private->m_schema != nullptr) { xmlSchemaFree(m_private->m_schema); } } void XMLValidator::setXsdFile(std::string fileName) { // Clean up first if (m_private->m_schema != nullptr) { xmlSchemaFree(m_private->m_schema); m_private->m_schema = nullptr; } xmlSchemaParserCtxtPtr temp_SchemaParser = xmlSchemaNewParserCtxt(fileName.c_str()); if (temp_SchemaParser != nullptr) { m_private->m_schema = xmlSchemaParse(temp_SchemaParser); xmlSchemaFreeParserCtxt(temp_SchemaParser); } else { m_private->m_error = new XMLValidator::Error{ fileName, 0, 0, "xsd file not found", }; } } bool XMLValidator::validateXML(std::string fileName) { if (m_private->m_schema == nullptr) { m_private->m_error = new XMLValidator::Error{ "", 0, 0, "first select xsd file", }; return false; } m_private->m_xmlFile = fileName; xmlSchemaValidCtxtPtr temp_scValCtxtPtr = xmlSchemaNewValidCtxt(m_private->m_schema); xmlSchemaSetValidErrors(temp_scValCtxtPtr, XMLValidator::errorHandler, XMLValidator::warningHandler, this); if (xmlSchemaValidateFile(temp_scValCtxtPtr, fileName.c_str(), 0) == 0) { xmlSchemaFreeValidCtxt(temp_scValCtxtPtr); return true; } xmlSchemaFreeValidCtxt(temp_scValCtxtPtr); return false; } XMLValidator::Error* XMLValidator::getErrorDetails() { return m_private->m_error; } void XMLValidator::errorHandler(void* ctx, const char* msg, ...) { static_cast<XMLValidator*>(ctx)->saveLastError(); } void XMLValidator::warningHandler(void* ctx, const char* msg, ...) { static_cast<XMLValidator*>(ctx)->saveLastError(); } void XMLValidator::saveLastError() { const xmlError* temp_err = xmlGetLastError(); if (temp_err == nullptr) { return; } m_private->m_error = new XMLValidator::Error{ m_private->m_xmlFile, temp_err->code, temp_err->line, temp_err->message, }; }
xmlvalidator.h
/** * This class provides functionality to validate a XML file against a XSD schema. * libxml2 library is required to use this class. */ #ifndef XMLVALIDATOR_H #define XMLVALIDATOR_H #include <memory> #include <string> class XMLValidatorPrivate; class XMLValidator { public: struct Error { std::string file; int errorCode = 0; int line = 0; std::string message; }; public: XMLValidator(std::string xsdFile); ~XMLValidator(); private: std::unique_ptr<XMLValidatorPrivate> m_private; public: void setXsdFile(std::string fileName); bool validateXML(std::string fileName); Error* getErrorDetails(); static void errorHandler(void* ctx, const char* msg, ...); static void warningHandler(void* ctx, const char* msg, ...); protected: void saveLastError(); }; #endif // XMLVALIDATOR_H
-
@QT-static-prgm
I suggested you try libXML instead of libXML2, at least for a test. I don't know anything about where you get it from but I can at least see https://download.gnome.org/sources/libxml/. Just a thought. -
@QT-static-prgm
Alternatively/additionally, are you compiling libXML2 yourself with sources? Compile for debug, find where thatError '1835'
is coming from in code, put a breakpoint on it, look at the stack trace and see whether you can figure what has happened to your input string/the processing which causes it? -
@JonB no i don't build libxml2 from source.
i don't think using an older libxml version will solve the issue. As i build Qt from source the xml version used should be the same version as i use now for my program.
i would test it but as the computer is offline i cannot simply downgrade
-
@QT-static-prgm said in conflict LibXML2 validation with qt application:
i don't think using an older libxml version will solve the issue. As i build Qt from source the xml version used should be the same version as i use now for my program.
It was supposed to be a test to see if it gave us a clue as to what the issue might be. Anyway I leave it with you, I don't use Qt6.