1/* 2 * This file is part of the XSL implementation. 3 * 4 * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22#include "config.h" 23 24#if ENABLE(XSLT) 25 26#include "XSLTProcessor.h" 27 28#include "Console.h" 29#include "DOMWindow.h" 30#include "Frame.h" 31#include "TransformSource.h" 32#include "markup.h" 33#include <wtf/Assertions.h> 34#include <wtf/Vector.h> 35 36#include <qabstractmessagehandler.h> 37#include <qabstracturiresolver.h> 38#include <qbuffer.h> 39#include <qsourcelocation.h> 40#include <qxmlquery.h> 41 42namespace WebCore { 43 44class XSLTMessageHandler : public QAbstractMessageHandler { 45 46public: 47 XSLTMessageHandler(Document* document = 0); 48 virtual void handleMessage(QtMsgType type, const QString& description, 49 const QUrl& identifier, const QSourceLocation& sourceLocation); 50 51private: 52 Document* m_document; 53}; 54 55XSLTMessageHandler::XSLTMessageHandler(Document* document) 56 : QAbstractMessageHandler() 57 , m_document(document) 58{ 59} 60 61void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description, 62 const QUrl&, const QSourceLocation& sourceLocation) 63{ 64 if (!m_document->frame()) 65 return; 66 67 MessageLevel level; 68 switch (type) { 69 case QtDebugMsg: 70 level = TipMessageLevel; 71 break; 72 case QtWarningMsg: 73 level = WarningMessageLevel; 74 break; 75 case QtCriticalMsg: 76 case QtFatalMsg: 77 level = ErrorMessageLevel; 78 break; 79 default: 80 level = LogMessageLevel; 81 break; 82 } 83 84 Console* console = m_document->frame()->domWindow()->console(); 85 console->addMessage(XMLMessageSource, LogMessageType, level, description, 86 sourceLocation.line(), sourceLocation.uri().toString()); 87} 88 89class XSLTUriResolver : public QAbstractUriResolver { 90 91public: 92 XSLTUriResolver(Document* document); 93 virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const; 94 95private: 96 Document* m_document; 97}; 98 99XSLTUriResolver::XSLTUriResolver(Document* document) 100 : QAbstractUriResolver() 101 , m_document(document) 102{ 103} 104 105QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const 106{ 107 QUrl url = baseURI.resolved(relative); 108 109 if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url)) 110 return QUrl(); 111 return url; 112} 113 114bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&) 115{ 116 bool success = false; 117 118 RefPtr<XSLStyleSheet> stylesheet = m_stylesheet; 119 if (!stylesheet && m_stylesheetRootNode) { 120 Node* node = m_stylesheetRootNode.get(); 121 stylesheet = XSLStyleSheet::createForXSLTProcessor(node->parentNode() ? node->parentNode() : node, 122 node->document()->url().string(), 123 node->document()->url()); // FIXME: Should we use baseURL here? 124 125 // According to Mozilla documentation, the node must be a Document node, an xsl:stylesheet or xsl:transform element. 126 // But we just use text content regardless of node type. 127 stylesheet->parseString(createMarkup(node)); 128 } 129 130 if (!stylesheet || stylesheet->sheetString().isEmpty()) 131 return success; 132 133 RefPtr<Document> ownerDocument = sourceNode->document(); 134 bool sourceIsDocument = (sourceNode == ownerDocument.get()); 135 136 QXmlQuery query(QXmlQuery::XSLT20); 137 138 XSLTMessageHandler messageHandler(ownerDocument.get()); 139 XSLTUriResolver uriResolver(ownerDocument.get()); 140 query.setMessageHandler(&messageHandler); 141 142 XSLTProcessor::ParameterMap::iterator end = m_parameters.end(); 143 for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it) 144 query.bindVariable(QString(it->first), QXmlItem(QVariant(QString(it->second)))); 145 146 QString source; 147 if (sourceIsDocument && ownerDocument->transformSource()) 148 source = ownerDocument->transformSource()->platformSource(); 149 if (!sourceIsDocument || source.isEmpty()) 150 source = createMarkup(sourceNode); 151 152 QBuffer inputBuffer; 153 QBuffer styleSheetBuffer; 154 QBuffer outputBuffer; 155 156 inputBuffer.setData(source.toUtf8()); 157 styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8()); 158 159 inputBuffer.open(QIODevice::ReadOnly); 160 styleSheetBuffer.open(QIODevice::ReadOnly); 161 outputBuffer.open(QIODevice::ReadWrite); 162 163 query.setFocus(&inputBuffer); 164 query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href())); 165 166 query.setUriResolver(&uriResolver); 167 168 success = query.evaluateTo(&outputBuffer); 169 outputBuffer.reset(); 170 resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed(); 171 172 if (m_stylesheet) { 173 m_stylesheet->clearDocuments(); 174 m_stylesheet = 0; 175 } 176 177 return success; 178} 179 180} // namespace WebCore 181 182#endif // ENABLE(XSLT) 183