aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor/docparser.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2019-04-18 12:41:14 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2019-04-25 11:53:15 +0000
commit21077bec48f2ca16ec0fed25e0c0af62317606d9 (patch)
tree8f3e8e6c636ce96c7385745a8b15959c01de426e /sources/shiboken2/ApiExtractor/docparser.cpp
parente336872828de86146059de0f62ed06afaaf64d8d (diff)
shiboken2: Enable documentation generation with libxml2/libxslt
As QtXmlPatterns is deprecated in Qt 5.14, the documentation build needs to be changed to work with libxml2/libxslt exclusively. Split the XML functionality into separate files for libxslt and Qt and provide an interface for XPATH queries and XSLT transformations in xmlutils.h. Adapt testmodifydocumentation to work on temporary files as libxslt cannot handle Qt resources. Change-Id: I923f5b2e7c1d2511f15788e4b80c7721daeb2bc3 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken2/ApiExtractor/docparser.cpp')
-rw-r--r--sources/shiboken2/ApiExtractor/docparser.cpp183
1 files changed, 28 insertions, 155 deletions
diff --git a/sources/shiboken2/ApiExtractor/docparser.cpp b/sources/shiboken2/ApiExtractor/docparser.cpp
index 99921e7d3..532956d1a 100644
--- a/sources/shiboken2/ApiExtractor/docparser.cpp
+++ b/sources/shiboken2/ApiExtractor/docparser.cpp
@@ -30,10 +30,10 @@
#include "messages.h"
#include "reporthandler.h"
#include "typesystem.h"
+#include "xmlutils.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QTextStream>
-#include <QtXmlPatterns/QXmlQuery>
#include <QBuffer>
#include <cstdlib>
@@ -53,27 +53,19 @@ DocParser::DocParser()
DocParser::~DocParser() = default;
-QString DocParser::getDocumentation(QXmlQuery& xquery, const QString& query,
+QString DocParser::getDocumentation(const XQueryPtr &xquery, const QString& query,
const DocModificationList& mods) const
{
QString doc = execXQuery(xquery, query);
return applyDocModifications(mods, doc.trimmed());
}
-QString DocParser::execXQuery(QXmlQuery& xquery, const QString& query) const
+QString DocParser::execXQuery(const XQueryPtr &xquery, const QString& query) const
{
- QString escapedQuery(query);
- // XQuery can't have invalid XML characters
- escapedQuery.replace(QLatin1Char('&'), QLatin1String("&amp;"));
- escapedQuery.replace(QLatin1Char('<'), QLatin1String("&lt;"));
- xquery.setQuery(escapedQuery);
- if (!xquery.isValid()) {
- qWarning() << "Bad XQuery: " << escapedQuery;
- return QString();
- }
-
- QString result;
- xquery.evaluateTo(&result);
+ QString errorMessage;
+ const QString result = xquery->evaluate(query, &errorMessage);
+ if (!errorMessage.isEmpty())
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
return result;
}
@@ -108,41 +100,6 @@ AbstractMetaFunctionList DocParser::documentableFunctions(const AbstractMetaClas
return result;
}
-
-#ifdef HAVE_LIBXSLT
-namespace
-{
-
-class XslResources
-{
- Q_DISABLE_COPY(XslResources)
-
-public:
- xmlDocPtr xmlDoc = nullptr;
- xsltStylesheetPtr xslt = nullptr;
- xmlDocPtr xslResult = nullptr;
-
- XslResources() = default;
-
- ~XslResources()
- {
- if (xslt)
- xsltFreeStylesheet(xslt);
-
- if (xslResult)
- xmlFreeDoc(xslResult);
-
- if (xmlDoc)
- xmlFreeDoc(xmlDoc);
-
- xsltCleanupGlobals();
- xmlCleanupParser();
- }
-};
-
-} // namespace
-#endif // HAVE_LIBXSLT
-
static inline bool isXpathDocModification(const DocModification &mod)
{
return mod.mode() == TypeSystem::DocModificationXPathReplace;
@@ -150,102 +107,22 @@ static inline bool isXpathDocModification(const DocModification &mod)
QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) const
{
+ const char xslPrefix[] =
+R"(<xsl:template match="/">
+ <xsl:apply-templates />
+</xsl:template>
+<xsl:template match="*">
+<xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates/>
+</xsl:copy>
+</xsl:template>
+)";
+
if (mods.isEmpty() || xml.isEmpty()
|| !std::any_of(mods.cbegin(), mods.cend(), isXpathDocModification)) {
return xml;
}
-#ifdef HAVE_LIBXSLT
- const QString result = applyDocModificationsLibXsl(mods, xml);
-#else
- const QString result = applyDocModificationsQt(mods, xml);
-#endif
- if (result == xml) {
- const QString message = QLatin1String("Query did not result in any modifications to \"")
- + xml + QLatin1Char('"');
- qCWarning(lcShiboken, "%s",
- qPrintable(msgXpathDocModificationError(mods, message)));
- }
- return result;
-}
-
-QString DocParser::applyDocModificationsLibXsl(const DocModificationList& mods, const QString& xml) const
-{
-#ifdef HAVE_LIBXSLT
- QString xsl = QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
- "<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"
- );
- for (const DocModification &mod : mods) {
- if (isXpathDocModification(mod)) {
- QString xpath = mod.xpath();
- xpath.replace(QLatin1Char('"'), QLatin1String("&quot;"));
- xsl += QLatin1String("<xsl:template match=\"")
- + xpath + 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 = QString::fromUtf8(reinterpret_cast<char*>(buffer), bufferSize);
- std::free(buffer);
- } else {
- result = xml;
- }
- return result.trimmed();
-#else // HAVE_LIBXSLT
- Q_UNUSED(mods)
- return xml;
-#endif // !HAVE_LIBXSLT
-}
-
-QString DocParser::applyDocModificationsQt(const DocModificationList& mods, const QString& xml) const
-{
- const char xslPrefix[] =
-R"(<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
- <xsl:template match="/">
- <xsl:apply-templates/>\n"
- </xsl:template>
- <xsl:template match="*">
- <xsl:copy>
- <xsl:copy-of select="@*"/>
- <xsl:apply-templates/>
- </xsl:copy>
- </xsl:template>
-)";
QString xsl = QLatin1String(xslPrefix);
for (const DocModification &mod : mods) {
@@ -257,21 +134,17 @@ R"(<?xml version="1.0" encoding="UTF-8"?>
+ mod.code() + QLatin1String("</xsl:template>\n");
}
}
- xsl += QLatin1String("</xsl:stylesheet>");
- QXmlQuery query(QXmlQuery::XSLT20);
- query.setFocus(xml);
- query.setQuery(xsl);
- if (!query.isValid()) {
+ QString errorMessage;
+ const QString result = xsl_transform(xml, xsl, &errorMessage);
+ if (!errorMessage.isEmpty())
qCWarning(lcShiboken, "%s",
- qPrintable(msgXpathDocModificationError(mods, QLatin1String("Invalid query."))));
- return xml;
- }
- QString result;
- if (!query.evaluateTo(&result)) {
+ qPrintable(msgXpathDocModificationError(mods, errorMessage)));
+ if (result == xml) {
+ const QString message = QLatin1String("Query did not result in any modifications to \"")
+ + xml + QLatin1Char('"');
qCWarning(lcShiboken, "%s",
- qPrintable(msgXpathDocModificationError(mods, QLatin1String("evaluate() failed."))));
- return xml;
+ qPrintable(msgXpathDocModificationError(mods, message)));
}
- return result.trimmed();
+ return result;
}