26#include <QtCore/QFile>
27#include <QtCore/QLocale>
28#include <QtCore/QString>
29#include <QtCore/QTextStream>
30#include <QtXmlPatterns/QXmlSchema>
31#include <QtXmlPatterns/QXmlSchemaValidator>
32#include <QAbstractMessageHandler>
34#define XMLNS_BASE "http://www.hydrogen-music.org/"
35#define XMLNS_XSI "http://www.w3.org/2001/XMLSchema-instance"
44 : QAbstractMessageHandler(nullptr)
50 const QUrl &identifier,
const QSourceLocation &sourceLocation)
65 XMLNode node = this->ownerDocument().createElement( name );
73 ERRORLOG( QString(
"try to read %1 XML node from an empty parent %2." )
74 .arg( node ).arg( nodeName() ) );
77 QDomElement el = firstChildElement( node );
79 if ( !inexistent_ok && ! bSilent ) {
80 WARNINGLOG( QString(
"XML node %1->%2 should exists." )
81 .arg( nodeName() ).arg( node ) );
85 if( el.text().isEmpty() ) {
86 if( !empty_ok && ! bSilent ) {
87 WARNINGLOG( QString(
"XML node %1->%2 should not be empty." )
88 .arg( nodeName() ).arg( node ) );
95QString
XMLNode::read_string(
const QString& node,
const QString& sDefaultValue,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
97 QString sText =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
98 if ( sText.isNull() && ! sDefaultValue.isEmpty() ) {
100 WARNINGLOG( QString(
"Using default value %1 for %2" )
101 .arg( sDefaultValue ).arg( node ) );
103 return sDefaultValue;
107QColor
XMLNode::read_color(
const QString& node,
const QColor& default_value,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
109 QString text =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
111 if ( ! text.isEmpty() ) {
112 QStringList textList = text.split( QLatin1Char(
',' ) );
113 if ( textList.size() != 3 ) {
115 WARNINGLOG( QString(
"Invalid color format [%1] for node [%2]" )
116 .arg( default_value.name() ).arg( node ) );
118 return default_value;
121 QColor color( textList[ 0 ].toInt(), textList[ 1 ].toInt(), textList[ 2 ].toInt() );
122 if ( ! color.isValid() ) {
124 WARNINGLOG( QString(
"Invalid color values [%1] for node [%2]" )
125 .arg( default_value.name() ).arg( node ) );
127 return default_value;
133 WARNINGLOG( QString(
"Using default value [%1] for node [%2]" )
134 .arg( default_value.name() ).arg( node ) );
136 return default_value;
139float XMLNode::read_float(
const QString& node,
float default_value,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
141 QString ret =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
144 WARNINGLOG( QString(
"Using default value %1 for %2" )
145 .arg( default_value ).arg( node ) );
147 return default_value;
149 QLocale c_locale = QLocale::c();
150 return c_locale.toFloat( ret );
153float XMLNode::read_float(
const QString& node,
float default_value,
bool *pFound,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
155 QString ret =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
158 WARNINGLOG( QString(
"Using default value %1 for %2" )
159 .arg( default_value ).arg( node ) );
162 return default_value;
165 QLocale c_locale = QLocale::c();
166 return c_locale.toFloat( ret );
170int XMLNode::read_int(
const QString& node,
int default_value,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
172 QString ret =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
175 WARNINGLOG( QString(
"Using default value %1 for %2" )
176 .arg( default_value ).arg( node ) );
178 return default_value;
180 QLocale c_locale = QLocale::c();
181 return c_locale.toInt( ret );
184bool XMLNode::read_bool(
const QString& node,
bool default_value,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
186 QString ret =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
189 WARNINGLOG( QString(
"Using default value %1 for %2" )
190 .arg( default_value ).arg( node ) );
192 return default_value;
201bool XMLNode::read_bool(
const QString& node,
bool default_value,
bool* pFound,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
203 QString ret =
read_child_node( node, inexistent_ok, empty_ok, bSilent );
207 WARNINGLOG( QString(
"Using default value %1 for %2" )
208 .arg( default_value ).arg( node ) );
210 return default_value;
223 QString text = toElement().text();
224 if ( !empty_ok && text.isEmpty() && ! bSilent ) {
225 WARNINGLOG( QString(
"XML node %1 should not be empty." ).arg( nodeName() ) );
230QString
XMLNode::read_attribute(
const QString& attribute,
const QString& default_value,
bool inexistent_ok,
bool empty_ok,
bool bSilent )
232 QDomElement el = toElement();
233 if ( !inexistent_ok && !el.hasAttribute( attribute ) ) {
235 WARNINGLOG( QString(
"XML node %1 attribute %2 should exists." )
236 .arg( nodeName() ).arg( attribute ) );
238 return default_value;
240 QString attr = el.attribute( attribute );
241 if ( attr.isEmpty() ) {
242 if( !empty_ok && ! bSilent ) {
243 WARNINGLOG( QString(
"XML node %1 attribute %2 should not be empty." )
244 .arg( nodeName() ).arg( attribute ) );
248 WARNINGLOG( QString(
"Using default value %1 for attribute %2" )
249 .arg( default_value ).arg( attribute ) );
251 return default_value;
258 toElement().setAttribute( attribute, value );
263 QDomDocument doc = this->ownerDocument();
264 QDomElement el = doc.createElement( node );
265 QDomText txt = doc.createTextNode( text );
266 el.appendChild( txt );
267 this->appendChild( el );
277 .arg( color.green() )
278 .arg( color.blue() ) );
296bool XMLDoc::read(
const QString& sFilePath,
const QString& sSchemaPath,
bool bSilent )
299 QFile file( sFilePath );
300 if ( !file.open( QIODevice::ReadOnly ) ) {
301 ERRORLOG( QString(
"Unable to open [%1] for reading" )
308 schema.setMessageHandler( &handler );
310 bool bSchemaUsable =
false;
312 if ( ! sSchemaPath.isEmpty() ) {
313 QFile file( sSchemaPath );
314 if ( !file.open( QIODevice::ReadOnly ) ) {
315 ERRORLOG( QString(
"Unable to open XML schema [%1] for reading." )
316 .arg( sSchemaPath ) );
318 schema.load( &file, QUrl::fromLocalFile( file.fileName() ) );
320 if ( schema.isValid() ) {
321 bSchemaUsable =
true;
323 ERRORLOG( QString(
"XML schema [%1] is not valid. File [%2] will not be validated" )
324 .arg( sSchemaPath ).arg( sFilePath ) );
329 if ( bSchemaUsable ) {
330 QXmlSchemaValidator validator( schema );
331 if ( !validator.validate( &file, QUrl::fromLocalFile( file.fileName() ) ) ) {
333 WARNINGLOG( QString(
"XML document [%1] is not valid with respect to schema [%2], loading may fail" )
334 .arg( sFilePath ).arg( sSchemaPath ) );
339 else if ( ! bSilent ) {
340 INFOLOG( QString(
"XML document [%1] is valid with respect to schema [%2]" )
341 .arg( sFilePath ).arg( sSchemaPath ) );
350 ERRORLOG( QString(
"Unable to read conversion result document [%1]" )
358 if ( ! setContent( &file ) ) {
359 ERRORLOG( QString(
"Unable to read XML document [%1]" )
372 QFile file( filepath );
373 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) ) {
374 ERRORLOG( QString(
"Unable to open %1 for writing" ).arg( filepath ) );
377 QTextStream out( &file );
378 out.setCodec(
"UTF-8" );
379 out << toString().toUtf8();
383 if ( !toString().isEmpty() && file.size() == 0 ) {
393 QDomProcessingInstruction header = createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\"" );
394 appendChild( header );
395 XMLNode root = createElement( node_name );
396 if ( !xmlns.isEmpty() ) {
397 QDomElement el = root.toElement();
399 el.setAttribute(
"xmlns:xsi",
XMLNS_XSI );
static bool checkTinyXMLCompatMode(QFile *pFile, bool bSilent=false)
static QByteArray convertFromTinyXML(QFile *pFile, bool bSilent=false)
virtual void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation)
XMLNode set_root(const QString &node_name, const QString &xmlns=nullptr)
create the xml header and root node
bool read(const QString &filepath, const QString &schemapath=nullptr, bool bSilent=false)
read the content of an xml file
bool write(const QString &filepath)
write itself into a file
XMLDoc()
basic constructor
XMLNode is a subclass of QDomNode with read and write values methods.
int read_int(const QString &node, int default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads an integer stored into a child node
void write_attribute(const QString &attribute, const QString &value)
write a string as an attribute of the node
QString read_child_node(const QString &node, bool inexistent_ok, bool empty_ok, bool bSilent=false)
reads a string stored into a child node
bool read_bool(const QString &node, bool default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a boolean stored into a child node
QString read_attribute(const QString &attribute, const QString &default_value, bool inexistent_ok, bool empty_ok, bool bSilent=false)
reads an attribute from the node
QColor read_color(const QString &node, const QColor &defaultValue=QColor(97, 167, 251), bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
void write_child_node(const QString &node, const QString &text)
write a string into a child node
QString read_string(const QString &node, const QString &default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a string stored into a child node
float read_float(const QString &node, float default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a float stored into a child node
void write_color(const QString &node, const QColor &color)
void write_float(const QString &node, const float value)
write a float into a child node
XMLNode createNode(const QString &name)
create a new XMLNode that has to be appended into de XMLDoc
XMLNode()
basic constructor
void write_string(const QString &node, const QString &value)
write a string into a child node
void write_bool(const QString &node, const bool value)
write a boolean into a child node
QString read_text(bool empty_ok, bool bSilent=false)
reads the text (content) from the node
void write_int(const QString &node, const int value)
write an integer into a child node