выкладываю:
H файл: XmlSettings.h
C++ (Qt)
 
#ifndef __XML_SETTINGS_H__
#define __XML_SETTINGS_H__
 
#include <QString>
#include <QSettings>
 
class QDomDocument;
class QDomElement;
class QIODevice;
 
class CXmlSettings
{
	QSettings * m_pSettings;
public:
	CXmlSettings( QString fname = "" );
	~CXmlSettings();
 
	inline QSettings& settings() const { return * m_pSettings; }
 
	// при использование CXmlSettings::value конфиг создастся автоматически, если его не было
	QVariant value( const QString & key, const QVariant & defaultValue = QVariant() );
	void setValue ( const QString & key, const QVariant & value );
 
private:
	static bool readXmlFile(QIODevice &device, QSettings::SettingsMap &map);
	static bool writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map);
	static void processWriteKey( QDomDocument& doc, QDomElement& domElement, QString key, const QVariant& value );
	static void processReadKey( QString key, QSettings::SettingsMap &map, QDomElement& domElement );
};
 
#endif // __XML_SETTINGS_H__
 
 
CPP файл: XmlSettings.cpp
C++ (Qt)
 
#include "XmlSettings.h"
#include "FileUtils.h"
#include <QDomDocument>
#include <QDebug>
 
CXmlSettings::CXmlSettings( QString fname )
{
	if ( fname.isEmpty() )
		fname = settingsPath() + appBaseName() + ".xml";
 
	static const QSettings::Format XmlFormat = QSettings::registerFormat("xml", readXmlFile, writeXmlFile);
 
	m_pSettings = new QSettings( fname, XmlFormat );
}
 
CXmlSettings::~CXmlSettings()
{
	delete m_pSettings;
}
 
QVariant CXmlSettings::value( const QString & key, const QVariant & defaultValue )
{
	if ( !settings().contains( key ) )
		settings().setValue( key, defaultValue );
	return settings().value( key );
}
void CXmlSettings::setValue ( const QString & key, const QVariant & value )
{
	settings().setValue( key, value );
}
 
bool CXmlSettings::readXmlFile(QIODevice &device, QSettings::SettingsMap &map)
{
	qDebug() << "-----readXmlSettings------";
 
	QDomDocument doc("");
	if ( !doc.setContent( &device ) ) return false;
 
	QDomElement root = doc.documentElement();
 
	processReadKey( "", map, root );
 
/*
	// Для теста использовалось при отладке
	QMap<QString, QVariant>::const_iterator i = map.constBegin();
	while (i != map.constEnd()) {
		qDebug() << i.key() << ": " << i.value() << endl;
		++i;
	}
*/
	return true;
}
 
bool CXmlSettings::writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map)
{
	qDebug() << "-----writeXmlSettings-----";
 
/*
	// Для теста использовалось при отладке
	QMap<QString, QVariant>::const_iterator i = map.constBegin();
	while (i != map.constEnd()) {
		qDebug() << i.key() << ": " << i.value() << endl;
		++i;
	}
*/
 
	QDomDocument doc("");
	QDomElement root = doc.createElement("Main");
	doc.appendChild(root);
 
	QMapIterator<QString, QVariant> i(map);
	while ( i.hasNext() )
	{
		i.next();
 
		QString  sKey = i.key();
		QVariant value = i.value();
		processWriteKey( doc, root, sKey, i.value() );
	};
 
	QDomNode xmlNode = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\""); 
	doc.insertBefore(xmlNode, doc.firstChild());
 
	QTextStream out( &device );
	doc.save(out, 4);
 
	return true;
}
 
void CXmlSettings::processWriteKey( QDomDocument& doc, QDomElement& domElement, QString key, const QVariant& value )
{
	int slashPos = key.indexOf( '/' );
 
	// переданный ключ является параметром
	if ( slashPos < 0 )
	{
		// не пишем в конфиг параметр size (является ограничением - нельзя исп. пар-тр с таким именем)
		if ( key == "size" ) return;
		domElement.setAttribute( key, value.toString() );
		return;
	};
 
	// получение имени группы соответствующей xml ноде
	QString groupName = key.left( slashPos );
	// если в качестве имени использован числовой параметр - это табличная строка, преобразуем ее в row_?
	if ( groupName.toInt() )
	{
		groupName = "row_" + groupName;
		domElement.toElement().setAttribute("table", "1");
	};
 
	// поиск/создание ноды соответствующей ключу
	QDomElement groupElement;
 
	QDomNode findedGroupNode = domElement.namedItem( groupName );
 
	if ( findedGroupNode.isNull() )
	{
		groupElement = doc.createElement( groupName );
		domElement.appendChild( groupElement );
	}
	else
		groupElement = findedGroupNode.toElement();
 
	// готовим обрезанную часть ключа
	key = key.right( key.size() - slashPos - 1 );
 
	// продолжение обработки (создание/поиск групп) - пока не найдется параметр
	processWriteKey( doc, groupElement, key, value );
}
 
void CXmlSettings::processReadKey( QString key, QSettings::SettingsMap &map, QDomElement& domElement )
{
 
	QDomNamedNodeMap namedNodeMap = domElement.attributes();
 
	// Добавление всех атрибутов элемента в качестве значений
	for (int i = 0; i < namedNodeMap.count(); ++i)
	{
		QString name = namedNodeMap.item( i ).toAttr().name();
		QString value = namedNodeMap.item( i ).toAttr().value();
		map.insert( key + name, value );
	};
 
	QDomNodeList nlChild = domElement.childNodes();
 
	// если узел является таблицей - то все дети строки
	bool isTable = domElement.attribute("table", "0").toInt();
	// создаем доп. элемент size равный числу детей (необходим для QSettings - beginArray)
	if ( isTable )
		map.insert( key + "size", nlChild.count() );
 
	// проход по всем детям
	for (int i = 0; i < nlChild.count(); ++i)
	{
		QString childName = nlChild.item(i).toElement().tagName();
		if ( childName.contains("row_") )
			childName = childName.right( childName.size() - 4 );
 
		QString subKey = key + childName + "/";
		QDomElement subElement = nlChild.item(i).toElement();
		processReadKey( subKey, map, subElement );
	};
}
 
 
Функции settingsPath()  и  appBaseName() - у меня реализованы в моем FileUtils - возвращают дефолтный путь к папке с настройками и базовое имя программы (без расширения)
Также продублировал во вложении.
Пользоваться можно через обращение к settings() - всеми возможностями самого QSettings - группы, массивы и т.д. Ограничение - нельзя использовать атрибут с именем "table" - он используется для определения таблицы (массива) при чтение настроек. Если пользоваться через прямые методы value, CXmlSettings - то в случае если значения в конфиге не было - оно создасться и заполниться значением по умолчанию (сделал чтобы программа сама создавала свой конфиг если был утерян...).