|
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 "loader.h" |
|
33 #include "markup.h" |
|
34 #include <wtf/Assertions.h> |
|
35 #include <wtf/Vector.h> |
|
36 |
|
37 #include <qabstractmessagehandler.h> |
|
38 #include <qabstracturiresolver.h> |
|
39 #include <qbuffer.h> |
|
40 #include <qsourcelocation.h> |
|
41 #include <qxmlquery.h> |
|
42 |
|
43 namespace WebCore { |
|
44 |
|
45 class XSLTMessageHandler : public QAbstractMessageHandler { |
|
46 |
|
47 public: |
|
48 XSLTMessageHandler(Document* document = 0); |
|
49 virtual void handleMessage(QtMsgType type, const QString& description, |
|
50 const QUrl& identifier, const QSourceLocation& sourceLocation); |
|
51 |
|
52 private: |
|
53 Document* m_document; |
|
54 }; |
|
55 |
|
56 XSLTMessageHandler::XSLTMessageHandler(Document* document) |
|
57 : QAbstractMessageHandler() |
|
58 , m_document(document) |
|
59 { |
|
60 } |
|
61 |
|
62 void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description, |
|
63 const QUrl&, const QSourceLocation& sourceLocation) |
|
64 { |
|
65 if (!m_document->frame()) |
|
66 return; |
|
67 |
|
68 MessageLevel level; |
|
69 switch (type) { |
|
70 case QtDebugMsg: |
|
71 level = TipMessageLevel; |
|
72 break; |
|
73 case QtWarningMsg: |
|
74 level = WarningMessageLevel; |
|
75 break; |
|
76 case QtCriticalMsg: |
|
77 case QtFatalMsg: |
|
78 level = ErrorMessageLevel; |
|
79 break; |
|
80 default: |
|
81 level = LogMessageLevel; |
|
82 break; |
|
83 } |
|
84 |
|
85 Console* console = m_document->frame()->domWindow()->console(); |
|
86 console->addMessage(XMLMessageSource, LogMessageType, level, description, |
|
87 sourceLocation.line(), sourceLocation.uri().toString()); |
|
88 } |
|
89 |
|
90 class XSLTUriResolver : public QAbstractUriResolver { |
|
91 |
|
92 public: |
|
93 XSLTUriResolver(Document* document); |
|
94 virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const; |
|
95 |
|
96 private: |
|
97 Document* m_document; |
|
98 }; |
|
99 |
|
100 XSLTUriResolver::XSLTUriResolver(Document* document) |
|
101 : QAbstractUriResolver() |
|
102 , m_document(document) |
|
103 { |
|
104 } |
|
105 |
|
106 QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const |
|
107 { |
|
108 QUrl url = baseURI.resolved(relative); |
|
109 |
|
110 if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url)) |
|
111 return QUrl(); |
|
112 return url; |
|
113 } |
|
114 |
|
115 bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&) |
|
116 { |
|
117 bool success = false; |
|
118 |
|
119 RefPtr<XSLStyleSheet> stylesheet = m_stylesheet; |
|
120 if (!stylesheet && m_stylesheetRootNode) { |
|
121 Node* node = m_stylesheetRootNode.get(); |
|
122 stylesheet = XSLStyleSheet::create(node->parent() ? node->parent() : node, |
|
123 node->document()->url().string(), |
|
124 node->document()->url()); // FIXME: Should we use baseURL here? |
|
125 stylesheet->parseString(createMarkup(node)); |
|
126 } |
|
127 |
|
128 if (!stylesheet || stylesheet->sheetString().isEmpty()) |
|
129 return success; |
|
130 |
|
131 RefPtr<Document> ownerDocument = sourceNode->document(); |
|
132 bool sourceIsDocument = (sourceNode == ownerDocument.get()); |
|
133 |
|
134 QXmlQuery query(QXmlQuery::XSLT20); |
|
135 |
|
136 XSLTMessageHandler messageHandler(ownerDocument.get()); |
|
137 XSLTUriResolver uriResolver(ownerDocument.get()); |
|
138 query.setMessageHandler(&messageHandler); |
|
139 |
|
140 XSLTProcessor::ParameterMap::iterator end = m_parameters.end(); |
|
141 for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it) |
|
142 query.bindVariable(QString(it->first), QXmlItem(QVariant(it->second))); |
|
143 |
|
144 QString source; |
|
145 if (sourceIsDocument && ownerDocument->transformSource()) |
|
146 source = ownerDocument->transformSource()->platformSource(); |
|
147 if (!sourceIsDocument || source.isEmpty()) |
|
148 source = createMarkup(sourceNode); |
|
149 |
|
150 QBuffer inputBuffer; |
|
151 QBuffer styleSheetBuffer; |
|
152 QBuffer outputBuffer; |
|
153 |
|
154 inputBuffer.setData(source.toUtf8()); |
|
155 styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8()); |
|
156 |
|
157 inputBuffer.open(QIODevice::ReadOnly); |
|
158 styleSheetBuffer.open(QIODevice::ReadOnly); |
|
159 outputBuffer.open(QIODevice::ReadWrite); |
|
160 |
|
161 query.setFocus(&inputBuffer); |
|
162 query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href())); |
|
163 |
|
164 query.setUriResolver(&uriResolver); |
|
165 |
|
166 success = query.evaluateTo(&outputBuffer); |
|
167 outputBuffer.reset(); |
|
168 resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed(); |
|
169 |
|
170 if (m_stylesheet) { |
|
171 m_stylesheet->clearDocuments(); |
|
172 m_stylesheet = 0; |
|
173 } |
|
174 |
|
175 return success; |
|
176 } |
|
177 |
|
178 } // namespace WebCore |
|
179 |
|
180 #endif // ENABLE(XSLT) |