1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.javascript.host.dom;
16
17 import java.io.IOException;
18
19 import org.htmlunit.StringWebResponse;
20 import org.htmlunit.WebClient;
21 import org.htmlunit.WebResponse;
22 import org.htmlunit.WebWindow;
23 import org.htmlunit.html.HtmlPage;
24 import org.htmlunit.html.parser.HTMLParser;
25 import org.htmlunit.javascript.HtmlUnitScriptable;
26 import org.htmlunit.javascript.JavaScriptEngine;
27 import org.htmlunit.javascript.configuration.JsxClass;
28 import org.htmlunit.javascript.configuration.JsxConstructor;
29 import org.htmlunit.javascript.configuration.JsxFunction;
30 import org.htmlunit.javascript.host.Window;
31 import org.htmlunit.javascript.host.html.HTMLDocument;
32 import org.htmlunit.javascript.host.xml.XMLDocument;
33 import org.htmlunit.util.MimeType;
34
35 /**
36 * A JavaScript object for {@code DOMParser}.
37 *
38 * @author Ahmed Ashour
39 * @author Frank Danek
40 * @author Ronald Brill
41 *
42 * @see <a href="http://www.w3.org/TR/DOM-Parsing/">W3C Spec</a>
43 * @see <a href="http://domparsing.spec.whatwg.org/">WhatWG Spec</a>
44 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMParser">MDN Documentation</a>
45 */
46 @JsxClass
47 public class DOMParser extends HtmlUnitScriptable {
48
49 /**
50 * JavaScript constructor.
51 */
52 @JsxConstructor
53 public void jsConstructor() {
54 // nothing to do
55 }
56
57 /**
58 * Parses the given Unicode string into a DOM document.
59 * @param str the Unicode string to be parsed
60 * @param type the MIME type of the string -
61 * <code>text/html</code>, <code>text/xml</code>, <code>application/xml</code>,
62 * <code>application/xhtml+xml</code>, <code>image/svg+xml</code>. Must not be {@code null}.
63 * @return the generated document
64 */
65 @JsxFunction
66 public Document parseFromString(final String str, final Object type) {
67 try {
68 final Document document = parseFromString(this, str, type);
69 if (document == null) {
70 throw JavaScriptEngine.typeError("Invalid 'type' parameter: " + type);
71 }
72 return document;
73 }
74 catch (final IOException e) {
75 throw JavaScriptEngine.syntaxError("Parsing failed" + e.getMessage());
76 }
77 }
78
79 /**
80 * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
81 *
82 * Parses the given Unicode string into a DOM document.
83 * @param scriptable the ScriptableObject this belongs to
84 * @param str the Unicode string to be parsed
85 * @param type the MIME type of the string -
86 * <code>text/html</code>, <code>text/xml</code>, <code>application/xml</code>,
87 * <code>application/xhtml+xml</code>, <code>image/svg+xml</code>. Must not be {@code null}.
88 * @return the generated document
89 * @throws IOException in case of error
90 */
91 public static Document parseFromString(final HtmlUnitScriptable scriptable, final String str, final Object type)
92 throws IOException {
93 if (type == null || JavaScriptEngine.isUndefined(type)) {
94 throw JavaScriptEngine.typeError("Missing 'type' parameter");
95 }
96
97 if (MimeType.TEXT_XML.equals(type)
98 || MimeType.APPLICATION_XML.equals(type)
99 || MimeType.APPLICATION_XHTML.equals(type)
100 || "image/svg+xml".equals(type)) {
101 final XMLDocument document = new XMLDocument();
102 document.setParentScope(scriptable.getParentScope());
103 document.setPrototype(scriptable.getPrototype(XMLDocument.class));
104 document.loadXML(str);
105 return document;
106 }
107
108 if (MimeType.TEXT_HTML.equals(type)) {
109 final WebWindow webWindow = scriptable.getWindow().getWebWindow();
110 final WebResponse webResponse = new StringWebResponse(str, webWindow.getEnclosedPage().getUrl());
111
112 return parseHtmlDocument(scriptable, webResponse, webWindow);
113 }
114
115 return null;
116 }
117
118 /**
119 * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
120 *
121 * Parses the given Unicode string into a DOM document.
122 * @param scriptable the ScriptableObject this belongs to
123 * @param webResponse the response to be parsed
124 * @param webWindow the window
125 * @return the generated document
126 * @throws IOException in case of error
127 */
128 public static Document parseHtmlDocument(final HtmlUnitScriptable scriptable, final WebResponse webResponse,
129 final WebWindow webWindow)
130 throws IOException {
131 // a similar impl is in
132 // org.htmlunit.javascript.host.dom.DOMImplementation.createHTMLDocument(Object)
133 final HtmlPage page = new HtmlPage(webResponse, webWindow);
134 page.setEnclosingWindow(null);
135 final Window window = webWindow.getScriptableObject();
136
137 // document knows the window but is not the windows document
138 final HTMLDocument document = new HTMLDocument();
139 document.setParentScope(getTopLevelScope(scriptable.getParentScope()));
140 document.setPrototype(window.getPrototype(document.getClass()));
141 // document.setWindow(window);
142 document.setDomNode(page);
143
144 final WebClient webClient = webWindow.getWebClient();
145 final HTMLParser htmlParser = webClient.getPageCreator().getHtmlParser();
146 htmlParser.parse(webClient, webResponse, page, false, true);
147 return page.getScriptableObject();
148 }
149 }