1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.dom;
16
17 import org.htmlunit.corejs.javascript.Context;
18 import org.htmlunit.corejs.javascript.Function;
19 import org.htmlunit.corejs.javascript.NativeFunction;
20 import org.htmlunit.corejs.javascript.Scriptable;
21 import org.htmlunit.corejs.javascript.ScriptableObject;
22 import org.htmlunit.corejs.javascript.VarScope;
23 import org.htmlunit.html.DomNode;
24 import org.htmlunit.javascript.HtmlUnitScriptable;
25 import org.htmlunit.javascript.JavaScriptEngine;
26 import org.htmlunit.javascript.configuration.JsxClass;
27 import org.htmlunit.javascript.configuration.JsxConstructor;
28 import org.htmlunit.javascript.configuration.JsxFunction;
29 import org.htmlunit.javascript.host.NativeFunctionPrefixResolver;
30 import org.htmlunit.javascript.host.Window;
31 import org.htmlunit.xpath.xml.utils.PrefixResolver;
32
33
34
35
36
37
38
39
40 @JsxClass
41 public class XPathEvaluator extends HtmlUnitScriptable {
42
43
44
45
46 @JsxConstructor
47 public void jsConstructor() {
48
49 }
50
51
52
53
54
55
56
57
58 @JsxFunction
59 public NativeXPathNSResolver createNSResolver(final Node nodeResolver) {
60 final NativeXPathNSResolver resolver = new NativeXPathNSResolver();
61 resolver.setElement(nodeResolver);
62 resolver.setParentScope(getTopLevelScope(getParentScope()));
63 resolver.setPrototype(getPrototype(resolver.getClass()));
64 return resolver;
65 }
66
67
68
69
70
71
72
73
74
75
76
77 @JsxFunction
78 public XPathResult evaluate(final String expression, final Object contextNodeObj,
79 final Object resolver, final int type, final Object result) {
80 try {
81
82 if (!(contextNodeObj instanceof Node contextNode)) {
83 throw JavaScriptEngine.typeError("Illegal value for parameter 'context'");
84 }
85
86 PrefixResolver prefixResolver = null;
87 if (resolver instanceof PrefixResolver prefixResolver1) {
88 prefixResolver = prefixResolver1;
89 }
90 else if (resolver instanceof NativeFunction function) {
91 prefixResolver = new NativeFunctionPrefixResolver(
92 function, contextNode.getParentScope());
93 }
94
95 final XPathResult xPathResult;
96 if (result instanceof XPathResult pathResult) {
97 xPathResult = pathResult;
98 }
99 else {
100 xPathResult = new XPathResult();
101 xPathResult.setParentScope(getParentScope());
102 xPathResult.setPrototype(getPrototype(xPathResult.getClass()));
103 }
104
105 xPathResult.init(contextNode.getDomNodeOrDie().getByXPath(expression, prefixResolver), type);
106 return xPathResult;
107 }
108 catch (final Exception e) {
109 throw JavaScriptEngine.typeError("Failed to execute 'evaluate': " + e.getMessage());
110 }
111 }
112
113
114
115
116
117
118
119
120
121
122 @JsxFunction
123 public static XPathExpression createExpression(final Context context, final VarScope scope,
124 final Scriptable thisObj, final Object[] args, final Function function) {
125 if (args.length < 1) {
126 throw JavaScriptEngine.reportRuntimeError("Missing 'expression' parameter");
127 }
128
129 PrefixResolver prefixResolver = null;
130 if (args.length > 1) {
131 final Object resolver = args[1];
132 if (resolver instanceof PrefixResolver prefixResolver1) {
133 prefixResolver = prefixResolver1;
134 }
135 else if (resolver instanceof NativeFunction nativeFunction) {
136 prefixResolver = new NativeFunctionPrefixResolver(
137 nativeFunction, scope.getParentScope());
138 }
139 }
140
141 final XPathEvaluator evaluator = (XPathEvaluator) thisObj;
142
143 try {
144 final String xpath = JavaScriptEngine.toString(args[0]);
145 final Window window = (Window) (ScriptableObject.getTopLevelScope(scope)).getGlobalThis();
146 final DomNode doc = window.getDocument().getDocumentElement().getDomNodeOrDie();
147 final XPathExpression xPathExpression = new XPathExpression(xpath, prefixResolver, doc);
148 xPathExpression.setParentScope(evaluator.getParentScope());
149 xPathExpression.setPrototype(evaluator.getPrototype(xPathExpression.getClass()));
150
151 return xPathExpression;
152 }
153 catch (final Exception e) {
154 throw JavaScriptEngine.syntaxError(
155 "Failed to compile xpath '" + args[0] + "' (" + e.getMessage() + ")");
156 }
157 }
158 }