/* * This file is part of the XSL implementation. * * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "config.h" #if ENABLE(XSLT) #include "XSLTProcessor.h" #include "Console.h" #include "DOMWindow.h" #include "Frame.h" #include "TransformSource.h" #include "markup.h" #include <wtf/Assertions.h> #include <wtf/Vector.h> #include <qabstractmessagehandler.h> #include <qabstracturiresolver.h> #include <qbuffer.h> #include <qsourcelocation.h> #include <qxmlquery.h> namespace WebCore { class XSLTMessageHandler : public QAbstractMessageHandler { public: XSLTMessageHandler(Document* document = 0); virtual void handleMessage(QtMsgType type, const QString& description, const QUrl& identifier, const QSourceLocation& sourceLocation); private: Document* m_document; }; XSLTMessageHandler::XSLTMessageHandler(Document* document) : QAbstractMessageHandler() , m_document(document) { } void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description, const QUrl&, const QSourceLocation& sourceLocation) { if (!m_document->frame()) return; MessageLevel level; switch (type) { case QtDebugMsg: level = TipMessageLevel; break; case QtWarningMsg: level = WarningMessageLevel; break; case QtCriticalMsg: case QtFatalMsg: level = ErrorMessageLevel; break; default: level = LogMessageLevel; break; } Console* console = m_document->frame()->domWindow()->console(); console->addMessage(XMLMessageSource, LogMessageType, level, description, sourceLocation.line(), sourceLocation.uri().toString()); } class XSLTUriResolver : public QAbstractUriResolver { public: XSLTUriResolver(Document* document); virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const; private: Document* m_document; }; XSLTUriResolver::XSLTUriResolver(Document* document) : QAbstractUriResolver() , m_document(document) { } QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const { QUrl url = baseURI.resolved(relative); if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url)) return QUrl(); return url; } bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&) { bool success = false; RefPtr<XSLStyleSheet> stylesheet = m_stylesheet; if (!stylesheet && m_stylesheetRootNode) { Node* node = m_stylesheetRootNode.get(); stylesheet = XSLStyleSheet::createForXSLTProcessor(node->parentNode() ? node->parentNode() : node, node->document()->url().string(), node->document()->url()); // FIXME: Should we use baseURL here? // According to Mozilla documentation, the node must be a Document node, an xsl:stylesheet or xsl:transform element. // But we just use text content regardless of node type. stylesheet->parseString(createMarkup(node)); } if (!stylesheet || stylesheet->sheetString().isEmpty()) return success; RefPtr<Document> ownerDocument = sourceNode->document(); bool sourceIsDocument = (sourceNode == ownerDocument.get()); QXmlQuery query(QXmlQuery::XSLT20); XSLTMessageHandler messageHandler(ownerDocument.get()); XSLTUriResolver uriResolver(ownerDocument.get()); query.setMessageHandler(&messageHandler); XSLTProcessor::ParameterMap::iterator end = m_parameters.end(); for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it) query.bindVariable(QString(it->first), QXmlItem(QVariant(QString(it->second)))); QString source; if (sourceIsDocument && ownerDocument->transformSource()) source = ownerDocument->transformSource()->platformSource(); if (!sourceIsDocument || source.isEmpty()) source = createMarkup(sourceNode); QBuffer inputBuffer; QBuffer styleSheetBuffer; QBuffer outputBuffer; inputBuffer.setData(source.toUtf8()); styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8()); inputBuffer.open(QIODevice::ReadOnly); styleSheetBuffer.open(QIODevice::ReadOnly); outputBuffer.open(QIODevice::ReadWrite); query.setFocus(&inputBuffer); query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href())); query.setUriResolver(&uriResolver); success = query.evaluateTo(&outputBuffer); outputBuffer.reset(); resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed(); if (m_stylesheet) { m_stylesheet->clearDocuments(); m_stylesheet = 0; } return success; } } // namespace WebCore #endif // ENABLE(XSLT)