diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-04-18 12:41:14 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-04-25 11:53:15 +0000 |
commit | 21077bec48f2ca16ec0fed25e0c0af62317606d9 (patch) | |
tree | 8f3e8e6c636ce96c7385745a8b15959c01de426e /sources/shiboken2/ApiExtractor/docparser.cpp | |
parent | e336872828de86146059de0f62ed06afaaf64d8d (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.cpp | 183 |
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("&")); - escapedQuery.replace(QLatin1Char('<'), QLatin1String("<")); - 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(""")); - 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; } |