1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.xml;
16
17 import java.io.IOException;
18 import java.io.Serializable;
19 import java.util.function.Predicate;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.htmlunit.StringWebResponse;
24 import org.htmlunit.WebResponse;
25 import org.htmlunit.WebWindow;
26 import org.htmlunit.html.DomAttr;
27 import org.htmlunit.html.DomElement;
28 import org.htmlunit.html.DomNode;
29 import org.htmlunit.html.HtmlElement;
30 import org.htmlunit.javascript.HtmlUnitScriptable;
31 import org.htmlunit.javascript.JavaScriptEngine;
32 import org.htmlunit.javascript.configuration.JsxClass;
33 import org.htmlunit.javascript.configuration.JsxConstructor;
34 import org.htmlunit.javascript.configuration.JsxFunction;
35 import org.htmlunit.javascript.host.Element;
36 import org.htmlunit.javascript.host.dom.Attr;
37 import org.htmlunit.javascript.host.dom.Document;
38 import org.htmlunit.javascript.host.html.HTMLCollection;
39 import org.htmlunit.svg.SvgElement;
40 import org.htmlunit.util.StringUtils;
41 import org.htmlunit.xml.XmlPage;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @JsxClass
57 public class XMLDocument extends Document {
58
59 private static final Log LOG = LogFactory.getLog(XMLDocument.class);
60
61
62
63
64 public XMLDocument() {
65 this(null);
66 }
67
68
69
70
71 @Override
72 @JsxConstructor
73 public void jsConstructor() {
74 super.jsConstructor();
75 }
76
77
78
79
80
81
82 public XMLDocument(final WebWindow enclosingWindow) {
83 super();
84
85 if (enclosingWindow != null) {
86 try {
87 final XmlPage page = new XmlPage((WebResponse) null, enclosingWindow);
88 setDomNode(page);
89 }
90 catch (final IOException e) {
91 throw JavaScriptEngine.reportRuntimeError("IOException: " + e);
92 }
93 }
94 }
95
96
97
98
99
100
101
102
103 public boolean loadXML(final String strXML) {
104 final WebWindow webWindow = getWindow().getWebWindow();
105 try {
106 if (StringUtils.isEmptyOrNull(strXML)) {
107 throw new IOException("Error parsing XML '" + strXML + "'");
108 }
109
110 final WebResponse webResponse = new StringWebResponse(strXML, webWindow.getEnclosedPage().getUrl());
111
112 final XmlPage page = new XmlPage(webResponse, webWindow, false);
113 setDomNode(page);
114 return true;
115 }
116 catch (final IOException e) {
117 if (LOG.isDebugEnabled()) {
118 LOG.debug("Error parsing XML\n" + strXML, e);
119 }
120
121 try {
122 final XmlPage page = createParserErrorXmlPage("Syntax Error", webWindow);
123 setDomNode(page);
124 }
125 catch (final IOException ex) {
126 LOG.error("Could not handle ParserError", e);
127 }
128
129 return false;
130 }
131 }
132
133 private static XmlPage createParserErrorXmlPage(final String message, final WebWindow webWindow)
134 throws IOException {
135 final String xml = "<parsererror xmlns=\"http://www.mozilla.org/newlayout/xml/parsererror.xml\">\n"
136 + message + "\n"
137 + "<sourcetext></sourcetext>\n"
138 + "</parsererror>";
139
140 final WebResponse webResponse = new StringWebResponse(xml, webWindow.getEnclosedPage().getUrl());
141
142 return new XmlPage(webResponse, webWindow, false);
143 }
144
145
146
147
148 @Override
149 public HtmlUnitScriptable makeScriptableFor(final DomNode domNode) {
150 final HtmlUnitScriptable scriptable;
151
152
153 if (domNode instanceof DomElement && !(domNode instanceof HtmlElement)) {
154 if (domNode instanceof SvgElement) {
155 final Class<? extends HtmlUnitScriptable> javaScriptClass
156 = ((JavaScriptEngine) getWindow().getWebWindow().getWebClient()
157 .getJavaScriptEngine()).getJavaScriptClass(domNode.getClass());
158 try {
159 scriptable = javaScriptClass.getDeclaredConstructor().newInstance();
160 }
161 catch (final Exception e) {
162 throw JavaScriptEngine.throwAsScriptRuntimeEx(e);
163 }
164 }
165 else {
166 scriptable = new Element();
167 }
168 }
169 else if (domNode instanceof DomAttr) {
170 scriptable = new Attr();
171 }
172 else {
173 return super.makeScriptableFor(domNode);
174 }
175
176 scriptable.setPrototype(getPrototype(scriptable.getClass()));
177 scriptable.setParentScope(getParentScope());
178 scriptable.setDomNode(domNode);
179 return scriptable;
180 }
181
182
183
184
185 @Override
186 @JsxFunction
187 public HTMLCollection getElementsByTagName(final String tagName) {
188 final DomNode firstChild = getDomNodeOrDie().getFirstChild();
189 if (firstChild == null) {
190 return HTMLCollection.emptyCollection(getWindow().getDomNodeOrDie());
191 }
192
193 final HTMLCollection elements = new HTMLCollection(getDomNodeOrDie(), false);
194
195 elements.setIsMatchingPredicate(
196 (Predicate<DomNode> & Serializable)
197 node -> {
198 final String nodeName = node.getNodeName();
199 return nodeName.equals(tagName);
200 });
201 return elements;
202 }
203 }