diff --git a/util/glgen/glgen.pro b/util/glgen/glgen.pro
index 9208ba9e8e63e4f5cba285659c01761c6a09d204..11018e942d4162ee5cf4ec85181bd6266d4c0156 100644
--- a/util/glgen/glgen.pro
+++ b/util/glgen/glgen.pro
@@ -9,11 +9,14 @@ TEMPLATE  = app
 TARGET    = glgen
 
 SOURCES      += main.cpp \
-                specparser.cpp \
+                xmlspecparser.cpp \
+                legacyspecparser.cpp \
                 codegenerator.cpp
 
 HEADERS      += \
                 specparser.h \
+                xmlspecparser.h \
+                legacyspecparser.h \
                 codegenerator.h
 
 OTHER_FILES  += \
diff --git a/util/glgen/specparser.cpp b/util/glgen/legacyspecparser.cpp
similarity index 88%
rename from util/glgen/specparser.cpp
rename to util/glgen/legacyspecparser.cpp
index 91a906bca9c09fcb558feeea20f32a82fd6d8512..84dcd0b2001369f2380f06d3cee4f4913bf9ccf2 100644
--- a/util/glgen/specparser.cpp
+++ b/util/glgen/legacyspecparser.cpp
@@ -39,7 +39,7 @@
 **
 ****************************************************************************/
 
-#include "specparser.h"
+#include "legacyspecparser.h"
 
 #include <QDebug>
 #include <QFile>
@@ -48,39 +48,36 @@
 #include <QTextStream>
 
 #ifdef SPECPARSER_DEBUG
-#define qSpecParserDebug qDebug
+#define qLegacySpecParserDebug qDebug
 #else
-#define qSpecParserDebug QT_NO_QDEBUG_MACRO
+#define qLegacySpecParserDebug QT_NO_QDEBUG_MACRO
 #endif
 
-SpecParser::SpecParser()
-{
-}
-
-void SpecParser::parse()
+bool LegacySpecParser::parse()
 {
     // Get the mapping form generic types to specific types suitable for use in C-headers
     if (!parseTypeMap())
-        return;
+        return false;
 
     // Open up a stream on the actual OpenGL function spec file
-    QFile file(m_specFileName);
+    QFile file(specFileName());
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-        qWarning() << "Failed to open spec file:" << m_specFileName << "Aborting";
-        return;
+        qWarning() << "Failed to open spec file:" << specFileName() << "Aborting";
+        return false;
     }
 
     QTextStream stream(&file);
 
     // Extract the info that we need
     parseFunctions(stream);
+    return true;
 }
 
-bool SpecParser::parseTypeMap()
+bool LegacySpecParser::parseTypeMap()
 {
-    QFile file(m_typeMapFileName);
+    QFile file(typeMapFileName());
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-        qWarning() << "Failed to open spec file:" << m_specFileName << "Aborting";
+        qWarning() << "Failed to open type file:" << typeMapFileName() << "Aborting";
         return false;
     }
 
@@ -103,18 +100,18 @@ bool SpecParser::parseTypeMap()
                 value = QStringLiteral("void");
 
             m_typeMap.insert(key, value);
-            qSpecParserDebug() << "Found type mapping from" << key << "=>" << value;
+            qLegacySpecParserDebug() << "Found type mapping from" << key << "=>" << value;
         }
     }
 
     return true;
 }
 
-void SpecParser::parseEnums()
+void LegacySpecParser::parseEnums()
 {
 }
 
-void SpecParser::parseFunctions(QTextStream &stream)
+void LegacySpecParser::parseFunctions(QTextStream &stream)
 {
     static QRegExp functionRegExp("^(\\w+)\\(.*\\)");
     static QRegExp returnRegExp("^\\treturn\\s+(\\S+)");
@@ -168,8 +165,12 @@ void SpecParser::parseFunctions(QTextStream &stream)
                     versions.insert(currentVersionProfile.version);
                 }
 
-                if (acceptCurrentFunctionInExtension)
-                    m_extensionFunctions.insert(currentCategory, currentFunction);
+                if (acceptCurrentFunctionInExtension) {
+                    FunctionProfile fp;
+                    fp.profile = currentVersionProfile.profile;
+                    fp.function = currentFunction;
+                    m_extensionFunctions.insert(currentCategory, fp);
+                }
             }
 
             // Start a new function
@@ -187,7 +188,7 @@ void SpecParser::parseFunctions(QTextStream &stream)
             // Extract the function name
             QString functionName = functionRegExp.cap(1);
             currentFunction.name = functionName;
-            qSpecParserDebug() << "Found function:" << functionName;
+            qLegacySpecParserDebug() << "Found function:" << functionName;
 
         } else if (argumentRegExp.indexIn(line) != -1) {
             // Extract info about this function argument
@@ -219,7 +220,7 @@ void SpecParser::parseFunctions(QTextStream &stream)
                 acceptCurrentFunctionInCore = false;
             }
 
-            qSpecParserDebug() << "    argument:" << arg.type << arg.name;
+            qLegacySpecParserDebug() << "    argument:" << arg.type << arg.name;
             currentFunction.arguments.append(arg);
 
         } else if (returnRegExp.indexIn(line) != -1) {
@@ -230,13 +231,13 @@ void SpecParser::parseFunctions(QTextStream &stream)
                 acceptCurrentFunctionInCore = false;
             }
             QString returnType = m_typeMap.value(returnTypeKey);
-            qSpecParserDebug() << "    return type:" << returnType;
+            qLegacySpecParserDebug() << "    return type:" << returnType;
             currentFunction.returnType = returnType;
 
         } else if (versionRegExp.indexIn(line) != -1 && !haveVersionInfo) { // Only use version line if no other source
             // Extract the OpenGL version in which this function was introduced
             QString version = versionRegExp.cap(1);
-            qSpecParserDebug() << "    version:" << version;
+            qLegacySpecParserDebug() << "    version:" << version;
             QStringList parts = version.split(QLatin1Char('.'));
             if (parts.size() != 2) {
                 qWarning() << "Found invalid version number";
@@ -259,7 +260,7 @@ void SpecParser::parseFunctions(QTextStream &stream)
         } else if (categoryRegExp.indexIn(line) != -1) {
             // Extract the category for this function
             QString category = categoryRegExp.cap(1).simplified();
-            qSpecParserDebug() << "    category:" << category;
+            qLegacySpecParserDebug() << "    category:" << category;
 
             if (categoryVersionRegExp.indexIn(category) != -1) {
                 // Use the version info in the category in preference to the version
@@ -275,7 +276,7 @@ void SpecParser::parseFunctions(QTextStream &stream)
 
             } else {
                 // Make a note of the extension name and tag this function as being part of an extension
-                qSpecParserDebug() << "Found category =" << category;
+                qLegacySpecParserDebug() << "Found category =" << category;
                 currentCategory = category;
                 acceptCurrentFunctionInExtension = true;
 
@@ -290,7 +291,7 @@ void SpecParser::parseFunctions(QTextStream &stream)
             }
 
         } else if (extToCoreVersionRegExp.indexIn(line) != -1) {
-            qSpecParserDebug() << line;
+            qLegacySpecParserDebug() << line;
             int majorVersion = extToCoreVersionRegExp.cap(1).toInt();
             int minorVersion = extToCoreVersionRegExp.cap(2).toInt();
             extToCoreCurrentVersion.major = majorVersion;
@@ -306,7 +307,7 @@ void SpecParser::parseFunctions(QTextStream &stream)
     qSort(m_versions);
 }
 
-bool SpecParser::inDeprecationException(const QString &functionName) const
+bool LegacySpecParser::inDeprecationException(const QString &functionName) const
 {
     return (functionName == QStringLiteral("TexImage3D"));
 }
diff --git a/util/glgen/legacyspecparser.h b/util/glgen/legacyspecparser.h
new file mode 100644
index 0000000000000000000000000000000000000000..63d9a9f1704e27a58a67bb4ff6e5c8dc5496ed5a
--- /dev/null
+++ b/util/glgen/legacyspecparser.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the utilities of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LEGACYSPECPARSER_H
+#define LEGACYSPECPARSER_H
+
+#include "specparser.h"
+
+#include <QStringList>
+#include <QVariant>
+
+class QTextStream;
+
+class LegacySpecParser : public SpecParser
+{
+public:
+    virtual QList<Version> versions() const {return m_versions;}
+
+    virtual bool parse();
+
+protected:
+    const QMultiHash<VersionProfile, Function> &versionFunctions() const { return m_functions; }
+    const QMultiMap<QString, FunctionProfile> &extensionFunctions() const { return m_extensionFunctions; }
+
+private:
+    QMap<QString, QString> m_typeMap;
+    QMultiHash<VersionProfile, Function> m_functions;
+
+    QList<Version> m_versions;
+
+    // Extension support
+    QMultiMap<QString, FunctionProfile> m_extensionFunctions;
+
+    bool parseTypeMap();
+    void parseEnums();
+    void parseFunctions(QTextStream &stream);
+    bool inDeprecationException(const QString &functionName) const;
+};
+
+#endif // LEGACYSPECPARSER_H
diff --git a/util/glgen/main.cpp b/util/glgen/main.cpp
index 15c311caf36a30237f9498c6810ca17c911696b2..41d97a6c850818b1de1adb2d4fc45f7d48c768e4 100644
--- a/util/glgen/main.cpp
+++ b/util/glgen/main.cpp
@@ -40,22 +40,39 @@
 ****************************************************************************/
 
 #include "codegenerator.h"
-#include "specparser.h"
+#include "legacyspecparser.h"
+#include "xmlspecparser.h"
+
+#include <QCommandLineParser>
 
 int main(int argc, char *argv[])
 {
-    Q_UNUSED(argc);
-    Q_UNUSED(argv);
+    QCoreApplication app(argc, argv);
+    QCommandLineParser cmdParser;
+
+    // flag whether to use legacy or not
+    QCommandLineOption legacyOption(QStringList() << "l" << "legacy", "Use legacy parser.");
+    cmdParser.addOption(legacyOption);
+    cmdParser.process(app);
+
+    SpecParser *parser;
+
+    if (cmdParser.isSet(legacyOption)) {
+        parser = new LegacySpecParser();
+        parser->setTypeMapFileName(QStringLiteral("gl.tm"));
+        parser->setSpecFileName(QStringLiteral("gl.spec"));
+    } else {
+        parser = new XmlSpecParser();
+        parser->setSpecFileName(QStringLiteral("gl.xml"));
+    }
 
-    SpecParser parser;
-    parser.setTypeMapFileName(QStringLiteral("gl.tm"));
-    parser.setSpecFileName(QStringLiteral("gl.spec"));
-    parser.parse();
+    parser->parse();
 
     CodeGenerator generator;
-    generator.setParser(&parser);
+    generator.setParser(parser);
     generator.generateCoreClasses(QStringLiteral("qopenglversionfunctions"));
     generator.generateExtensionClasses(QStringLiteral("qopenglextensions"));
 
+    delete parser;
     return 0;
 }
diff --git a/util/glgen/specparser.h b/util/glgen/specparser.h
index 19357841ca3cdaaadc970c935047293a9803f0bf..0ba36ef8d84e616cdec1cd21366961d6f158d946 100644
--- a/util/glgen/specparser.h
+++ b/util/glgen/specparser.h
@@ -46,6 +46,7 @@
 #include <QVariant>
 
 class QTextStream;
+class QXmlStreamReader;
 
 struct Version {
     int major;
@@ -57,6 +58,11 @@ inline bool operator == (const Version &lhs, const Version &rhs)
     return (lhs.major == rhs.major && lhs.minor == rhs.minor);
 }
 
+inline bool operator != (const Version &lhs, const Version &rhs)
+{
+    return !(lhs == rhs);
+}
+
 inline bool operator < (const Version &lhs, const Version &rhs)
 {
     if (lhs.major != rhs.major)
@@ -73,6 +79,17 @@ inline bool operator > (const Version &lhs, const Version &rhs)
         return (lhs.minor > rhs.minor);
 }
 
+inline bool operator >= (const Version &lhs, const Version &rhs)
+{
+    return !(lhs < rhs);
+}
+
+
+inline bool operator <= (const Version &lhs, const Version &rhs)
+{
+    return !(lhs > rhs);
+}
+
 inline uint qHash(const Version &v)
 {
     return qHash(v.major * 100 + v.minor * 10);
@@ -102,6 +119,11 @@ inline bool operator == (const VersionProfile &lhs, const VersionProfile &rhs)
     return lhs.version == rhs.version;
 }
 
+inline bool operator != (const VersionProfile &lhs, const VersionProfile &rhs)
+{
+    return !(lhs == rhs);
+}
+
 inline bool operator < (const VersionProfile &lhs, const VersionProfile &rhs)
 {
     if (lhs.profile != rhs.profile)
@@ -140,13 +162,47 @@ struct Function
     QList<Argument> arguments;
 };
 
+inline bool operator== (const Argument &lhs, const Argument &rhs)
+{
+    if ((lhs.type != rhs.type) || (lhs.name != rhs.name) || (lhs.direction != rhs.direction)) {
+        return false;
+    }
+
+    return (lhs.mode != rhs.mode);
+}
+
+inline bool operator!= (const Argument &lhs, const Argument &rhs)
+{
+    return !(lhs == rhs);
+}
+
+inline bool operator== (const Function &lhs, const Function &rhs)
+{
+    if ((lhs.returnType != rhs.returnType) || (lhs.name != rhs.name)) {
+        return false;
+    }
+
+    return (lhs.arguments == rhs.arguments);
+}
+
+inline bool operator!= (const Function &lhs, const Function &rhs)
+{
+    return !(lhs == rhs);
+}
+
 typedef QList<Function> FunctionList;
 typedef QMap<VersionProfile, FunctionList> FunctionCollection;
 
+struct FunctionProfile
+{
+    VersionProfile::OpenGLProfile profile;
+    Function function;
+};
+
 class SpecParser
 {
 public:
-    explicit SpecParser();
+    virtual ~SpecParser() {}
 
     QString specFileName() const
     {
@@ -158,22 +214,28 @@ public:
         return m_typeMapFileName;
     }
 
-    QList<Version> versions() const {return m_versions;}
-    QList<VersionProfile> versionProfiles() const {return m_functions.uniqueKeys();}
+    virtual QList<Version> versions() const = 0;
+
+    QList<VersionProfile> versionProfiles() const {return versionFunctions().uniqueKeys();}
 
     QList<Function> functionsForVersion(const VersionProfile &v) const
     {
-        return m_functions.values(v);
+        return versionFunctions().values(v);
     }
 
     QStringList extensions() const
     {
-        return QStringList(m_extensionFunctions.uniqueKeys());
+        return QStringList(extensionFunctions().uniqueKeys());
     }
 
     QList<Function> functionsForExtension(const QString &extension)
     {
-        return m_extensionFunctions.values(extension);
+        QList<Function> func;
+
+        Q_FOREACH (const FunctionProfile &f, extensionFunctions().values(extension))
+            func.append(f.function);
+
+        return func;
     }
 
     void setSpecFileName(QString arg)
@@ -186,25 +248,15 @@ public:
         m_typeMapFileName = arg;
     }
 
-    void parse();
+    virtual bool parse() = 0;
 
 protected:
-    bool parseTypeMap();
-    void parseEnums();
-    void parseFunctions(QTextStream &stream);
-    bool inDeprecationException(const QString &functionName) const;
+    virtual const QMultiHash<VersionProfile, Function> &versionFunctions() const = 0;
+    virtual const QMultiMap<QString, FunctionProfile> &extensionFunctions() const = 0;
 
 private:
     QString m_specFileName;
     QString m_typeMapFileName;
-
-    QMap<QString, QString> m_typeMap;
-    QMultiMap<VersionProfile, Function> m_functions;
-
-    QList<Version> m_versions;
-
-    // Extension support
-    QMultiMap<QString, Function> m_extensionFunctions;
 };
 
 #endif // SPECPARSER_H
