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