Skip to content

Instantly share code, notes, and snippets.

@jsm222
Created February 5, 2024 22:55
Show Gist options
  • Save jsm222/eb1414b651e81a8ea20b20df8bb46556 to your computer and use it in GitHub Desktop.
Save jsm222/eb1414b651e81a8ea20b20df8bb46556 to your computer and use it in GitHub Desktop.
mscore use libxml2 directly in qt6
diff --git a/src/importexport/musicxml/CMakeLists.txt b/src/importexport/musicxml/CMakeLists.txt
index f9882fb776..1e06776c65 100644
--- a/src/importexport/musicxml/CMakeLists.txt
+++ b/src/importexport/musicxml/CMakeLists.txt
@@ -19,9 +19,11 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
set(MODULE iex_musicxml)
-
set(MODULE_QRC musicxml.qrc)
+find_package(LibXml2 REQUIRED)
+include_directories("${LIBXML2_INCLUDE_DIRS}")
+
include(${CMAKE_CURRENT_LIST_DIR}/internal/musicxml/musicxml.cmake)
set(MODULE_SRC
@@ -41,6 +43,7 @@ set(MODULE_SRC
set(MODULE_LINK
engraving
+ "${LIBXML2_LIBRARIES}"
)
include(SetupModule)
diff --git a/src/importexport/musicxml/internal/musicxml/importxml.cpp b/src/importexport/musicxml/internal/musicxml/importxml.cpp
index dc41844a54..4e51c36832 100644
--- a/src/importexport/musicxml/internal/musicxml/importxml.cpp
+++ b/src/importexport/musicxml/internal/musicxml/importxml.cpp
@@ -31,6 +31,8 @@
//#include <QXmlSchemaValidator>
#include "importmxml.h"
+#include <libxml/xmlschemastypes.h>
+#include <libxml/catalog.h>
#include "musicxmlsupport.h"
#include "translation.h"
@@ -66,44 +68,6 @@ static_assert(int(DurationType::V_BREVE) == int(DurationType::V_LONG) + 1
&& int(DurationType::V_512TH) == int(DurationType::V_256TH) + 1
&& int(DurationType::V_1024TH) == int(DurationType::V_512TH) + 1);
-//---------------------------------------------------------
-// initMusicXmlSchema
-// return false on error
-//---------------------------------------------------------
-
-//static bool initMusicXmlSchema(QXmlSchema& schema)
-//{
-// // read the MusicXML schema from the application resources
-// QFile schemaFile(":/schema/musicxml.xsd");
-// if (!schemaFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
-// LOGE("initMusicXmlSchema() could not open resource musicxml.xsd");
-// return false;
-// }
-
-// // copy the schema into a QByteArray and fixup xs:imports,
-// // using a path to the application resources instead of to www.musicxml.org
-// // to prevent downloading from the net
-// QByteArray schemaBa;
-// QTextStream schemaStream(&schemaFile);
-// while (!schemaStream.atEnd()) {
-// QString line = schemaStream.readLine();
-// if (line.contains("xs:import")) {
-// line.replace("http://www.musicxml.org/xsd", "qrc:///schema");
-// }
-// schemaBa += line.toUtf8();
-// schemaBa += "\n";
-// }
-
-// // load and validate the schema
-// schema.load(schemaBa);
-// if (!schema.isValid()) {
-// LOGE("initMusicXmlSchema() internal error: MusicXML schema is invalid");
-// return false;
-// }
-
-// return true;
-//}
-
//---------------------------------------------------------
// musicXMLValidationErrorDialog
//---------------------------------------------------------
@@ -114,18 +78,52 @@ static_assert(int(DurationType::V_BREVE) == int(DurationType::V_LONG) + 1
Return QMessageBox::Yes (try anyway) or QMessageBox::No (don't)
*/
-static int musicXMLValidationErrorDialog(QString text, QString detailedText)
+static int musicXMLValidationErrorDialog(void *ctxt,const char *fmt,...)
{
+ std::string format(fmt);
+ std::string fstr("%s");
+ int count=0;
+ int nPos = format.find(fstr, 0); // fist occurrence
+
+ while (nPos != std::string::npos)
+ {
+ count++;
+ nPos = format.find(fstr, nPos + 1);
+ }
+
QMessageBox errorDialog;
+ std::va_list argp;
+ va_start(argp, fmt);
+ std::string detailedError;
+ for(int i=0;i<count;i++) {
+ char * t = (char*)malloc(sizeof(char)*4096);
+ t = va_arg(argp, char*);
+ std::string str(t);
+ detailedError+=str;
+ free(t);
+ }
+
+ va_end(argp);
errorDialog.setIcon(QMessageBox::Question);
- errorDialog.setText(text);
+ errorDialog.setText("Xml parser error");
errorDialog.setInformativeText(qtrc("iex_musicxml", "Do you want to try to load this file anyway?"));
- errorDialog.setDetailedText(detailedText);
+ errorDialog.setDetailedText(QString::fromStdString(detailedError));
errorDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
errorDialog.setDefaultButton(QMessageBox::No);
return errorDialog.exec();
}
+//---------------------------------------------------------
+// initMusicXmlSchema
+// return false on error
+//---------------------------------------------------------
+static bool initMusicXmlSchema()
+{
+ xmlSchemaParserCtxtPtr ctxt;
+ ctxt = xmlSchemaNewParserCtxt(QFile(":/schema/musicxml.xsd").fileName().toStdString().c_str());
+ xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc) musicXMLValidationErrorDialog, (xmlSchemaValidityWarningFunc) musicXMLValidationErrorDialog, ctxt);
+ return (ctxt);
+}
//---------------------------------------------------------
// extractRootfile
//---------------------------------------------------------
@@ -191,35 +189,62 @@ static bool extractRootfile(QFile* qf, QByteArray& data)
static Err doValidate(const QString& name, QIODevice* dev)
{
- NOT_IMPLEMENTED;
-
- //QElapsedTimer t;
- //t.start();
-
- // initialize the schema
-// ValidatorMessageHandler messageHandler;
-// QXmlSchema schema;
-// schema.setMessageHandler(&messageHandler);
-// if (!initMusicXmlSchema(schema)) {
-// return Err::FileBadFormat; // appropriate error message has been printed by initMusicXmlSchema
-// }
-// // validate the data
-// QXmlSchemaValidator validator(schema);
-// bool valid = validator.validate(dev, QUrl::fromLocalFile(name));
-// //LOGD("Validation time elapsed: %d ms", t.elapsed());
-
-// if (!valid) {
-// LOGD("importMusicXml() file '%s' is not a valid MusicXML file", qPrintable(name));
-// QString strErr = qtrc("iex_musicxml", "File “%1” is not a valid MusicXML file.").arg(name);
-// if (MScore::noGui) {
-// return Err::NoError; // might as well try anyhow in converter mode
-// }
-// if (musicXMLValidationErrorDialog(strErr, messageHandler.getErrors()) != QMessageBox::Yes) {
-// return Err::UserAbort;
-// }
-// }
-
- return Err::NoError;
+ xmlLoadCatalog("/home/jesper/Hentet/schema/catalog.xml");
+ Err error = Err::UnknownError;
+ xmlDocPtr doc;
+ xmlSchemaPtr schema = NULL;
+ xmlSchemaParserCtxtPtr ctxt;
+ ctxt = xmlSchemaNewParserCtxt("/home/jesper/Hentet/schema/musicxml.xsd");
+ xmlLineNumbersDefault(1);
+
+
+ xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc) musicXMLValidationErrorDialog, (xmlSchemaValidityWarningFunc) musicXMLValidationErrorDialog,ctxt);
+ schema = xmlSchemaParse(ctxt);
+ xmlSchemaFreeParserCtxt(ctxt);
+
+
+ doc = xmlReadFile(name.toStdString().c_str(), NULL, 0);
+
+ if (doc == NULL)
+ {
+ std::cout << "Could not parse " << name.toStdString() << "\n";
+ }
+ else
+ {
+ xmlSchemaValidCtxtPtr ctxt;
+ int ret;
+
+ ctxt = xmlSchemaNewValidCtxt(schema);
+ xmlSchemaSetValidErrors(ctxt, (xmlSchemaValidityErrorFunc) musicXMLValidationErrorDialog, (xmlSchemaValidityWarningFunc) musicXMLValidationErrorDialog,ctxt);
+ ret = xmlSchemaValidateDoc(ctxt, doc);
+ if (ret == 0)
+ {
+ error = Err::NoError;
+ }
+ else if (ret > 0)
+ {
+ std::cout <<"fails to validate"<< name.toStdString() << "\n";
+ error = Err::FileCorrupted;
+ }
+ else
+ {
+ std::cout <<"fails to validate internal error" << "\n";
+ error = Err::UnknownError;
+
+ }
+ xmlSchemaFreeValidCtxt(ctxt);
+ xmlFreeDoc(doc);
+ }
+
+
+ if(schema != NULL)
+ xmlSchemaFree(schema);
+
+ xmlSchemaCleanupTypes();
+ xmlCleanupParser();
+ xmlMemoryDump();
+
+ return error;
}
//---------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment