|
1 /* |
|
2 * This file is part of the XSL implementation. |
|
3 * |
|
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple, Inc. All rights reserved. |
|
5 * Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@webkit.org> |
|
6 * |
|
7 * This library is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU Library General Public |
|
9 * License as published by the Free Software Foundation; either |
|
10 * version 2 of the License, or (at your option) any later version. |
|
11 * |
|
12 * This library is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 * Library General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU Library General Public License |
|
18 * along with this library; see the file COPYING.LIB. If not, write to |
|
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
20 * Boston, MA 02110-1301, USA. |
|
21 */ |
|
22 |
|
23 #include "config.h" |
|
24 |
|
25 #if ENABLE(XSLT) |
|
26 |
|
27 #include "XSLTProcessor.h" |
|
28 |
|
29 #include "DOMImplementation.h" |
|
30 #include "DocLoader.h" |
|
31 #include "DocumentFragment.h" |
|
32 #include "Frame.h" |
|
33 #include "FrameLoader.h" |
|
34 #include "FrameView.h" |
|
35 #include "HTMLDocument.h" |
|
36 #include "Page.h" |
|
37 #include "Text.h" |
|
38 #include "TextResourceDecoder.h" |
|
39 #include "loader.h" |
|
40 #include "markup.h" |
|
41 |
|
42 #include <wtf/Assertions.h> |
|
43 #include <wtf/Vector.h> |
|
44 |
|
45 namespace WebCore { |
|
46 |
|
47 static inline void transformTextStringToXHTMLDocumentString(String& text) |
|
48 { |
|
49 // Modify the output so that it is a well-formed XHTML document with a <pre> tag enclosing the text. |
|
50 text.replace('&', "&"); |
|
51 text.replace('<', "<"); |
|
52 text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
|
53 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" |
|
54 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" |
|
55 "<head><title/></head>\n" |
|
56 "<body>\n" |
|
57 "<pre>" + text + "</pre>\n" |
|
58 "</body>\n" |
|
59 "</html>\n"; |
|
60 } |
|
61 |
|
62 PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourceString, |
|
63 const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame) |
|
64 { |
|
65 RefPtr<Document> ownerDocument = sourceNode->document(); |
|
66 bool sourceIsDocument = (sourceNode == ownerDocument.get()); |
|
67 String documentSource = sourceString; |
|
68 |
|
69 RefPtr<Document> result; |
|
70 if (sourceMIMEType == "text/plain") { |
|
71 result = Document::create(frame, sourceIsDocument ? ownerDocument->url() : KURL()); |
|
72 transformTextStringToXHTMLDocumentString(documentSource); |
|
73 } else |
|
74 result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : KURL(), false); |
|
75 |
|
76 // Before parsing, we need to save & detach the old document and get the new document |
|
77 // in place. We have to do this only if we're rendering the result document. |
|
78 if (frame) { |
|
79 if (FrameView* view = frame->view()) |
|
80 view->clear(); |
|
81 result->setTransformSourceDocument(frame->document()); |
|
82 frame->setDocument(result); |
|
83 } |
|
84 |
|
85 result->open(); |
|
86 |
|
87 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(sourceMIMEType); |
|
88 decoder->setEncoding(sourceEncoding.isEmpty() ? UTF8Encoding() : TextEncoding(sourceEncoding), TextResourceDecoder::EncodingFromXMLHeader); |
|
89 result->setDecoder(decoder.release()); |
|
90 |
|
91 result->write(documentSource); |
|
92 result->finishParsing(); |
|
93 result->close(); |
|
94 |
|
95 return result.release(); |
|
96 } |
|
97 |
|
98 static inline RefPtr<DocumentFragment> createFragmentFromSource(const String& sourceString, const String& sourceMIMEType, Document* outputDoc) |
|
99 { |
|
100 RefPtr<DocumentFragment> fragment = outputDoc->createDocumentFragment(); |
|
101 |
|
102 if (sourceMIMEType == "text/html") |
|
103 fragment->parseHTML(sourceString); |
|
104 else if (sourceMIMEType == "text/plain") |
|
105 fragment->legacyParserAddChild(Text::create(outputDoc, sourceString)); |
|
106 else { |
|
107 bool successfulParse = fragment->parseXML(sourceString, outputDoc->documentElement()); |
|
108 if (!successfulParse) |
|
109 return 0; |
|
110 } |
|
111 |
|
112 // FIXME: Do we need to mess with URLs here? |
|
113 |
|
114 return fragment; |
|
115 } |
|
116 |
|
117 PassRefPtr<Document> XSLTProcessor::transformToDocument(Node* sourceNode) |
|
118 { |
|
119 String resultMIMEType; |
|
120 String resultString; |
|
121 String resultEncoding; |
|
122 if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding)) |
|
123 return 0; |
|
124 return createDocumentFromSource(resultString, resultEncoding, resultMIMEType, sourceNode, 0); |
|
125 } |
|
126 |
|
127 PassRefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode, Document* outputDoc) |
|
128 { |
|
129 String resultMIMEType; |
|
130 String resultString; |
|
131 String resultEncoding; |
|
132 |
|
133 // If the output document is HTML, default to HTML method. |
|
134 if (outputDoc->isHTMLDocument()) |
|
135 resultMIMEType = "text/html"; |
|
136 |
|
137 if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding)) |
|
138 return 0; |
|
139 return createFragmentFromSource(resultString, resultMIMEType, outputDoc); |
|
140 } |
|
141 |
|
142 void XSLTProcessor::setParameter(const String& /*namespaceURI*/, const String& localName, const String& value) |
|
143 { |
|
144 // FIXME: namespace support? |
|
145 // should make a QualifiedName here but we'd have to expose the impl |
|
146 m_parameters.set(localName, value); |
|
147 } |
|
148 |
|
149 String XSLTProcessor::getParameter(const String& /*namespaceURI*/, const String& localName) const |
|
150 { |
|
151 // FIXME: namespace support? |
|
152 // should make a QualifiedName here but we'd have to expose the impl |
|
153 return m_parameters.get(localName); |
|
154 } |
|
155 |
|
156 void XSLTProcessor::removeParameter(const String& /*namespaceURI*/, const String& localName) |
|
157 { |
|
158 // FIXME: namespace support? |
|
159 m_parameters.remove(localName); |
|
160 } |
|
161 |
|
162 void XSLTProcessor::reset() |
|
163 { |
|
164 m_stylesheet.clear(); |
|
165 m_stylesheetRootNode.clear(); |
|
166 m_parameters.clear(); |
|
167 } |
|
168 |
|
169 } // namespace WebCore |
|
170 |
|
171 #endif // ENABLE(XSLT) |