aboutsummaryrefslogtreecommitdiffstats
path: root/docparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docparser.cpp')
-rw-r--r--docparser.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/docparser.cpp b/docparser.cpp
new file mode 100644
index 000000000..ddff5ffe9
--- /dev/null
+++ b/docparser.cpp
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include "docparser.h"
+#include <QtCore/QDebug>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QBuffer>
+
+#include <cstdlib>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+
+DocParser::DocParser()
+{
+ xmlSubstituteEntitiesDefault(1);
+}
+
+DocParser::~DocParser()
+{
+}
+
+QString DocParser::getDocumentation(QXmlQuery& xquery, const QString& query,
+ const DocModificationList& mods) const
+{
+ QString doc = execXQuery(xquery, query);
+ return applyDocModifications(mods, doc);
+}
+
+QString DocParser::execXQuery(QXmlQuery& xquery, const QString& query) const
+{
+ QString escapedQuery(query);
+ // XQuery can't have invalid XML characters
+ escapedQuery.replace("&", "&amp;").replace("<", "&lt;");
+ xquery.setQuery(escapedQuery);
+ if (!xquery.isValid()) {
+ qWarning() << "Bad XQuery: " << escapedQuery;
+ return QString();
+ }
+
+ QString result;
+ xquery.evaluateTo(&result);
+ return result;
+}
+
+namespace
+{
+
+struct XslResources
+{
+ xmlDocPtr xmlDoc;
+ xsltStylesheetPtr xslt;
+ xmlDocPtr xslResult;
+
+ XslResources() : xmlDoc(0), xslt(0), xslResult(0) {}
+
+ ~XslResources()
+ {
+ if (xslt)
+ xsltFreeStylesheet(xslt);
+
+ if (xslResult)
+ xmlFreeDoc(xslResult);
+
+ if (xmlDoc)
+ xmlFreeDoc(xmlDoc);
+
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+ }
+};
+
+} // namespace
+
+QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) const
+{
+ if (mods.isEmpty())
+ return xml;
+
+ QString xsl = QLatin1String("<xsl:transform version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
+ "<xsl:template match=\"/\">\n"
+ " <xsl:apply-templates />\n"
+ "</xsl:template>\n"
+ "<xsl:template match=\"*\">\n"
+ "<xsl:copy>\n"
+ " <xsl:copy-of select=\"@*\"/>\n"
+ " <xsl:apply-templates/>\n"
+ "</xsl:copy>\n"
+ "</xsl:template>\n"
+ );
+ foreach (DocModification mod, mods) {
+ if (mod.mode() == DocModification::XPathReplace) {
+ xsl += QLatin1String("<xsl:template match=\"")
+ + mod.xpath().replace("\"", "&quot;") + QLatin1String("\">")
+ + mod.code() + QLatin1String("</xsl:template>\n");
+ }
+ }
+ xsl += QLatin1String("</xsl:transform>");
+
+ XslResources res;
+ // Read XML data
+ QByteArray xmlData = xml.toUtf8();
+ res.xmlDoc = xmlParseMemory(xmlData.constData(), xmlData.size());
+ if (!res.xmlDoc)
+ return xml;
+
+ // Read XSL data as a XML file
+ QByteArray xslData = xsl.toUtf8();
+ // xsltFreeStylesheet will delete this pointer
+ xmlDocPtr xslDoc = xmlParseMemory(xslData.constData(), xslData.size());
+ if (!xslDoc)
+ return xml;
+
+ // Parse XSL data
+ res.xslt = xsltParseStylesheetDoc(xslDoc);
+ if (!res.xslt)
+ return xml;
+
+ // Apply XSL
+ res.xslResult = xsltApplyStylesheet(res.xslt, res.xmlDoc, 0);
+ xmlChar* buffer = 0;
+ int bufferSize;
+ QString result;
+ if (!xsltSaveResultToString(&buffer, &bufferSize, res.xslResult, res.xslt)) {
+ result = QByteArray(reinterpret_cast<char*>(buffer), bufferSize);
+ std::free(buffer);
+ } else {
+ result = xml;
+ }
+
+ Q_ASSERT(result != xml);
+ return result;
+}
+