diff --git a/util/glgen/xmlspecparser.cpp b/util/glgen/xmlspecparser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c2be6d292d0352f49034b32968067ebd39e71ea1
--- /dev/null
+++ b/util/glgen/xmlspecparser.cpp
@@ -0,0 +1,440 @@
+/***************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB)
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the utilities of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "xmlspecparser.h"
+
+#include <QDebug>
+#include <QFile>
+#include <QRegularExpression>
+#include <QStringList>
+#include <QTextStream>
+#include <QXmlStreamReader>
+
+#ifdef SPECPARSER_DEBUG
+#define qXmlSpecParserDebug qDebug
+#else
+#define qXmlSpecParserDebug QT_NO_QDEBUG_MACRO
+#endif
+
+bool XmlSpecParser::parse()
+{
+    // Open up a stream on the actual OpenGL function spec file
+    QFile file(specFileName());
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        qWarning() << "Failed to open spec file:" << specFileName() << "Aborting";
+        return false;
+    }
+
+    QXmlStreamReader stream(&file);
+
+    // Extract the info that we need
+    parseFunctions(stream);
+    return true;
+}
+
+void XmlSpecParser::parseParam(QXmlStreamReader &stream, Function &func)
+{
+    Argument arg;
+    arg.type = QString();
+
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "ptype") {
+                if (stream.readNext() == QXmlStreamReader::Characters)
+                    arg.type.append(stream.text().toString());
+            }
+
+            else if (tag == "name") {
+                if (stream.readNext() == QXmlStreamReader::Characters)
+                    arg.name = stream.text().toString().trimmed();
+            }
+        } else if (stream.isCharacters()) {
+            arg.type.append(stream.text().toString());
+        } else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "param") {
+                // compatibility with old spec
+                QRegularExpression typeRegExp("(const )?(.+)(?<!\\*)((?:(?!\\*$)\\*)*)(\\*)?");
+
+                // remove extra whitespace
+                arg.type = arg.type.trimmed();
+
+                // set default
+                arg.direction = Argument::In;
+                arg.mode = Argument::Value;
+
+                QRegularExpressionMatch exp = typeRegExp.match(arg.type);
+                if (exp.hasMatch()) {
+                    if (!exp.captured(4).isEmpty()) {
+                        arg.mode = Argument::Reference;
+
+                        if (exp.captured(1).isEmpty())
+                            arg.direction = Argument::Out;
+                    }
+
+                    arg.type = exp.captured(2) + exp.captured(3);
+                }
+
+                break;
+            }
+        }
+    }
+
+    // remove any excess whitespace
+    arg.type = arg.type.trimmed();
+    arg.name = arg.name.trimmed();
+
+    // maybe some checks?
+    func.arguments.append(arg);
+}
+
+void XmlSpecParser::parseCommand(QXmlStreamReader &stream)
+{
+    Function func;
+
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "proto") {
+                while (!stream.isEndDocument()) {
+                    stream.readNext();
+                    if (stream.isStartElement() && (stream.name().toString() == "name")) {
+                        if (stream.readNext() == QXmlStreamReader::Characters)
+                            func.name = stream.text().toString();
+                    } else if (stream.isCharacters()) {
+                        func.returnType.append(stream.text().toString());
+                    } else if (stream.isEndElement() && (stream.name().toString() == "proto")) {
+                        break;
+                    }
+                }
+            }
+
+            if (tag == "param")
+                parseParam(stream, func);
+        }
+
+        else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "command")
+                break;
+        }
+    }
+
+    // maybe checks?
+    func.returnType = func.returnType.trimmed();
+
+    // for compatibility with old spec
+    if (func.name.startsWith("gl"))
+        func.name.remove(0, 2);
+
+    m_functionList.insert(func.name, func);
+}
+
+void XmlSpecParser::parseCommands(QXmlStreamReader &stream)
+{
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "command")
+                parseCommand(stream);
+        }
+
+        else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "commands")
+                break;
+        }
+    }
+}
+
+void XmlSpecParser::parseRequire(QXmlStreamReader &stream, FunctionList &funcs)
+{
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "command") {
+                QString func = stream.attributes().value("name").toString();
+
+                // for compatibility with old spec
+                if (func.startsWith("gl"))
+                    func.remove(0, 2);
+
+                funcs.append(m_functionList[func]);
+            }
+        } else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "require")
+                break;
+        }
+    }
+}
+
+void XmlSpecParser::parseRemoveCore(QXmlStreamReader &stream)
+{
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "command") {
+                QString func = stream.attributes().value("name").toString();
+
+                // for compatibility with old spec
+                if (func.startsWith("gl"))
+                    func.remove(0, 2);
+
+                // go through list of version and mark as incompatible
+                Q_FOREACH (const Version& v, m_versions) {
+                    // Combine version and profile for this subset of functions
+                    VersionProfile version;
+                    version.version = v;
+                    version.profile = VersionProfile::CoreProfile;
+
+                    // Fetch the functions and add to collection for this class
+                    Q_FOREACH (const Function& f, m_functions.values(version)) {
+                        if (f.name == func) {
+                            VersionProfile newVersion;
+                            newVersion.version = v;
+                            newVersion.profile = VersionProfile::CompatibilityProfile;
+
+                            m_functions.insert(newVersion, f);
+                            m_functions.remove(version, f);
+                        }
+                    }
+                }
+            }
+        } else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "remove")
+                break;
+        }
+    }
+}
+
+void XmlSpecParser::parseFeature(QXmlStreamReader &stream)
+{
+    QRegularExpression versionRegExp("(\\d).(\\d)");
+    QXmlStreamAttributes attributes = stream.attributes();
+
+    QRegularExpressionMatch match = versionRegExp.match(attributes.value("number").toString());
+
+    if (!match.hasMatch()) {
+        qWarning() << "Malformed version indicator";
+        return;
+    }
+
+    if (attributes.value("api").toString() != "gl")
+        return;
+
+    int majorVersion = match.captured(1).toInt();
+    int minorVersion = match.captured(2).toInt();
+
+    Version v;
+    VersionProfile core, compat;
+
+    v.major = majorVersion;
+    v.minor = minorVersion;
+    core.version = compat.version = v;
+    core.profile = VersionProfile::CoreProfile;
+    compat.profile = VersionProfile::CompatibilityProfile;
+
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "require") {
+                FunctionList funcs;
+
+                if (stream.attributes().value("profile").toString() == "compatibility") {
+                    parseRequire(stream, funcs);
+                    Q_FOREACH (const Function& f, funcs) {
+                        m_functions.insert(compat, f);
+                    }
+                } else {
+                    parseRequire(stream, funcs);
+                    Q_FOREACH (const Function& f, funcs) {
+                        m_functions.insert(core, f);
+                    }
+                }
+            } else if (tag == "remove") {
+                if (stream.attributes().value("profile").toString() == "core")
+                    parseRemoveCore(stream);
+            }
+        } else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "feature")
+                break;
+        }
+    }
+
+    m_versions.append(v);
+}
+
+void XmlSpecParser::parseExtension(QXmlStreamReader &stream)
+{
+    QXmlStreamAttributes attributes = stream.attributes();
+    QString name = attributes.value("name").toString();
+
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "require") {
+                if (stream.attributes().value("profile").toString() == "compatibility") {
+                    FunctionList funcs;
+                    parseRequire(stream, funcs);
+
+                    Q_FOREACH (const Function& f, funcs) {
+                        FunctionProfile fp;
+                        fp.function = f;
+                        fp.profile = VersionProfile::CompatibilityProfile;
+                        m_extensionFunctions.insert(name, fp);
+                    }
+                } else {
+                    FunctionList funcs;
+                    parseRequire(stream, funcs);
+                    Q_FOREACH (const Function& f, funcs) {
+                        FunctionProfile fp;
+                        fp.function = f;
+                        fp.profile = VersionProfile::CoreProfile;
+                        m_extensionFunctions.insert(name, fp);
+                    }
+                }
+
+
+            }
+        } else if (stream.isEndElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "extension")
+                break;
+        }
+    }
+}
+
+void XmlSpecParser::parseFunctions(QXmlStreamReader &stream)
+{
+    while (!stream.isEndDocument()) {
+        stream.readNext();
+
+        if (stream.isStartElement()) {
+            QString tag = stream.name().toString();
+
+            if (tag == "feature") {
+                parseFeature(stream);
+            } else if (tag == "commands") {
+                parseCommands(stream);
+            } else if (tag == "extension") {
+                parseExtension(stream);
+            }
+        } else if (stream.isEndElement()) {
+            stream.readNext();
+        }
+    }
+
+    // hack - add GL_ARB_imaging to every version after 1.2 inclusive
+    Version versionThreshold;
+    versionThreshold.major = 1;
+    versionThreshold.minor = 2;
+    QList<FunctionProfile> funcs = m_extensionFunctions.values("GL_ARB_imaging");
+
+    VersionProfile vp;
+    vp.version = versionThreshold;
+
+    Q_FOREACH (const FunctionProfile& fp, funcs) {
+        vp.profile = fp.profile;
+        m_functions.insert(vp, fp.function);
+    }
+
+    // now we will prune any duplicates
+    QSet<QString> funcset;
+
+    Q_FOREACH (const Version& v, m_versions) {
+        // check compatibility first
+        VersionProfile vp;
+        vp.version = v;
+
+        vp.profile = VersionProfile::CompatibilityProfile;
+
+        Q_FOREACH (const Function& f, m_functions.values(vp)) {
+            // remove duplicate
+            if (funcset.contains(f.name))
+                m_functions.remove(vp, f);
+
+            funcset.insert(f.name);
+        }
+
+        vp.profile = VersionProfile::CoreProfile;
+
+        Q_FOREACH (const Function& f, m_functions.values(vp)) {
+
+            // remove duplicate
+            if (funcset.contains(f.name))
+                m_functions.remove(vp, f);
+
+            funcset.insert(f.name);
+        }
+    }
+}
diff --git a/util/glgen/xmlspecparser.h b/util/glgen/xmlspecparser.h
new file mode 100644
index 0000000000000000000000000000000000000000..3049e911cc56473120d11e5b242bc6fd8a5b406f
--- /dev/null
+++ b/util/glgen/xmlspecparser.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the utilities of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef XMLSPECPARSER_H
+#define XMLSPECPARSER_H
+
+#include "specparser.h"
+
+#include <QStringList>
+#include <QVariant>
+
+class QXmlStreamReader;
+
+class XmlSpecParser : public SpecParser
+{
+public:
+    virtual QList<Version> versions() const { return m_versions; }
+
+    virtual bool parse();
+
+protected:
+    const QMultiHash<VersionProfile, Function> &versionFunctions() const { return m_functions; }
+    const QMultiMap<QString, FunctionProfile> &extensionFunctions() const { return m_extensionFunctions; }
+
+private:
+    void parseFunctions(QXmlStreamReader &stream);
+    void parseCommands(QXmlStreamReader &stream);
+    void parseCommand(QXmlStreamReader &stream);
+    void parseParam(QXmlStreamReader &stream, Function &func);
+    void parseFeature(QXmlStreamReader &stream);
+    void parseExtension(QXmlStreamReader &stream);
+    void parseRequire(QXmlStreamReader &stream, FunctionList& profile);
+    void parseRemoveCore(QXmlStreamReader &stream);
+
+    QMultiHash<VersionProfile, Function> m_functions;
+
+    QList<Version> m_versions;
+
+    // Extension support
+    QMultiMap<QString, FunctionProfile> m_extensionFunctions;
+
+    QMap<QString, Function> m_functionList;
+};
+
+#endif // XMLSPECPARSER_H