xslt-processor 3.4.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/index.d.mts +817 -0
  2. package/index.d.ts +817 -4
  3. package/index.js +4467 -12
  4. package/index.js.map +1 -1
  5. package/index.mjs +4431 -0
  6. package/index.mjs.map +1 -0
  7. package/package.json +23 -18
  8. package/umd/xslt-processor.global.js +9 -0
  9. package/umd/xslt-processor.global.js.map +1 -0
  10. package/constants.d.ts +0 -12
  11. package/constants.js +0 -17
  12. package/constants.js.map +0 -1
  13. package/dom/functions.d.ts +0 -14
  14. package/dom/functions.js +0 -57
  15. package/dom/functions.js.map +0 -1
  16. package/dom/index.d.ts +0 -7
  17. package/dom/index.js +0 -24
  18. package/dom/index.js.map +0 -1
  19. package/dom/util.d.ts +0 -7
  20. package/dom/util.js +0 -43
  21. package/dom/util.js.map +0 -1
  22. package/dom/xbrowser-node.d.ts +0 -9
  23. package/dom/xbrowser-node.js +0 -32
  24. package/dom/xbrowser-node.js.map +0 -1
  25. package/dom/xdocument.d.ts +0 -16
  26. package/dom/xdocument.js +0 -74
  27. package/dom/xdocument.js.map +0 -1
  28. package/dom/xml-functions.d.ts +0 -73
  29. package/dom/xml-functions.js +0 -402
  30. package/dom/xml-functions.js.map +0 -1
  31. package/dom/xml-output-options.d.ts +0 -6
  32. package/dom/xml-output-options.js +0 -3
  33. package/dom/xml-output-options.js.map +0 -1
  34. package/dom/xml-parser.d.ts +0 -47
  35. package/dom/xml-parser.js +0 -308
  36. package/dom/xml-parser.js.map +0 -1
  37. package/dom/xmltoken.d.ts +0 -12
  38. package/dom/xmltoken.js +0 -102
  39. package/dom/xmltoken.js.map +0 -1
  40. package/dom/xnode.d.ts +0 -73
  41. package/dom/xnode.js +0 -451
  42. package/dom/xnode.js.map +0 -1
  43. package/test-without-jest.d.ts +0 -1
  44. package/test-without-jest.js +0 -63
  45. package/test-without-jest.js.map +0 -1
  46. package/umd/constants.d.ts +0 -12
  47. package/umd/dom/functions.d.ts +0 -14
  48. package/umd/dom/index.d.ts +0 -7
  49. package/umd/dom/util.d.ts +0 -7
  50. package/umd/dom/xbrowser-node.d.ts +0 -9
  51. package/umd/dom/xdocument.d.ts +0 -16
  52. package/umd/dom/xml-functions.d.ts +0 -73
  53. package/umd/dom/xml-output-options.d.ts +0 -6
  54. package/umd/dom/xml-parser.d.ts +0 -47
  55. package/umd/dom/xmltoken.d.ts +0 -12
  56. package/umd/dom/xnode.d.ts +0 -73
  57. package/umd/index.d.ts +0 -4
  58. package/umd/test-without-jest.d.ts +0 -1
  59. package/umd/xpath/common-function.d.ts +0 -8
  60. package/umd/xpath/expr-context.d.ts +0 -116
  61. package/umd/xpath/expressions/binary-expr.d.ts +0 -11
  62. package/umd/xpath/expressions/expression.d.ts +0 -4
  63. package/umd/xpath/expressions/filter-expr.d.ts +0 -9
  64. package/umd/xpath/expressions/function-call-expr.d.ts +0 -12
  65. package/umd/xpath/expressions/index.d.ts +0 -13
  66. package/umd/xpath/expressions/literal-expr.d.ts +0 -7
  67. package/umd/xpath/expressions/location-expr.d.ts +0 -15
  68. package/umd/xpath/expressions/number-expr.d.ts +0 -7
  69. package/umd/xpath/expressions/path-expr.d.ts +0 -9
  70. package/umd/xpath/expressions/predicate-expr.d.ts +0 -8
  71. package/umd/xpath/expressions/step-expr.d.ts +0 -25
  72. package/umd/xpath/expressions/token-expr.d.ts +0 -7
  73. package/umd/xpath/expressions/unary-minus-expr.d.ts +0 -8
  74. package/umd/xpath/expressions/union-expr.d.ts +0 -9
  75. package/umd/xpath/expressions/variable-expr.d.ts +0 -7
  76. package/umd/xpath/functions/index.d.ts +0 -4
  77. package/umd/xpath/functions/internal-functions.d.ts +0 -2
  78. package/umd/xpath/functions/non-standard.d.ts +0 -12
  79. package/umd/xpath/functions/standard-20.d.ts +0 -5
  80. package/umd/xpath/functions/standard.d.ts +0 -40
  81. package/umd/xpath/functions/xslt-specific.d.ts +0 -3
  82. package/umd/xpath/grammar-rule-candidate.d.ts +0 -8
  83. package/umd/xpath/index.d.ts +0 -3
  84. package/umd/xpath/match-resolver.d.ts +0 -55
  85. package/umd/xpath/node-tests/index.d.ts +0 -8
  86. package/umd/xpath/node-tests/node-test-any.d.ts +0 -6
  87. package/umd/xpath/node-tests/node-test-comment.d.ts +0 -6
  88. package/umd/xpath/node-tests/node-test-element-or-attribute.d.ts +0 -6
  89. package/umd/xpath/node-tests/node-test-name.d.ts +0 -10
  90. package/umd/xpath/node-tests/node-test-nc.d.ts +0 -9
  91. package/umd/xpath/node-tests/node-test-pi.d.ts +0 -8
  92. package/umd/xpath/node-tests/node-test-text.d.ts +0 -6
  93. package/umd/xpath/node-tests/node-test.d.ts +0 -5
  94. package/umd/xpath/tokens.d.ts +0 -62
  95. package/umd/xpath/values/boolean-value.d.ts +0 -11
  96. package/umd/xpath/values/index.d.ts +0 -5
  97. package/umd/xpath/values/node-set-value.d.ts +0 -11
  98. package/umd/xpath/values/node-value.d.ts +0 -7
  99. package/umd/xpath/values/number-value.d.ts +0 -11
  100. package/umd/xpath/values/string-value.d.ts +0 -11
  101. package/umd/xpath/xpath-grammar-rules.d.ts +0 -68
  102. package/umd/xpath/xpath-token-rule.d.ts +0 -7
  103. package/umd/xpath/xpath.d.ts +0 -174
  104. package/umd/xpathdebug.d.ts +0 -2
  105. package/umd/xslt/index.d.ts +0 -3
  106. package/umd/xslt/xslt-decimal-format-settings.d.ts +0 -28
  107. package/umd/xslt/xslt-options.d.ts +0 -7
  108. package/umd/xslt/xslt-parameter.d.ts +0 -5
  109. package/umd/xslt/xslt.d.ts +0 -275
  110. package/umd/xslt-processor.js +0 -2
  111. package/umd/xslt-processor.js.map +0 -1
  112. package/xpath/common-function.d.ts +0 -8
  113. package/xpath/common-function.js +0 -32
  114. package/xpath/common-function.js.map +0 -1
  115. package/xpath/expr-context.d.ts +0 -116
  116. package/xpath/expr-context.js +0 -191
  117. package/xpath/expr-context.js.map +0 -1
  118. package/xpath/expressions/binary-expr.d.ts +0 -11
  119. package/xpath/expressions/binary-expr.js +0 -166
  120. package/xpath/expressions/binary-expr.js.map +0 -1
  121. package/xpath/expressions/expression.d.ts +0 -4
  122. package/xpath/expressions/expression.js +0 -10
  123. package/xpath/expressions/expression.js.map +0 -1
  124. package/xpath/expressions/filter-expr.d.ts +0 -9
  125. package/xpath/expressions/filter-expr.js +0 -53
  126. package/xpath/expressions/filter-expr.js.map +0 -1
  127. package/xpath/expressions/function-call-expr.d.ts +0 -12
  128. package/xpath/expressions/function-call-expr.js +0 -97
  129. package/xpath/expressions/function-call-expr.js.map +0 -1
  130. package/xpath/expressions/index.d.ts +0 -13
  131. package/xpath/expressions/index.js +0 -30
  132. package/xpath/expressions/index.js.map +0 -1
  133. package/xpath/expressions/literal-expr.d.ts +0 -7
  134. package/xpath/expressions/literal-expr.js +0 -34
  135. package/xpath/expressions/literal-expr.js.map +0 -1
  136. package/xpath/expressions/location-expr.d.ts +0 -15
  137. package/xpath/expressions/location-expr.js +0 -99
  138. package/xpath/expressions/location-expr.js.map +0 -1
  139. package/xpath/expressions/number-expr.d.ts +0 -7
  140. package/xpath/expressions/number-expr.js +0 -34
  141. package/xpath/expressions/number-expr.js.map +0 -1
  142. package/xpath/expressions/path-expr.d.ts +0 -9
  143. package/xpath/expressions/path-expr.js +0 -52
  144. package/xpath/expressions/path-expr.js.map +0 -1
  145. package/xpath/expressions/predicate-expr.d.ts +0 -8
  146. package/xpath/expressions/predicate-expr.js +0 -41
  147. package/xpath/expressions/predicate-expr.js.map +0 -1
  148. package/xpath/expressions/step-expr.d.ts +0 -25
  149. package/xpath/expressions/step-expr.js +0 -281
  150. package/xpath/expressions/step-expr.js.map +0 -1
  151. package/xpath/expressions/token-expr.d.ts +0 -7
  152. package/xpath/expressions/token-expr.js +0 -34
  153. package/xpath/expressions/token-expr.js.map +0 -1
  154. package/xpath/expressions/unary-minus-expr.d.ts +0 -8
  155. package/xpath/expressions/unary-minus-expr.js +0 -34
  156. package/xpath/expressions/unary-minus-expr.js.map +0 -1
  157. package/xpath/expressions/union-expr.d.ts +0 -9
  158. package/xpath/expressions/union-expr.js +0 -51
  159. package/xpath/expressions/union-expr.js.map +0 -1
  160. package/xpath/expressions/variable-expr.d.ts +0 -7
  161. package/xpath/expressions/variable-expr.js +0 -33
  162. package/xpath/expressions/variable-expr.js.map +0 -1
  163. package/xpath/functions/index.d.ts +0 -4
  164. package/xpath/functions/index.js +0 -21
  165. package/xpath/functions/index.js.map +0 -1
  166. package/xpath/functions/internal-functions.d.ts +0 -2
  167. package/xpath/functions/internal-functions.js +0 -22
  168. package/xpath/functions/internal-functions.js.map +0 -1
  169. package/xpath/functions/non-standard.d.ts +0 -12
  170. package/xpath/functions/non-standard.js +0 -45
  171. package/xpath/functions/non-standard.js.map +0 -1
  172. package/xpath/functions/standard-20.d.ts +0 -5
  173. package/xpath/functions/standard-20.js +0 -26
  174. package/xpath/functions/standard-20.js.map +0 -1
  175. package/xpath/functions/standard.d.ts +0 -40
  176. package/xpath/functions/standard.js +0 -442
  177. package/xpath/functions/standard.js.map +0 -1
  178. package/xpath/functions/xslt-specific.d.ts +0 -3
  179. package/xpath/functions/xslt-specific.js +0 -14
  180. package/xpath/functions/xslt-specific.js.map +0 -1
  181. package/xpath/grammar-rule-candidate.d.ts +0 -8
  182. package/xpath/grammar-rule-candidate.js +0 -3
  183. package/xpath/grammar-rule-candidate.js.map +0 -1
  184. package/xpath/index.d.ts +0 -3
  185. package/xpath/index.js +0 -20
  186. package/xpath/index.js.map +0 -1
  187. package/xpath/match-resolver.d.ts +0 -55
  188. package/xpath/match-resolver.js +0 -137
  189. package/xpath/match-resolver.js.map +0 -1
  190. package/xpath/node-tests/index.d.ts +0 -8
  191. package/xpath/node-tests/index.js +0 -18
  192. package/xpath/node-tests/index.js.map +0 -1
  193. package/xpath/node-tests/node-test-any.d.ts +0 -6
  194. package/xpath/node-tests/node-test-any.js +0 -15
  195. package/xpath/node-tests/node-test-any.js.map +0 -1
  196. package/xpath/node-tests/node-test-comment.d.ts +0 -6
  197. package/xpath/node-tests/node-test-comment.js +0 -15
  198. package/xpath/node-tests/node-test-comment.js.map +0 -1
  199. package/xpath/node-tests/node-test-element-or-attribute.d.ts +0 -6
  200. package/xpath/node-tests/node-test-element-or-attribute.js +0 -16
  201. package/xpath/node-tests/node-test-element-or-attribute.js.map +0 -1
  202. package/xpath/node-tests/node-test-name.d.ts +0 -10
  203. package/xpath/node-tests/node-test-name.js +0 -39
  204. package/xpath/node-tests/node-test-name.js.map +0 -1
  205. package/xpath/node-tests/node-test-nc.d.ts +0 -9
  206. package/xpath/node-tests/node-test-nc.js +0 -17
  207. package/xpath/node-tests/node-test-nc.js.map +0 -1
  208. package/xpath/node-tests/node-test-pi.d.ts +0 -8
  209. package/xpath/node-tests/node-test-pi.js +0 -17
  210. package/xpath/node-tests/node-test-pi.js.map +0 -1
  211. package/xpath/node-tests/node-test-text.d.ts +0 -6
  212. package/xpath/node-tests/node-test-text.js +0 -15
  213. package/xpath/node-tests/node-test-text.js.map +0 -1
  214. package/xpath/node-tests/node-test.d.ts +0 -5
  215. package/xpath/node-tests/node-test.js +0 -3
  216. package/xpath/node-tests/node-test.js.map +0 -1
  217. package/xpath/tokens.d.ts +0 -62
  218. package/xpath/tokens.js +0 -301
  219. package/xpath/tokens.js.map +0 -1
  220. package/xpath/values/boolean-value.d.ts +0 -11
  221. package/xpath/values/boolean-value.js +0 -24
  222. package/xpath/values/boolean-value.js.map +0 -1
  223. package/xpath/values/index.d.ts +0 -5
  224. package/xpath/values/index.js +0 -47
  225. package/xpath/values/index.js.map +0 -1
  226. package/xpath/values/node-set-value.d.ts +0 -11
  227. package/xpath/values/node-set-value.js +0 -28
  228. package/xpath/values/node-set-value.js.map +0 -1
  229. package/xpath/values/node-value.d.ts +0 -7
  230. package/xpath/values/node-value.js +0 -3
  231. package/xpath/values/node-value.js.map +0 -1
  232. package/xpath/values/number-value.d.ts +0 -11
  233. package/xpath/values/number-value.js +0 -24
  234. package/xpath/values/number-value.js.map +0 -1
  235. package/xpath/values/string-value.d.ts +0 -11
  236. package/xpath/values/string-value.js +0 -24
  237. package/xpath/values/string-value.js.map +0 -1
  238. package/xpath/xpath-grammar-rules.d.ts +0 -68
  239. package/xpath/xpath-grammar-rules.js +0 -75
  240. package/xpath/xpath-grammar-rules.js.map +0 -1
  241. package/xpath/xpath-token-rule.d.ts +0 -7
  242. package/xpath/xpath-token-rule.js +0 -3
  243. package/xpath/xpath-token-rule.js.map +0 -1
  244. package/xpath/xpath.d.ts +0 -174
  245. package/xpath/xpath.js +0 -912
  246. package/xpath/xpath.js.map +0 -1
  247. package/xpathdebug.d.ts +0 -2
  248. package/xpathdebug.js +0 -188
  249. package/xpathdebug.js.map +0 -1
  250. package/xslt/index.d.ts +0 -3
  251. package/xslt/index.js +0 -20
  252. package/xslt/index.js.map +0 -1
  253. package/xslt/xslt-decimal-format-settings.d.ts +0 -28
  254. package/xslt/xslt-decimal-format-settings.js +0 -3
  255. package/xslt/xslt-decimal-format-settings.js.map +0 -1
  256. package/xslt/xslt-options.d.ts +0 -7
  257. package/xslt/xslt-options.js +0 -3
  258. package/xslt/xslt-options.js.map +0 -1
  259. package/xslt/xslt-parameter.d.ts +0 -5
  260. package/xslt/xslt-parameter.js +0 -3
  261. package/xslt/xslt-parameter.js.map +0 -1
  262. package/xslt/xslt.d.ts +0 -275
  263. package/xslt/xslt.js +0 -1329
  264. package/xslt/xslt.js.map +0 -1
package/index.js CHANGED
@@ -1,13 +1,4468 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExprContext = exports.xmlEscapeText = exports.XmlParser = exports.Xslt = exports.XPath = void 0;
4
- var xpath_1 = require("./xpath");
5
- Object.defineProperty(exports, "XPath", { enumerable: true, get: function () { return xpath_1.XPath; } });
6
- var xslt_1 = require("./xslt");
7
- Object.defineProperty(exports, "Xslt", { enumerable: true, get: function () { return xslt_1.Xslt; } });
8
- var dom_1 = require("./dom");
9
- Object.defineProperty(exports, "XmlParser", { enumerable: true, get: function () { return dom_1.XmlParser; } });
10
- Object.defineProperty(exports, "xmlEscapeText", { enumerable: true, get: function () { return dom_1.xmlEscapeText; } });
11
- var xpath_2 = require("./xpath");
12
- Object.defineProperty(exports, "ExprContext", { enumerable: true, get: function () { return xpath_2.ExprContext; } });
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
+ var __spreadValues = (a, b) => {
13
+ for (var prop in b || (b = {}))
14
+ if (__hasOwnProp.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ if (__getOwnPropSymbols)
17
+ for (var prop of __getOwnPropSymbols(b)) {
18
+ if (__propIsEnum.call(b, prop))
19
+ __defNormalProp(a, prop, b[prop]);
20
+ }
21
+ return a;
22
+ };
23
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
+ var __export = (target, all) => {
25
+ for (var name in all)
26
+ __defProp(target, name, { get: all[name], enumerable: true });
27
+ };
28
+ var __copyProps = (to, from, except, desc) => {
29
+ if (from && typeof from === "object" || typeof from === "function") {
30
+ for (let key of __getOwnPropNames(from))
31
+ if (!__hasOwnProp.call(to, key) && key !== except)
32
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
33
+ }
34
+ return to;
35
+ };
36
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
37
+ // If the importer is in node compatibility mode or this is not an ESM
38
+ // file that has been converted to a CommonJS file using a Babel-
39
+ // compatible transform (i.e. "__esModule" has not been set), then set
40
+ // "default" to the CommonJS "module.exports" for node compatibility.
41
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
42
+ mod
43
+ ));
44
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
45
+ var __async = (__this, __arguments, generator) => {
46
+ return new Promise((resolve, reject) => {
47
+ var fulfilled = (value) => {
48
+ try {
49
+ step(generator.next(value));
50
+ } catch (e) {
51
+ reject(e);
52
+ }
53
+ };
54
+ var rejected = (value) => {
55
+ try {
56
+ step(generator.throw(value));
57
+ } catch (e) {
58
+ reject(e);
59
+ }
60
+ };
61
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
62
+ step((generator = generator.apply(__this, __arguments)).next());
63
+ });
64
+ };
65
+
66
+ // src/index.ts
67
+ var index_exports = {};
68
+ __export(index_exports, {
69
+ ExprContext: () => ExprContext,
70
+ XPath: () => XPath,
71
+ XmlParser: () => XmlParser,
72
+ Xslt: () => Xslt,
73
+ xmlEscapeText: () => xmlEscapeText
74
+ });
75
+ module.exports = __toCommonJS(index_exports);
76
+
77
+ // src/xpath/lib/src/lexer/token.ts
78
+ var XPathToken = class {
79
+ constructor(type, lexeme) {
80
+ this.type = type;
81
+ this.lexeme = lexeme;
82
+ }
83
+ };
84
+
85
+ // src/xpath/lib/src/lexer/lexer.ts
86
+ var RESERVED_WORDS = {
87
+ // Location axes (XPath 1.0 complete list)
88
+ "ancestor": { type: "LOCATION", value: "ancestor" },
89
+ "ancestor-or-self": { type: "LOCATION", value: "ancestor-or-self" },
90
+ "attribute": { type: "LOCATION", value: "attribute" },
91
+ "child": { type: "LOCATION", value: "child" },
92
+ "descendant": { type: "LOCATION", value: "descendant" },
93
+ "descendant-or-self": { type: "LOCATION", value: "descendant-or-self" },
94
+ "following": { type: "LOCATION", value: "following" },
95
+ "following-sibling": { type: "LOCATION", value: "following-sibling" },
96
+ "namespace": { type: "LOCATION", value: "namespace" },
97
+ "parent": { type: "LOCATION", value: "parent" },
98
+ "preceding": { type: "LOCATION", value: "preceding" },
99
+ "preceding-sibling": { type: "LOCATION", value: "preceding-sibling" },
100
+ "self": { type: "LOCATION", value: "self" },
101
+ // Node type tests
102
+ "node": { type: "NODE_TYPE", value: "node" },
103
+ "text": { type: "NODE_TYPE", value: "text" },
104
+ "comment": { type: "NODE_TYPE", value: "comment" },
105
+ "processing-instruction": { type: "NODE_TYPE", value: "processing-instruction" },
106
+ // Operators
107
+ "and": { type: "OPERATOR", value: "and" },
108
+ "or": { type: "OPERATOR", value: "or" },
109
+ "div": { type: "OPERATOR", value: "div" },
110
+ "mod": { type: "OPERATOR", value: "mod" },
111
+ // Node set functions
112
+ "last": { type: "FUNCTION", value: "last" },
113
+ "position": { type: "FUNCTION", value: "position" },
114
+ "count": { type: "FUNCTION", value: "count" },
115
+ "id": { type: "FUNCTION", value: "id" },
116
+ "local-name": { type: "FUNCTION", value: "local-name" },
117
+ "namespace-uri": { type: "FUNCTION", value: "namespace-uri" },
118
+ "name": { type: "FUNCTION", value: "name" },
119
+ // String functions
120
+ "string": { type: "FUNCTION", value: "string" },
121
+ "concat": { type: "FUNCTION", value: "concat" },
122
+ "starts-with": { type: "FUNCTION", value: "starts-with" },
123
+ "contains": { type: "FUNCTION", value: "contains" },
124
+ "substring-before": { type: "FUNCTION", value: "substring-before" },
125
+ "substring-after": { type: "FUNCTION", value: "substring-after" },
126
+ "substring": { type: "FUNCTION", value: "substring" },
127
+ "string-length": { type: "FUNCTION", value: "string-length" },
128
+ "normalize-space": { type: "FUNCTION", value: "normalize-space" },
129
+ "translate": { type: "FUNCTION", value: "translate" },
130
+ // Boolean functions
131
+ "boolean": { type: "FUNCTION", value: "boolean" },
132
+ "not": { type: "FUNCTION", value: "not" },
133
+ "true": { type: "FUNCTION", value: "true" },
134
+ "false": { type: "FUNCTION", value: "false" },
135
+ "lang": { type: "FUNCTION", value: "lang" },
136
+ // Number functions
137
+ "number": { type: "FUNCTION", value: "number" },
138
+ "sum": { type: "FUNCTION", value: "sum" },
139
+ "floor": { type: "FUNCTION", value: "floor" },
140
+ "ceiling": { type: "FUNCTION", value: "ceiling" },
141
+ "round": { type: "FUNCTION", value: "round" },
142
+ // XSLT-specific functions (commonly used)
143
+ "document": { type: "FUNCTION", value: "document" },
144
+ "key": { type: "FUNCTION", value: "key" },
145
+ "format-number": { type: "FUNCTION", value: "format-number" },
146
+ "current": { type: "FUNCTION", value: "current" },
147
+ "unparsed-entity-uri": { type: "FUNCTION", value: "unparsed-entity-uri" },
148
+ "generate-id": { type: "FUNCTION", value: "generate-id" },
149
+ "system-property": { type: "FUNCTION", value: "system-property" },
150
+ "element-available": { type: "FUNCTION", value: "element-available" },
151
+ "function-available": { type: "FUNCTION", value: "function-available" }
152
+ };
153
+ var XPathLexer = class {
154
+ /**
155
+ * Check if character is a valid start of an identifier.
156
+ * Supports Unicode letters according to XML NCName specification.
157
+ */
158
+ isAlpha(char) {
159
+ return /^[a-zA-Z_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]$/.test(char);
160
+ }
161
+ /**
162
+ * Check if character is valid in an identifier (after the first character).
163
+ * Supports Unicode letters and digits according to XML NCName specification.
164
+ * Note: Hyphen is handled separately in parseIdentifier for reserved words.
165
+ */
166
+ isAlphaNumeric(char) {
167
+ return /^[a-zA-Z0-9_\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0300-\u036F\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]$/.test(char);
168
+ }
169
+ isNumber(char) {
170
+ return /^[0-9]$/.test(char);
171
+ }
172
+ isWhitespace(char) {
173
+ return /^[\s\t\n\r]$/.test(char);
174
+ }
175
+ peek() {
176
+ return this.expression[this.current];
177
+ }
178
+ peekNext() {
179
+ return this.expression[this.current + 1];
180
+ }
181
+ next() {
182
+ return this.expression[this.current++];
183
+ }
184
+ match(expected) {
185
+ if (this.current >= this.expression.length) return false;
186
+ if (this.expression[this.current] !== expected) return false;
187
+ this.current++;
188
+ return true;
189
+ }
190
+ parseIdentifier(firstCharacter) {
191
+ let characters = firstCharacter;
192
+ while (this.current < this.expression.length) {
193
+ const char = this.expression[this.current];
194
+ if (this.isAlphaNumeric(char)) {
195
+ characters += this.next();
196
+ } else if (char === "-") {
197
+ const nextChar = this.expression[this.current + 1];
198
+ if (nextChar && this.isAlphaNumeric(nextChar)) {
199
+ this.current++;
200
+ characters += "-";
201
+ while (this.current < this.expression.length && this.isAlphaNumeric(this.expression[this.current])) {
202
+ characters += this.next();
203
+ }
204
+ } else {
205
+ break;
206
+ }
207
+ } else {
208
+ break;
209
+ }
210
+ }
211
+ const likelyReservedWord = RESERVED_WORDS[characters.toLowerCase()];
212
+ if (likelyReservedWord) {
213
+ return new XPathToken(likelyReservedWord.type, characters);
214
+ }
215
+ if (characters.length > 0) {
216
+ return new XPathToken("IDENTIFIER", characters);
217
+ }
218
+ throw new Error(`Invalid identifier: ${characters}`);
219
+ }
220
+ parseString(quoteChar) {
221
+ let value = "";
222
+ while (this.current < this.expression.length && this.expression[this.current] !== quoteChar) {
223
+ value += this.next();
224
+ }
225
+ if (this.current >= this.expression.length) {
226
+ throw new Error(`Unterminated string literal`);
227
+ }
228
+ this.next();
229
+ return new XPathToken("STRING", value);
230
+ }
231
+ parseNumber(firstCharacter) {
232
+ let characters = firstCharacter;
233
+ while (this.current < this.expression.length && this.isNumber(this.expression[this.current]) && this.expression[this.current] !== ".") {
234
+ characters += this.next();
235
+ }
236
+ if (this.current < this.expression.length && this.expression[this.current] === ".") {
237
+ characters += this.next();
238
+ while (this.current < this.expression.length && this.isNumber(this.expression[this.current])) {
239
+ characters += this.next();
240
+ }
241
+ }
242
+ if (characters.length > 0) {
243
+ return new XPathToken("NUMBER", characters);
244
+ }
245
+ throw new Error(`Invalid number: ${characters}`);
246
+ }
247
+ scanToken() {
248
+ const char = this.next();
249
+ if (this.isWhitespace(char)) {
250
+ return null;
251
+ }
252
+ switch (char) {
253
+ case "@":
254
+ return new XPathToken("AT", char);
255
+ case "$":
256
+ return new XPathToken("DOLLAR", char);
257
+ case "|":
258
+ return new XPathToken("PIPE", char);
259
+ case "{":
260
+ return new XPathToken("OPEN_CURLY_BRACKET", char);
261
+ case "}":
262
+ return new XPathToken("CLOSE_CURLY_BRACKET", char);
263
+ case "[":
264
+ return new XPathToken("OPEN_SQUARE_BRACKET", char);
265
+ case "]":
266
+ return new XPathToken("CLOSE_SQUARE_BRACKET", char);
267
+ case "(":
268
+ return new XPathToken("OPEN_PAREN", char);
269
+ case ")":
270
+ return new XPathToken("CLOSE_PAREN", char);
271
+ case "+":
272
+ return new XPathToken("PLUS", char);
273
+ case "-":
274
+ return new XPathToken("MINUS", char);
275
+ case "*":
276
+ return new XPathToken("ASTERISK", char);
277
+ case ",":
278
+ return new XPathToken("COMMA", char);
279
+ // Tokens that may be single or double character
280
+ case ".":
281
+ if (this.match(".")) {
282
+ return new XPathToken("DOT_DOT", "..");
283
+ }
284
+ if (this.peek() && this.isNumber(this.peek())) {
285
+ return this.parseNumber(char);
286
+ }
287
+ return new XPathToken("DOT", char);
288
+ case "/":
289
+ if (this.match("/")) {
290
+ return new XPathToken("DOUBLE_SLASH", "//");
291
+ }
292
+ return new XPathToken("SLASH", char);
293
+ case ":":
294
+ if (this.match(":")) {
295
+ return new XPathToken("COLON_COLON", "::");
296
+ }
297
+ return new XPathToken("COLON", char);
298
+ case "=":
299
+ return new XPathToken("EQUALS", char);
300
+ case "!":
301
+ if (this.match("=")) {
302
+ return new XPathToken("NOT_EQUALS", "!=");
303
+ }
304
+ throw new Error(`Unexpected character: ${char}`);
305
+ case "<":
306
+ if (this.match("=")) {
307
+ return new XPathToken("LESS_THAN_OR_EQUAL", "<=");
308
+ }
309
+ return new XPathToken("LESS_THAN", char);
310
+ case ">":
311
+ if (this.match("=")) {
312
+ return new XPathToken("GREATER_THAN_OR_EQUAL", ">=");
313
+ }
314
+ return new XPathToken("GREATER_THAN", char);
315
+ // String literals
316
+ case "'":
317
+ return this.parseString("'");
318
+ case '"':
319
+ return this.parseString('"');
320
+ default:
321
+ if (this.isNumber(char)) {
322
+ return this.parseNumber(char);
323
+ }
324
+ if (this.isAlpha(char)) {
325
+ return this.parseIdentifier(char);
326
+ }
327
+ throw new Error(`Unexpected character: ${char}`);
328
+ }
329
+ }
330
+ scan(expression) {
331
+ this.expression = expression;
332
+ this.tokens = [];
333
+ this.current = 0;
334
+ while (this.current < this.expression.length) {
335
+ const token = this.scanToken();
336
+ if (token !== null) {
337
+ this.tokens.push(token);
338
+ }
339
+ }
340
+ return this.tokens;
341
+ }
342
+ };
343
+
344
+ // src/xpath/lib/src/expressions/expression.ts
345
+ var XPathExpression = class {
346
+ };
347
+
348
+ // src/xpath/lib/src/expressions/literal-expression.ts
349
+ var XPathStringLiteral = class extends XPathExpression {
350
+ constructor(value) {
351
+ super();
352
+ this.value = value;
353
+ }
354
+ evaluate(_context) {
355
+ return this.value;
356
+ }
357
+ };
358
+ var XPathNumberLiteral = class extends XPathExpression {
359
+ constructor(value) {
360
+ super();
361
+ this.value = value;
362
+ }
363
+ evaluate(_context) {
364
+ return this.value;
365
+ }
366
+ };
367
+
368
+ // src/xpath/lib/src/expressions/variable-reference-expression.ts
369
+ var XPathVariableReference = class extends XPathExpression {
370
+ constructor(name) {
371
+ super();
372
+ this.name = name;
373
+ }
374
+ evaluate(context) {
375
+ if (!context.variables) {
376
+ throw new Error(`Variable $${this.name} is not defined`);
377
+ }
378
+ if (!(this.name in context.variables)) {
379
+ throw new Error(`Variable $${this.name} is not defined`);
380
+ }
381
+ return context.variables[this.name];
382
+ }
383
+ };
384
+
385
+ // src/xpath/lib/src/expressions/unary-expression.ts
386
+ var XPathUnaryExpression = class extends XPathExpression {
387
+ constructor(operator, operand) {
388
+ super();
389
+ this.operator = operator;
390
+ this.operand = operand;
391
+ }
392
+ evaluate(context) {
393
+ const value = this.operand.evaluate(context);
394
+ switch (this.operator) {
395
+ case "-":
396
+ return -Number(value);
397
+ default:
398
+ throw new Error(`Unknown unary operator: ${this.operator}`);
399
+ }
400
+ }
401
+ };
402
+
403
+ // src/xpath/lib/src/expressions/binary-expression.ts
404
+ var XPathBinaryExpression = class extends XPathExpression {
405
+ constructor(left, right, operator) {
406
+ super();
407
+ this.left = left;
408
+ this.right = right;
409
+ this.operator = operator;
410
+ }
411
+ evaluate(context) {
412
+ const leftValue = this.left.evaluate(context);
413
+ const rightValue = this.right.evaluate(context);
414
+ return this.compare(leftValue, rightValue, this.operator);
415
+ }
416
+ /**
417
+ * XPath comparison rules:
418
+ * - If both are node-sets: compare each node in left with each node in right
419
+ * - If one is node-set and other is string: convert node-set to strings and compare
420
+ * - If one is node-set and other is number: convert node-set to numbers and compare
421
+ * - If one is node-set and other is boolean: convert node-set to boolean and compare
422
+ * - Otherwise, convert both to numbers for numeric comparison, or strings for equality
423
+ */
424
+ compare(left, right, operator) {
425
+ const leftIsNodeSet = Array.isArray(left);
426
+ const rightIsNodeSet = Array.isArray(right);
427
+ if (leftIsNodeSet && rightIsNodeSet) {
428
+ return this.compareNodeSets(left, right, operator);
429
+ }
430
+ if (leftIsNodeSet) {
431
+ return this.compareNodeSetToValue(left, right, operator);
432
+ }
433
+ if (rightIsNodeSet) {
434
+ return this.compareValueToNodeSet(left, right, operator);
435
+ }
436
+ return this.comparePrimitives(left, right, operator);
437
+ }
438
+ compareNodeSets(left, right, operator) {
439
+ for (const leftNode of left) {
440
+ const leftStr = this.getStringValue(leftNode);
441
+ for (const rightNode of right) {
442
+ const rightStr = this.getStringValue(rightNode);
443
+ if (this.comparePrimitives(leftStr, rightStr, operator)) {
444
+ return true;
445
+ }
446
+ }
447
+ }
448
+ return false;
449
+ }
450
+ compareNodeSetToValue(nodeSet, value, operator) {
451
+ for (const node of nodeSet) {
452
+ const nodeValue = typeof value === "number" ? Number(this.getStringValue(node)) : this.getStringValue(node);
453
+ if (this.comparePrimitives(nodeValue, value, operator)) {
454
+ return true;
455
+ }
456
+ }
457
+ return false;
458
+ }
459
+ compareValueToNodeSet(value, nodeSet, operator) {
460
+ for (const node of nodeSet) {
461
+ const nodeValue = typeof value === "number" ? Number(this.getStringValue(node)) : this.getStringValue(node);
462
+ if (this.comparePrimitives(value, nodeValue, operator)) {
463
+ return true;
464
+ }
465
+ }
466
+ return false;
467
+ }
468
+ comparePrimitives(left, right, operator) {
469
+ switch (operator) {
470
+ case "=":
471
+ return left == right;
472
+ // Use loose equality for type coercion
473
+ case "!=":
474
+ return left != right;
475
+ case "<":
476
+ return Number(left) < Number(right);
477
+ case ">":
478
+ return Number(left) > Number(right);
479
+ case "<=":
480
+ return Number(left) <= Number(right);
481
+ case ">=":
482
+ return Number(left) >= Number(right);
483
+ default:
484
+ throw new Error(`Unknown operator: ${operator}`);
485
+ }
486
+ }
487
+ getStringValue(node) {
488
+ if (!node) return "";
489
+ if (node.nodeType === 3 || node.nodeType === 2) {
490
+ return node.nodeValue || node.textContent || "";
491
+ }
492
+ if (node.textContent !== void 0) {
493
+ return node.textContent;
494
+ }
495
+ if (node.childNodes) {
496
+ let text = "";
497
+ for (const child of Array.from(node.childNodes)) {
498
+ if (child.nodeType === 3) {
499
+ text += child.nodeValue || "";
500
+ } else if (child.nodeType === 1) {
501
+ text += this.getStringValue(child);
502
+ }
503
+ }
504
+ return text;
505
+ }
506
+ return String(node);
507
+ }
508
+ };
509
+
510
+ // src/xpath/lib/src/expressions/arithmetic-expression.ts
511
+ var XPathArithmeticExpression = class extends XPathExpression {
512
+ constructor(left, right, operator) {
513
+ super();
514
+ this.left = left;
515
+ this.right = right;
516
+ this.operator = operator;
517
+ }
518
+ evaluate(context) {
519
+ const leftValue = Number(this.left.evaluate(context));
520
+ const rightValue = Number(this.right.evaluate(context));
521
+ switch (this.operator) {
522
+ case "+":
523
+ return leftValue + rightValue;
524
+ case "-":
525
+ return leftValue - rightValue;
526
+ case "*":
527
+ return leftValue * rightValue;
528
+ case "div":
529
+ return leftValue / rightValue;
530
+ case "mod":
531
+ return leftValue % rightValue;
532
+ default:
533
+ throw new Error(`Unknown arithmetic operator: ${this.operator}`);
534
+ }
535
+ }
536
+ };
537
+
538
+ // src/xpath/lib/src/expressions/logical-expression.ts
539
+ var XPathLogicalExpression = class extends XPathExpression {
540
+ constructor(left, right, operator) {
541
+ super();
542
+ this.left = left;
543
+ this.right = right;
544
+ this.operator = operator;
545
+ }
546
+ toBoolean(value) {
547
+ if (typeof value === "boolean") {
548
+ return value;
549
+ }
550
+ if (typeof value === "number") {
551
+ return value !== 0 && !isNaN(value);
552
+ }
553
+ if (typeof value === "string") {
554
+ return value.length > 0;
555
+ }
556
+ if (Array.isArray(value)) {
557
+ return value.length > 0;
558
+ }
559
+ return !!value;
560
+ }
561
+ evaluate(context) {
562
+ const leftValue = this.toBoolean(this.left.evaluate(context));
563
+ if (this.operator === "and") {
564
+ if (!leftValue) return false;
565
+ return this.toBoolean(this.right.evaluate(context));
566
+ }
567
+ if (this.operator === "or") {
568
+ if (leftValue) return true;
569
+ return this.toBoolean(this.right.evaluate(context));
570
+ }
571
+ throw new Error(`Unknown logical operator: ${this.operator}`);
572
+ }
573
+ };
574
+
575
+ // src/xpath/lib/src/expressions/step-expression.ts
576
+ var XPathStep = class extends XPathExpression {
577
+ constructor(axis, nodeTest, predicates = []) {
578
+ super();
579
+ this.axis = axis;
580
+ this.nodeTest = nodeTest;
581
+ this.predicates = predicates;
582
+ }
583
+ evaluate(context) {
584
+ const node = context == null ? void 0 : context.node;
585
+ if (!node) return [];
586
+ let candidates = this.getNodesByAxis(node, context);
587
+ candidates = candidates.filter((n) => this.matchesNodeTest(n, context));
588
+ candidates = this.applyPredicates(candidates, context);
589
+ return candidates;
590
+ }
591
+ getNodesByAxis(node, context) {
592
+ switch (this.axis) {
593
+ case "child":
594
+ return this.getChildNodes(node);
595
+ case "parent":
596
+ return node.parentNode ? [node.parentNode] : [];
597
+ case "self":
598
+ return [node];
599
+ case "attribute":
600
+ if (node.attributes) {
601
+ return Array.from(node.attributes);
602
+ }
603
+ return Array.from(node.childNodes || []).filter((n) => n.nodeType === 2);
604
+ case "descendant":
605
+ return this.getDescendants(node, false);
606
+ case "descendant-or-self":
607
+ return this.getDescendants(node, true);
608
+ case "ancestor":
609
+ return this.getAncestors(node, false);
610
+ case "ancestor-or-self":
611
+ return this.getAncestors(node, true);
612
+ case "following-sibling":
613
+ return this.getFollowingSiblings(node);
614
+ case "preceding-sibling":
615
+ return this.getPrecedingSiblings(node);
616
+ case "following":
617
+ return this.getFollowing(node);
618
+ case "preceding":
619
+ return this.getPreceding(node);
620
+ case "namespace":
621
+ return [];
622
+ case "self-and-siblings":
623
+ if (context == null ? void 0 : context.nodeList) {
624
+ return context.nodeList.filter((n) => n.nodeType !== 2);
625
+ }
626
+ return [node];
627
+ default:
628
+ return [];
629
+ }
630
+ }
631
+ /**
632
+ * Get child nodes excluding attribute nodes.
633
+ * XNode stores attributes in childNodes, but XPath child axis doesn't include them.
634
+ */
635
+ getChildNodes(node) {
636
+ const children = Array.from(node.childNodes || []);
637
+ return children.filter((n) => n.nodeType !== 2);
638
+ }
639
+ getDescendants(node, includeSelf) {
640
+ const result = [];
641
+ if (includeSelf) result.push(node);
642
+ const walk = (n) => {
643
+ for (const child of this.getChildNodes(n)) {
644
+ result.push(child);
645
+ walk(child);
646
+ }
647
+ };
648
+ walk(node);
649
+ return result;
650
+ }
651
+ getAncestors(node, includeSelf) {
652
+ const result = [];
653
+ if (includeSelf) result.push(node);
654
+ let current = node.parentNode;
655
+ while (current) {
656
+ result.push(current);
657
+ current = current.parentNode;
658
+ }
659
+ return result;
660
+ }
661
+ getFollowingSiblings(node) {
662
+ const result = [];
663
+ let sibling = node.nextSibling;
664
+ while (sibling) {
665
+ result.push(sibling);
666
+ sibling = sibling.nextSibling;
667
+ }
668
+ return result;
669
+ }
670
+ getPrecedingSiblings(node) {
671
+ const result = [];
672
+ let sibling = node.previousSibling;
673
+ while (sibling) {
674
+ result.unshift(sibling);
675
+ sibling = sibling.previousSibling;
676
+ }
677
+ return result;
678
+ }
679
+ getFollowing(node) {
680
+ const result = [];
681
+ let sibling = node.nextSibling;
682
+ while (sibling) {
683
+ result.push(sibling);
684
+ result.push(...this.getDescendants(sibling, false));
685
+ sibling = sibling.nextSibling;
686
+ }
687
+ let ancestor = node.parentNode;
688
+ while (ancestor) {
689
+ sibling = ancestor.nextSibling;
690
+ while (sibling) {
691
+ result.push(sibling);
692
+ result.push(...this.getDescendants(sibling, false));
693
+ sibling = sibling.nextSibling;
694
+ }
695
+ ancestor = ancestor.parentNode;
696
+ }
697
+ return result;
698
+ }
699
+ getPreceding(node) {
700
+ const result = [];
701
+ let sibling = node.previousSibling;
702
+ while (sibling) {
703
+ result.unshift(sibling);
704
+ const descendants = this.getDescendants(sibling, false);
705
+ result.unshift(...descendants);
706
+ sibling = sibling.previousSibling;
707
+ }
708
+ let ancestor = node.parentNode;
709
+ while (ancestor) {
710
+ sibling = ancestor.previousSibling;
711
+ while (sibling) {
712
+ result.unshift(sibling);
713
+ const descendants = this.getDescendants(sibling, false);
714
+ result.unshift(...descendants);
715
+ sibling = sibling.previousSibling;
716
+ }
717
+ ancestor = ancestor.parentNode;
718
+ }
719
+ return result;
720
+ }
721
+ matchesNodeTest(node, context) {
722
+ var _a, _b;
723
+ const nodeType = node.nodeType;
724
+ switch (this.nodeTest.type) {
725
+ case "wildcard":
726
+ if (this.nodeTest.name && this.nodeTest.name.endsWith(":*")) {
727
+ const prefix = this.nodeTest.name.slice(0, -2);
728
+ const nsUri = (_a = context == null ? void 0 : context.namespaces) == null ? void 0 : _a[prefix];
729
+ if (!nsUri) return false;
730
+ const nodeNsUri = node.namespaceURI || node.namespaceUri || "";
731
+ return (nodeType === 1 || nodeType === 2) && nodeNsUri === nsUri;
732
+ }
733
+ return nodeType === 1 || nodeType === 2;
734
+ case "name":
735
+ if (nodeType !== 1 && nodeType !== 2) return false;
736
+ const testName = this.nodeTest.name;
737
+ const colonIndex = testName.indexOf(":");
738
+ if (colonIndex > 0) {
739
+ const prefix = testName.substring(0, colonIndex);
740
+ const localName = testName.substring(colonIndex + 1);
741
+ const nsUri = (_b = context == null ? void 0 : context.namespaces) == null ? void 0 : _b[prefix];
742
+ if (!nsUri) {
743
+ return false;
744
+ }
745
+ const nodeLocalName = node.localName || node.nodeName;
746
+ const nodeNsUri = node.namespaceURI || node.namespaceUri || "";
747
+ return nodeLocalName === localName && nodeNsUri === nsUri;
748
+ }
749
+ const nodeName = node.localName || node.nodeName;
750
+ return nodeName === testName;
751
+ case "node-type":
752
+ switch (this.nodeTest.nodeType) {
753
+ case "node":
754
+ return true;
755
+ // matches any node
756
+ case "text":
757
+ return nodeType === 3;
758
+ // text node
759
+ case "comment":
760
+ return nodeType === 8;
761
+ // comment node
762
+ case "processing-instruction":
763
+ return nodeType === 7;
764
+ // processing instruction
765
+ default:
766
+ return false;
767
+ }
768
+ case "processing-instruction":
769
+ if (nodeType !== 7) return false;
770
+ if (this.nodeTest.name) {
771
+ return node.target === this.nodeTest.name;
772
+ }
773
+ return true;
774
+ default:
775
+ return false;
776
+ }
777
+ }
778
+ applyPredicates(nodes, context) {
779
+ let result = nodes;
780
+ for (const predicate of this.predicates) {
781
+ const filtered = [];
782
+ const size = result.length;
783
+ for (let i = 0; i < result.length; i++) {
784
+ const predicateContext = __spreadProps(__spreadValues({}, context), {
785
+ node: result[i],
786
+ position: i + 1,
787
+ size
788
+ });
789
+ const predicateResult = predicate.evaluate(predicateContext);
790
+ if (typeof predicateResult === "number") {
791
+ if (predicateResult === i + 1) {
792
+ filtered.push(result[i]);
793
+ }
794
+ } else if (this.toBoolean(predicateResult)) {
795
+ filtered.push(result[i]);
796
+ }
797
+ }
798
+ result = filtered;
799
+ }
800
+ return result;
801
+ }
802
+ toBoolean(value) {
803
+ if (typeof value === "boolean") return value;
804
+ if (typeof value === "number") return value !== 0 && !isNaN(value);
805
+ if (typeof value === "string") return value.length > 0;
806
+ if (Array.isArray(value)) return value.length > 0;
807
+ return !!value;
808
+ }
809
+ };
810
+
811
+ // src/xpath/lib/src/expressions/predicate-expression.ts
812
+ var XPathPredicate = class extends XPathExpression {
813
+ constructor(expression) {
814
+ super();
815
+ this.expression = expression;
816
+ }
817
+ evaluate(context) {
818
+ return this.expression.evaluate(context);
819
+ }
820
+ test(context) {
821
+ const result = this.evaluate(context);
822
+ if (typeof result === "number") {
823
+ return result === (context == null ? void 0 : context.position);
824
+ }
825
+ return this.toBoolean(result);
826
+ }
827
+ toBoolean(value) {
828
+ if (typeof value === "boolean") return value;
829
+ if (typeof value === "number") return value !== 0 && !isNaN(value);
830
+ if (typeof value === "string") return value.length > 0;
831
+ if (Array.isArray(value)) return value.length > 0;
832
+ return !!value;
833
+ }
834
+ };
835
+
836
+ // src/xpath/lib/src/expressions/location-path-expression.ts
837
+ var XPathLocationPath = class extends XPathExpression {
838
+ constructor(steps, absolute = false) {
839
+ super();
840
+ this.steps = steps;
841
+ this.absolute = absolute;
842
+ }
843
+ evaluate(context) {
844
+ let nodes;
845
+ if (this.absolute) {
846
+ const root = this.getDocumentRoot(context == null ? void 0 : context.node);
847
+ nodes = root ? [root] : [];
848
+ } else {
849
+ nodes = (context == null ? void 0 : context.node) ? [context.node] : [];
850
+ }
851
+ for (const step of this.steps) {
852
+ const nextNodes = [];
853
+ for (const node of nodes) {
854
+ const stepContext = __spreadProps(__spreadValues({}, context), { node });
855
+ const result = step.evaluate(stepContext);
856
+ nextNodes.push(...result);
857
+ }
858
+ nodes = this.uniqueNodes(nextNodes);
859
+ }
860
+ return nodes;
861
+ }
862
+ getDocumentRoot(node) {
863
+ if (!node) return null;
864
+ let root = node;
865
+ while (root.parentNode) {
866
+ root = root.parentNode;
867
+ }
868
+ return root;
869
+ }
870
+ uniqueNodes(nodes) {
871
+ const seen = /* @__PURE__ */ new Set();
872
+ const result = [];
873
+ for (const node of nodes) {
874
+ if (!seen.has(node)) {
875
+ seen.add(node);
876
+ result.push(node);
877
+ }
878
+ }
879
+ return result;
880
+ }
881
+ };
882
+
883
+ // src/xpath/lib/src/expressions/filter-expression.ts
884
+ var XPathFilterExpression = class extends XPathExpression {
885
+ constructor(expression, predicate) {
886
+ super();
887
+ this.expression = expression;
888
+ this.predicate = predicate;
889
+ }
890
+ evaluate(context) {
891
+ return [];
892
+ }
893
+ };
894
+
895
+ // src/xpath/lib/src/expressions/union-expression.ts
896
+ var XPathUnionExpression = class extends XPathExpression {
897
+ constructor(left, right) {
898
+ super();
899
+ this.left = left;
900
+ this.right = right;
901
+ }
902
+ evaluate(context) {
903
+ const leftResult = this.left.evaluate(context);
904
+ const rightResult = this.right.evaluate(context);
905
+ const leftNodes = Array.isArray(leftResult) ? leftResult : [];
906
+ const rightNodes = Array.isArray(rightResult) ? rightResult : [];
907
+ return this.unionNodes(leftNodes, rightNodes);
908
+ }
909
+ unionNodes(left, right) {
910
+ const seen = /* @__PURE__ */ new Set();
911
+ const result = [];
912
+ for (const node of left) {
913
+ if (!seen.has(node)) {
914
+ seen.add(node);
915
+ result.push(node);
916
+ }
917
+ }
918
+ for (const node of right) {
919
+ if (!seen.has(node)) {
920
+ seen.add(node);
921
+ result.push(node);
922
+ }
923
+ }
924
+ return this.sortByDocumentOrder(result);
925
+ }
926
+ sortByDocumentOrder(nodes) {
927
+ return nodes.sort((a, b) => {
928
+ if (a === b) return 0;
929
+ if (typeof a.compareDocumentPosition === "function") {
930
+ const position = a.compareDocumentPosition(b);
931
+ if (position & 4) return -1;
932
+ if (position & 2) return 1;
933
+ }
934
+ return 0;
935
+ });
936
+ }
937
+ };
938
+
939
+ // src/xpath/lib/src/expressions/function-call-expression.ts
940
+ var XPathFunctionCall = class extends XPathExpression {
941
+ constructor(name, args) {
942
+ super();
943
+ this.name = name;
944
+ this.args = args;
945
+ }
946
+ evaluate(context) {
947
+ var _a, _b;
948
+ const evaluatedArgs = this.args.map((arg) => arg.evaluate(context));
949
+ switch (this.name) {
950
+ // Node set functions
951
+ case "last":
952
+ return (_a = context.size) != null ? _a : 0;
953
+ case "position":
954
+ return (_b = context.position) != null ? _b : 0;
955
+ case "count":
956
+ return Array.isArray(evaluatedArgs[0]) ? evaluatedArgs[0].length : 0;
957
+ case "local-name":
958
+ return this.localName(evaluatedArgs, context);
959
+ case "namespace-uri":
960
+ return this.namespaceUri(evaluatedArgs, context);
961
+ case "name":
962
+ return this.nodeName(evaluatedArgs, context);
963
+ // String functions
964
+ case "string":
965
+ return this.stringValue(evaluatedArgs, context);
966
+ case "concat":
967
+ return evaluatedArgs.map(String).join("");
968
+ case "starts-with":
969
+ return String(evaluatedArgs[0]).startsWith(String(evaluatedArgs[1]));
970
+ case "contains":
971
+ return String(evaluatedArgs[0]).includes(String(evaluatedArgs[1]));
972
+ case "substring-before":
973
+ return this.substringBefore(evaluatedArgs);
974
+ case "substring-after":
975
+ return this.substringAfter(evaluatedArgs);
976
+ case "substring":
977
+ return this.substring(evaluatedArgs);
978
+ case "string-length":
979
+ return this.stringLength(evaluatedArgs, context);
980
+ case "normalize-space":
981
+ return this.normalizeSpace(evaluatedArgs, context);
982
+ case "translate":
983
+ return this.translate(evaluatedArgs);
984
+ // Boolean functions
985
+ case "boolean":
986
+ return this.toBoolean(evaluatedArgs[0]);
987
+ case "not":
988
+ return !this.toBoolean(evaluatedArgs[0]);
989
+ case "true":
990
+ return true;
991
+ case "false":
992
+ return false;
993
+ case "lang":
994
+ return this.lang(evaluatedArgs, context);
995
+ // Number functions
996
+ case "number":
997
+ return this.toNumber(evaluatedArgs, context);
998
+ case "sum":
999
+ return this.sum(evaluatedArgs);
1000
+ case "floor":
1001
+ return Math.floor(Number(evaluatedArgs[0]));
1002
+ case "ceiling":
1003
+ return Math.ceil(Number(evaluatedArgs[0]));
1004
+ case "round":
1005
+ return Math.round(Number(evaluatedArgs[0]));
1006
+ default:
1007
+ if (context.functions && typeof context.functions[this.name] === "function") {
1008
+ return context.functions[this.name](...evaluatedArgs);
1009
+ }
1010
+ throw new Error(`Unknown function: ${this.name}`);
1011
+ }
1012
+ }
1013
+ toBoolean(value) {
1014
+ if (typeof value === "boolean") return value;
1015
+ if (typeof value === "number") return value !== 0 && !isNaN(value);
1016
+ if (typeof value === "string") return value.length > 0;
1017
+ if (Array.isArray(value)) return value.length > 0;
1018
+ return !!value;
1019
+ }
1020
+ toNumber(args, context) {
1021
+ if (args.length === 0) {
1022
+ return Number(this.stringValue([], context));
1023
+ }
1024
+ return Number(args[0]);
1025
+ }
1026
+ stringValue(args, context) {
1027
+ var _a, _b, _c, _d;
1028
+ if (args.length === 0) {
1029
+ return (_b = (_a = context.node) == null ? void 0 : _a.textContent) != null ? _b : "";
1030
+ }
1031
+ const value = args[0];
1032
+ if (Array.isArray(value) && value.length > 0) {
1033
+ return (_d = (_c = value[0]) == null ? void 0 : _c.textContent) != null ? _d : String(value[0]);
1034
+ }
1035
+ return String(value);
1036
+ }
1037
+ stringLength(args, context) {
1038
+ if (args.length === 0) {
1039
+ return this.stringValue([], context).length;
1040
+ }
1041
+ return String(args[0]).length;
1042
+ }
1043
+ normalizeSpace(args, context) {
1044
+ const str = args.length === 0 ? this.stringValue([], context) : String(args[0]);
1045
+ return str.trim().replace(/\s+/g, " ");
1046
+ }
1047
+ substringBefore(args) {
1048
+ const str = String(args[0]);
1049
+ const search = String(args[1]);
1050
+ const index = str.indexOf(search);
1051
+ return index === -1 ? "" : str.substring(0, index);
1052
+ }
1053
+ substringAfter(args) {
1054
+ const str = String(args[0]);
1055
+ const search = String(args[1]);
1056
+ const index = str.indexOf(search);
1057
+ return index === -1 ? "" : str.substring(index + search.length);
1058
+ }
1059
+ substring(args) {
1060
+ const str = String(args[0]);
1061
+ const start = Math.round(Number(args[1])) - 1;
1062
+ if (args.length === 2) {
1063
+ return str.substring(Math.max(0, start));
1064
+ }
1065
+ const length = Math.round(Number(args[2]));
1066
+ const adjustedStart = Math.max(0, start);
1067
+ const adjustedLength = Math.min(length - (adjustedStart - start), str.length - adjustedStart);
1068
+ return str.substring(adjustedStart, adjustedStart + adjustedLength);
1069
+ }
1070
+ translate(args) {
1071
+ const str = String(args[0]);
1072
+ const from = String(args[1]);
1073
+ const to = String(args[2]);
1074
+ let result = "";
1075
+ for (const char of str) {
1076
+ const index = from.indexOf(char);
1077
+ if (index === -1) {
1078
+ result += char;
1079
+ } else if (index < to.length) {
1080
+ result += to[index];
1081
+ }
1082
+ }
1083
+ return result;
1084
+ }
1085
+ localName(args, context) {
1086
+ var _a;
1087
+ const node = this.getNodeArg(args, context);
1088
+ return (_a = node == null ? void 0 : node.localName) != null ? _a : "";
1089
+ }
1090
+ namespaceUri(args, context) {
1091
+ var _a;
1092
+ const node = this.getNodeArg(args, context);
1093
+ return (_a = node == null ? void 0 : node.namespaceURI) != null ? _a : "";
1094
+ }
1095
+ nodeName(args, context) {
1096
+ var _a;
1097
+ const node = this.getNodeArg(args, context);
1098
+ return (_a = node == null ? void 0 : node.nodeName) != null ? _a : "";
1099
+ }
1100
+ getNodeArg(args, context) {
1101
+ if (args.length > 0 && Array.isArray(args[0]) && args[0].length > 0) {
1102
+ return args[0][0];
1103
+ }
1104
+ return context.node;
1105
+ }
1106
+ sum(args) {
1107
+ const nodeSet = args[0];
1108
+ if (!Array.isArray(nodeSet)) return 0;
1109
+ return nodeSet.reduce((acc, node) => {
1110
+ var _a;
1111
+ const value = Number((_a = node == null ? void 0 : node.textContent) != null ? _a : node);
1112
+ return acc + (isNaN(value) ? 0 : value);
1113
+ }, 0);
1114
+ }
1115
+ lang(args, context) {
1116
+ var _a, _b;
1117
+ const targetLang = String(args[0]).toLowerCase();
1118
+ let node = context.node;
1119
+ while (node) {
1120
+ const lang = ((_a = node.getAttribute) == null ? void 0 : _a.call(node, "xml:lang")) || ((_b = node.getAttribute) == null ? void 0 : _b.call(node, "lang"));
1121
+ if (lang) {
1122
+ const nodeLang = lang.toLowerCase();
1123
+ return nodeLang === targetLang || nodeLang.startsWith(targetLang + "-");
1124
+ }
1125
+ node = node.parentNode;
1126
+ }
1127
+ return false;
1128
+ }
1129
+ };
1130
+
1131
+ // src/xpath/lib/src/parser.ts
1132
+ var XPathParser = class {
1133
+ constructor() {
1134
+ this.tokens = [];
1135
+ this.current = 0;
1136
+ }
1137
+ parse(tokens) {
1138
+ this.tokens = tokens;
1139
+ this.current = 0;
1140
+ if (tokens.length === 0) {
1141
+ throw new Error("Empty expression");
1142
+ }
1143
+ const expr = this.parseExpr();
1144
+ if (!this.isAtEnd()) {
1145
+ throw new Error(`Unexpected token: ${this.peek().lexeme}`);
1146
+ }
1147
+ return expr;
1148
+ }
1149
+ // ==================== Token Management ====================
1150
+ peek() {
1151
+ return this.tokens[this.current];
1152
+ }
1153
+ peekNext() {
1154
+ return this.tokens[this.current + 1];
1155
+ }
1156
+ previous() {
1157
+ return this.tokens[this.current - 1];
1158
+ }
1159
+ isAtEnd() {
1160
+ return this.current >= this.tokens.length;
1161
+ }
1162
+ advance() {
1163
+ if (!this.isAtEnd()) this.current++;
1164
+ return this.previous();
1165
+ }
1166
+ check(type) {
1167
+ if (this.isAtEnd()) return false;
1168
+ return this.peek().type === type;
1169
+ }
1170
+ checkLexeme(lexeme) {
1171
+ if (this.isAtEnd()) return false;
1172
+ return this.peek().lexeme === lexeme;
1173
+ }
1174
+ match(...types) {
1175
+ for (const type of types) {
1176
+ if (this.check(type)) {
1177
+ this.advance();
1178
+ return true;
1179
+ }
1180
+ }
1181
+ return false;
1182
+ }
1183
+ consume(type, message) {
1184
+ var _a, _b;
1185
+ if (this.check(type)) return this.advance();
1186
+ throw new Error(`${message}. Got: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`);
1187
+ }
1188
+ // ==================== Expression Parsing ====================
1189
+ parseExpr() {
1190
+ return this.parseOrExpr();
1191
+ }
1192
+ parseOrExpr() {
1193
+ let left = this.parseAndExpr();
1194
+ while (this.check("OPERATOR") && this.peek().lexeme === "or") {
1195
+ this.advance();
1196
+ const right = this.parseAndExpr();
1197
+ left = new XPathLogicalExpression(left, right, "or");
1198
+ }
1199
+ return left;
1200
+ }
1201
+ parseAndExpr() {
1202
+ let left = this.parseEqualityExpr();
1203
+ while (this.check("OPERATOR") && this.peek().lexeme === "and") {
1204
+ this.advance();
1205
+ const right = this.parseEqualityExpr();
1206
+ left = new XPathLogicalExpression(left, right, "and");
1207
+ }
1208
+ return left;
1209
+ }
1210
+ parseEqualityExpr() {
1211
+ let left = this.parseRelationalExpr();
1212
+ while (this.match("EQUALS", "NOT_EQUALS")) {
1213
+ const operator = this.previous().lexeme;
1214
+ const right = this.parseRelationalExpr();
1215
+ left = new XPathBinaryExpression(left, right, operator);
1216
+ }
1217
+ return left;
1218
+ }
1219
+ parseRelationalExpr() {
1220
+ let left = this.parseAdditiveExpr();
1221
+ while (this.match("LESS_THAN", "GREATER_THAN", "LESS_THAN_OR_EQUAL", "GREATER_THAN_OR_EQUAL")) {
1222
+ const operator = this.previous().lexeme;
1223
+ const right = this.parseAdditiveExpr();
1224
+ left = new XPathBinaryExpression(left, right, operator);
1225
+ }
1226
+ return left;
1227
+ }
1228
+ parseAdditiveExpr() {
1229
+ let left = this.parseMultiplicativeExpr();
1230
+ while (this.match("PLUS", "MINUS")) {
1231
+ const operator = this.previous().lexeme;
1232
+ const right = this.parseMultiplicativeExpr();
1233
+ left = new XPathArithmeticExpression(left, right, operator);
1234
+ }
1235
+ return left;
1236
+ }
1237
+ parseMultiplicativeExpr() {
1238
+ let left = this.parseUnaryExpr();
1239
+ while (true) {
1240
+ if (this.match("ASTERISK")) {
1241
+ const right = this.parseUnaryExpr();
1242
+ left = new XPathArithmeticExpression(left, right, "*");
1243
+ } else if (this.check("OPERATOR") && (this.peek().lexeme === "div" || this.peek().lexeme === "mod")) {
1244
+ const operator = this.advance().lexeme;
1245
+ const right = this.parseUnaryExpr();
1246
+ left = new XPathArithmeticExpression(left, right, operator);
1247
+ } else {
1248
+ break;
1249
+ }
1250
+ }
1251
+ return left;
1252
+ }
1253
+ parseUnaryExpr() {
1254
+ if (this.match("MINUS")) {
1255
+ const operand = this.parseUnaryExpr();
1256
+ return new XPathUnaryExpression("-", operand);
1257
+ }
1258
+ return this.parseUnionExpr();
1259
+ }
1260
+ parseUnionExpr() {
1261
+ let left = this.parsePathExpr();
1262
+ while (this.match("PIPE")) {
1263
+ const right = this.parsePathExpr();
1264
+ left = new XPathUnionExpression(left, right);
1265
+ }
1266
+ return left;
1267
+ }
1268
+ // ==================== Path Expression Parsing ====================
1269
+ parsePathExpr() {
1270
+ if (this.check("SLASH") || this.check("DOUBLE_SLASH")) {
1271
+ return this.parseLocationPath();
1272
+ }
1273
+ if (this.isStepStart()) {
1274
+ return this.parseLocationPath();
1275
+ }
1276
+ const filterExpr = this.parseFilterExpr();
1277
+ if (this.match("SLASH", "DOUBLE_SLASH")) {
1278
+ const isDescendant = this.previous().type === "DOUBLE_SLASH";
1279
+ const steps = this.parseRelativeLocationPath();
1280
+ if (isDescendant) {
1281
+ steps.unshift(new XPathStep("descendant-or-self", { type: "node-type", nodeType: "node" }));
1282
+ }
1283
+ return new XPathFilterExpression(filterExpr, new XPathLocationPath(steps, false));
1284
+ }
1285
+ return filterExpr;
1286
+ }
1287
+ isStepStart() {
1288
+ if (this.isAtEnd()) return false;
1289
+ const token = this.peek();
1290
+ if (token.type === "DOT" || token.type === "DOT_DOT") return true;
1291
+ if (token.type === "AT") return true;
1292
+ if (token.type === "LOCATION") return true;
1293
+ if (token.type === "NODE_TYPE") return true;
1294
+ if (token.type === "ASTERISK") return true;
1295
+ if (token.type === "IDENTIFIER" || token.type === "OPERATOR" || token.type === "FUNCTION") {
1296
+ const next = this.peekNext();
1297
+ return !next || next.type !== "OPEN_PAREN";
1298
+ }
1299
+ return false;
1300
+ }
1301
+ parseLocationPath() {
1302
+ let absolute = false;
1303
+ const steps = [];
1304
+ if (this.match("SLASH")) {
1305
+ absolute = true;
1306
+ if (!this.isAtEnd() && this.isStepStart()) {
1307
+ steps.push(...this.parseRelativeLocationPath());
1308
+ }
1309
+ } else if (this.match("DOUBLE_SLASH")) {
1310
+ absolute = true;
1311
+ steps.push(new XPathStep("descendant-or-self", { type: "node-type", nodeType: "node" }));
1312
+ steps.push(...this.parseRelativeLocationPath());
1313
+ } else {
1314
+ steps.push(...this.parseRelativeLocationPath());
1315
+ }
1316
+ return new XPathLocationPath(steps, absolute);
1317
+ }
1318
+ parseRelativeLocationPath() {
1319
+ const steps = [];
1320
+ steps.push(this.parseStep());
1321
+ while (this.match("SLASH", "DOUBLE_SLASH")) {
1322
+ const isDescendant = this.previous().type === "DOUBLE_SLASH";
1323
+ if (isDescendant) {
1324
+ steps.push(new XPathStep("descendant-or-self", { type: "node-type", nodeType: "node" }));
1325
+ }
1326
+ steps.push(this.parseStep());
1327
+ }
1328
+ return steps;
1329
+ }
1330
+ parseStep() {
1331
+ if (this.match("DOT")) {
1332
+ return new XPathStep("self", { type: "node-type", nodeType: "node" });
1333
+ }
1334
+ if (this.match("DOT_DOT")) {
1335
+ return new XPathStep("parent", { type: "node-type", nodeType: "node" });
1336
+ }
1337
+ let axis = "child";
1338
+ if (this.match("AT")) {
1339
+ axis = "attribute";
1340
+ } else if (this.check("LOCATION")) {
1341
+ const next = this.peekNext();
1342
+ if (next && next.type === "COLON_COLON") {
1343
+ axis = this.advance().lexeme;
1344
+ this.advance();
1345
+ }
1346
+ }
1347
+ const nodeTest = this.parseNodeTest();
1348
+ const predicates = this.parsePredicates();
1349
+ return new XPathStep(axis, nodeTest, predicates);
1350
+ }
1351
+ parseNodeTest() {
1352
+ var _a, _b;
1353
+ if (this.match("ASTERISK")) {
1354
+ return { type: "wildcard" };
1355
+ }
1356
+ if (this.check("NODE_TYPE")) {
1357
+ const next = this.peekNext();
1358
+ if (next && next.type === "OPEN_PAREN") {
1359
+ const nodeType = this.advance().lexeme;
1360
+ this.advance();
1361
+ if (nodeType === "processing-instruction" && this.check("STRING")) {
1362
+ const name = this.advance().lexeme;
1363
+ this.consume("CLOSE_PAREN", "Expected ')' after processing-instruction name");
1364
+ return { type: "processing-instruction", name };
1365
+ }
1366
+ this.consume("CLOSE_PAREN", "Expected ')' after node type");
1367
+ return { type: "node-type", nodeType };
1368
+ }
1369
+ }
1370
+ if (this.check("IDENTIFIER") || this.check("LOCATION") || this.check("FUNCTION") || this.check("NODE_TYPE") || this.check("OPERATOR")) {
1371
+ const name = this.advance().lexeme;
1372
+ if (this.match("COLON")) {
1373
+ if (this.match("ASTERISK")) {
1374
+ return { type: "wildcard", name: `${name}:*` };
1375
+ }
1376
+ if (this.check("IDENTIFIER") || this.check("LOCATION") || this.check("FUNCTION") || this.check("NODE_TYPE") || this.check("OPERATOR")) {
1377
+ const localName = this.advance().lexeme;
1378
+ return { type: "name", name: `${name}:${localName}` };
1379
+ }
1380
+ throw new Error("Expected local name after namespace prefix");
1381
+ }
1382
+ return { type: "name", name };
1383
+ }
1384
+ throw new Error(`Expected node test, got: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`);
1385
+ }
1386
+ parsePredicates() {
1387
+ const predicates = [];
1388
+ while (this.match("OPEN_SQUARE_BRACKET")) {
1389
+ const expr = this.parseExpr();
1390
+ this.consume("CLOSE_SQUARE_BRACKET", "Expected ']' after predicate");
1391
+ predicates.push(new XPathPredicate(expr));
1392
+ }
1393
+ return predicates;
1394
+ }
1395
+ // ==================== Filter Expression Parsing ====================
1396
+ parseFilterExpr() {
1397
+ let expr = this.parsePrimaryExpr();
1398
+ while (this.check("OPEN_SQUARE_BRACKET")) {
1399
+ const predicates = this.parsePredicates();
1400
+ for (const predicate of predicates) {
1401
+ expr = new XPathFilterExpression(expr, predicate);
1402
+ }
1403
+ }
1404
+ return expr;
1405
+ }
1406
+ parsePrimaryExpr() {
1407
+ var _a, _b;
1408
+ if (this.match("DOLLAR")) {
1409
+ const name = this.consume("IDENTIFIER", "Expected variable name after $").lexeme;
1410
+ return new XPathVariableReference(name);
1411
+ }
1412
+ if (this.match("OPEN_PAREN")) {
1413
+ const expr = this.parseExpr();
1414
+ this.consume("CLOSE_PAREN", "Expected ')' after expression");
1415
+ return expr;
1416
+ }
1417
+ if (this.check("STRING")) {
1418
+ const value = this.advance().lexeme;
1419
+ return new XPathStringLiteral(value);
1420
+ }
1421
+ if (this.check("NUMBER")) {
1422
+ const value = parseFloat(this.advance().lexeme);
1423
+ return new XPathNumberLiteral(value);
1424
+ }
1425
+ if (this.check("FUNCTION") || this.check("IDENTIFIER")) {
1426
+ const next = this.peekNext();
1427
+ if (next && next.type === "OPEN_PAREN") {
1428
+ return this.parseFunctionCall();
1429
+ }
1430
+ }
1431
+ throw new Error(`Unexpected token in primary expression: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`);
1432
+ }
1433
+ parseFunctionCall() {
1434
+ const name = this.advance().lexeme;
1435
+ this.consume("OPEN_PAREN", "Expected '(' after function name");
1436
+ const args = [];
1437
+ if (!this.check("CLOSE_PAREN")) {
1438
+ do {
1439
+ args.push(this.parseExpr());
1440
+ } while (this.match("COMMA"));
1441
+ }
1442
+ this.consume("CLOSE_PAREN", "Expected ')' after function arguments");
1443
+ return new XPathFunctionCall(name, args);
1444
+ }
1445
+ };
1446
+
1447
+ // src/xpath/lib/src/context.ts
1448
+ function createContext(node, options) {
1449
+ return __spreadValues({
1450
+ node,
1451
+ position: 1,
1452
+ size: 1
1453
+ }, options);
1454
+ }
1455
+
1456
+ // src/xpath/values/string-value.ts
1457
+ var StringValue = class {
1458
+ constructor(value) {
1459
+ this.value = value;
1460
+ this.type = "string";
1461
+ }
1462
+ stringValue() {
1463
+ return String(this.value);
1464
+ }
1465
+ booleanValue() {
1466
+ return this.value.length > 0;
1467
+ }
1468
+ numberValue() {
1469
+ return this.value - 0;
1470
+ }
1471
+ nodeSetValue() {
1472
+ throw this;
1473
+ }
1474
+ };
1475
+
1476
+ // src/xpath/values/number-value.ts
1477
+ var NumberValue = class {
1478
+ constructor(value) {
1479
+ this.value = value;
1480
+ this.type = "number";
1481
+ }
1482
+ stringValue() {
1483
+ return `${this.value}`;
1484
+ }
1485
+ booleanValue() {
1486
+ return !!this.value;
1487
+ }
1488
+ numberValue() {
1489
+ return this.value - 0;
1490
+ }
1491
+ nodeSetValue() {
1492
+ throw this;
1493
+ }
1494
+ };
1495
+
1496
+ // src/xpath/values/boolean-value.ts
1497
+ var BooleanValue = class {
1498
+ constructor(value) {
1499
+ this.value = value;
1500
+ this.type = "boolean";
1501
+ }
1502
+ stringValue() {
1503
+ return `${this.value}`;
1504
+ }
1505
+ booleanValue() {
1506
+ return this.value;
1507
+ }
1508
+ numberValue() {
1509
+ return this.value ? 1 : 0;
1510
+ }
1511
+ nodeSetValue() {
1512
+ throw this;
1513
+ }
1514
+ };
1515
+
1516
+ // src/dom/functions.ts
1517
+ function domGetAttributeValue(node, name) {
1518
+ return node.getAttributeValue(name);
1519
+ }
1520
+ function domSetAttribute(node, name, value) {
1521
+ return node.setAttribute(name, value);
1522
+ }
1523
+ function domAppendChild(node, child) {
1524
+ return node.appendChild(child);
1525
+ }
1526
+ function domCreateTextNode(node, text) {
1527
+ return node.createTextNode(text);
1528
+ }
1529
+ function domCreateElement(doc, name) {
1530
+ return doc.createElement(name);
1531
+ }
1532
+ function domCreateCDATASection(doc, data) {
1533
+ return doc.createCDATASection(data);
1534
+ }
1535
+ function domCreateComment(doc, text) {
1536
+ return doc.createComment(text);
1537
+ }
1538
+ function domCreateDocumentFragment(doc) {
1539
+ return doc.createDocumentFragment();
1540
+ }
1541
+ function domCreateDTDSection(doc, data) {
1542
+ return doc.createDTDSection(data);
1543
+ }
1544
+
1545
+ // src/constants.ts
1546
+ var DOM_ELEMENT_NODE = 1;
1547
+ var DOM_ATTRIBUTE_NODE = 2;
1548
+ var DOM_TEXT_NODE = 3;
1549
+ var DOM_CDATA_SECTION_NODE = 4;
1550
+ var DOM_PROCESSING_INSTRUCTION_NODE = 7;
1551
+ var DOM_COMMENT_NODE = 8;
1552
+ var DOM_DOCUMENT_NODE = 9;
1553
+ var DOM_DOCUMENT_TYPE_NODE = 10;
1554
+ var DOM_DOCUMENT_FRAGMENT_NODE = 11;
1555
+
1556
+ // src/dom/xnode.ts
1557
+ var _XNode = class _XNode {
1558
+ constructor(type, name, opt_value, opt_owner, opt_namespace) {
1559
+ this.id = Math.random() * (Number.MAX_SAFE_INTEGER - 1) + 1;
1560
+ this.childNodes = [];
1561
+ this.visited = false;
1562
+ this.escape = true;
1563
+ this.siblingPosition = -1;
1564
+ this.init(type, name, opt_value, opt_owner, opt_namespace);
1565
+ }
1566
+ /**
1567
+ * Node initialization. Called by the constructor and `recycle` method.
1568
+ * @param type The node type.
1569
+ * @param name The node name.
1570
+ * @param value The node value.
1571
+ * @param owner The node owner.
1572
+ * @param namespaceUri The node namespace.
1573
+ */
1574
+ init(type, name, value, owner, namespaceUri) {
1575
+ this.nodeType = type - 0;
1576
+ this.nodeName = `${name}`;
1577
+ this.nodeValue = `${value}`;
1578
+ this.ownerDocument = owner;
1579
+ this.namespaceUri = namespaceUri || null;
1580
+ [this.prefix, this.localName] = this.qualifiedNameToParts(`${name}`);
1581
+ this.firstChild = null;
1582
+ this.lastChild = null;
1583
+ this.nextSibling = null;
1584
+ this.previousSibling = null;
1585
+ this.parentNode = null;
1586
+ }
1587
+ qualifiedNameToParts(name) {
1588
+ if (name.includes(":")) {
1589
+ return name.split(":");
1590
+ }
1591
+ return [null, name];
1592
+ }
1593
+ // Traverses the element nodes in the DOM section underneath the given
1594
+ // node and invokes the given callbacks as methods on every element
1595
+ // node encountered. Function opt_pre is invoked before a node's
1596
+ // children are traversed; opt_post is invoked after they are
1597
+ // traversed. Traversal will not be continued if a callback function
1598
+ // returns boolean false. NOTE(mesch): copied from
1599
+ // <//google3/maps/webmaps/javascript/dom.js>.
1600
+ domTraverseElements(node, opt_pre, opt_post) {
1601
+ let ret;
1602
+ if (opt_pre) {
1603
+ ret = opt_pre.call(null, node);
1604
+ if (typeof ret == "boolean" && !ret) {
1605
+ return false;
1606
+ }
1607
+ }
1608
+ for (let c = node.firstChild; c; c = c.nextSibling) {
1609
+ if (c.nodeType == DOM_ELEMENT_NODE) {
1610
+ ret = this.domTraverseElements.call(this, c, opt_pre, opt_post);
1611
+ if (typeof ret == "boolean" && !ret) {
1612
+ return false;
1613
+ }
1614
+ }
1615
+ }
1616
+ if (opt_post) {
1617
+ ret = opt_post.call(null, node);
1618
+ if (typeof ret == "boolean" && !ret) {
1619
+ return false;
1620
+ }
1621
+ }
1622
+ }
1623
+ // TODO: Do we still need this?
1624
+ static recycle(node) {
1625
+ if (!node) {
1626
+ return;
1627
+ }
1628
+ if (node.constructor.name === "XDocument") {
1629
+ this.recycle(node.documentElement);
1630
+ return;
1631
+ }
1632
+ if (node.constructor != this) {
1633
+ return;
1634
+ }
1635
+ this._unusedXNodes.push(node);
1636
+ for (let c = 0; c < node.childNodes.length; ++c) {
1637
+ this.recycle(node.childNodes[c]);
1638
+ }
1639
+ node.childNodes.length = 0;
1640
+ node.init.call(0, "", "", null);
1641
+ }
1642
+ static create(type, name, value, owner, namespace) {
1643
+ if (this._unusedXNodes.length > 0) {
1644
+ const node = this._unusedXNodes.pop();
1645
+ node.init(type, name, value, owner, namespace);
1646
+ return node;
1647
+ }
1648
+ return new _XNode(type, name, value, owner, namespace);
1649
+ }
1650
+ static clone(node, newOwner) {
1651
+ const newNode = new _XNode(node.nodeType, node.nodeName, node.nodeValue, newOwner, node.namespaceUri);
1652
+ newNode.id = node.id;
1653
+ for (let child of node.childNodes) {
1654
+ newNode.appendChild(_XNode.clone(child, newNode));
1655
+ }
1656
+ return newNode;
1657
+ }
1658
+ appendChild(node) {
1659
+ if (this.childNodes.length === 0) {
1660
+ this.firstChild = node;
1661
+ }
1662
+ node.previousSibling = this.lastChild;
1663
+ node.nextSibling = null;
1664
+ if (this.lastChild) {
1665
+ this.lastChild.nextSibling = node;
1666
+ }
1667
+ node.parentNode = this;
1668
+ this.lastChild = node;
1669
+ this.childNodes.push(node);
1670
+ }
1671
+ replaceChild(newNode, oldNode) {
1672
+ if (oldNode == newNode) {
1673
+ return;
1674
+ }
1675
+ for (let i = 0; i < this.childNodes.length; ++i) {
1676
+ if (this.childNodes[i] == oldNode) {
1677
+ this.childNodes[i] = newNode;
1678
+ let p = oldNode.parentNode;
1679
+ oldNode.parentNode = null;
1680
+ newNode.parentNode = p;
1681
+ p = oldNode.previousSibling;
1682
+ oldNode.previousSibling = null;
1683
+ newNode.previousSibling = p;
1684
+ if (newNode.previousSibling) {
1685
+ newNode.previousSibling.nextSibling = newNode;
1686
+ }
1687
+ p = oldNode.nextSibling;
1688
+ oldNode.nextSibling = null;
1689
+ newNode.nextSibling = p;
1690
+ if (newNode.nextSibling) {
1691
+ newNode.nextSibling.previousSibling = newNode;
1692
+ }
1693
+ if (this.firstChild == oldNode) {
1694
+ this.firstChild = newNode;
1695
+ }
1696
+ if (this.lastChild == oldNode) {
1697
+ this.lastChild = newNode;
1698
+ }
1699
+ break;
1700
+ }
1701
+ }
1702
+ }
1703
+ insertBefore(newNode, oldNode) {
1704
+ if (oldNode == newNode) {
1705
+ return;
1706
+ }
1707
+ if (oldNode.parentNode != this) {
1708
+ return;
1709
+ }
1710
+ if (newNode.parentNode) {
1711
+ newNode.parentNode.removeChild(newNode);
1712
+ }
1713
+ const newChildren = [];
1714
+ for (const c of this.childNodes) {
1715
+ if (c == oldNode) {
1716
+ newChildren.push(newNode);
1717
+ newNode.parentNode = this;
1718
+ newNode.previousSibling = oldNode.previousSibling;
1719
+ oldNode.previousSibling = newNode;
1720
+ if (newNode.previousSibling) {
1721
+ newNode.previousSibling.nextSibling = newNode;
1722
+ }
1723
+ newNode.nextSibling = oldNode;
1724
+ if (this.firstChild == oldNode) {
1725
+ this.firstChild = newNode;
1726
+ }
1727
+ }
1728
+ newChildren.push(c);
1729
+ }
1730
+ this.childNodes = newChildren;
1731
+ }
1732
+ removeChild(node) {
1733
+ const newChildren = [];
1734
+ for (const c of this.childNodes) {
1735
+ if (c != node) {
1736
+ newChildren.push(c);
1737
+ } else {
1738
+ if (c.previousSibling) {
1739
+ c.previousSibling.nextSibling = c.nextSibling;
1740
+ }
1741
+ if (c.nextSibling) {
1742
+ c.nextSibling.previousSibling = c.previousSibling;
1743
+ }
1744
+ if (this.firstChild == c) {
1745
+ this.firstChild = c.nextSibling;
1746
+ }
1747
+ if (this.lastChild == c) {
1748
+ this.lastChild = c.previousSibling;
1749
+ }
1750
+ }
1751
+ }
1752
+ this.childNodes = newChildren;
1753
+ }
1754
+ hasAttributes() {
1755
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1756
+ return attributes.length > 0;
1757
+ }
1758
+ setAttribute(name, value) {
1759
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1760
+ for (let i = 0; i < attributes.length; ++i) {
1761
+ if (attributes[i].nodeName == name) {
1762
+ attributes[i].nodeValue = `${value}`;
1763
+ return;
1764
+ }
1765
+ }
1766
+ const newAttribute = _XNode.create(DOM_ATTRIBUTE_NODE, name, value, this);
1767
+ newAttribute.parentNode = this;
1768
+ this.appendChild(newAttribute);
1769
+ }
1770
+ setAttributeNS(namespace, name, value) {
1771
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1772
+ for (let i = 0; i < attributes.length; ++i) {
1773
+ const attribute = attributes[i];
1774
+ if (attribute.namespaceUri == namespace && attribute.localName == this.qualifiedNameToParts(`${name}`)[1]) {
1775
+ attribute.nodeValue = `${value}`;
1776
+ attribute.nodeName = `${name}`;
1777
+ attribute.prefix = this.qualifiedNameToParts(`${name}`)[0];
1778
+ return;
1779
+ }
1780
+ }
1781
+ const newAttribute = _XNode.create(DOM_ATTRIBUTE_NODE, name, value, this, namespace);
1782
+ newAttribute.parentNode = this;
1783
+ this.appendChild(newAttribute);
1784
+ }
1785
+ getAttributeValue(name) {
1786
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1787
+ for (let i = 0; i < attributes.length; ++i) {
1788
+ if (attributes[i].nodeName === name) {
1789
+ return attributes[i].nodeValue;
1790
+ }
1791
+ }
1792
+ return null;
1793
+ }
1794
+ getAttributeNS(namespace, localName) {
1795
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1796
+ for (let i = 0; i < attributes.length; ++i) {
1797
+ const attribute = attributes[i];
1798
+ if (attribute.namespaceUri === namespace && attribute.localName === localName) {
1799
+ return attribute.nodeValue;
1800
+ }
1801
+ }
1802
+ return null;
1803
+ }
1804
+ hasAttribute(name) {
1805
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1806
+ for (let i = 0; i < attributes.length; ++i) {
1807
+ if (attributes[i].nodeName === name) {
1808
+ return true;
1809
+ }
1810
+ }
1811
+ return false;
1812
+ }
1813
+ hasAttributeNS(namespace, localName) {
1814
+ const attributes = this.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
1815
+ for (let i = 0; i < attributes.length; ++i) {
1816
+ const attribute = attributes[i];
1817
+ if (attribute.namespaceUri === namespace && attribute.localName === localName) {
1818
+ return true;
1819
+ }
1820
+ }
1821
+ return false;
1822
+ }
1823
+ removeAttribute(name) {
1824
+ const newChildNodes = [];
1825
+ for (let i = 0; i < this.childNodes.length; ++i) {
1826
+ const childNode = this.childNodes[i];
1827
+ if (childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
1828
+ newChildNodes.push(childNode);
1829
+ continue;
1830
+ }
1831
+ if (childNode.nodeName !== name) {
1832
+ newChildNodes.push(childNode);
1833
+ }
1834
+ }
1835
+ this.childNodes = newChildNodes;
1836
+ }
1837
+ removeAttributeNS(namespace, localName) {
1838
+ const newChildNodes = [];
1839
+ for (let i = 0; i < this.childNodes.length; ++i) {
1840
+ const childNode = this.childNodes[i];
1841
+ if (childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
1842
+ newChildNodes.push(childNode);
1843
+ continue;
1844
+ }
1845
+ if (childNode.localName !== localName || childNode.namespaceUri !== namespace) {
1846
+ newChildNodes.push(childNode);
1847
+ }
1848
+ }
1849
+ this.childNodes = newChildNodes;
1850
+ }
1851
+ getElementsByTagName(name) {
1852
+ const ret = [];
1853
+ const self = this;
1854
+ if ("*" == name) {
1855
+ this.domTraverseElements(
1856
+ this,
1857
+ (node) => {
1858
+ if (self == node) return;
1859
+ ret.push(node);
1860
+ },
1861
+ null
1862
+ );
1863
+ } else {
1864
+ this.domTraverseElements(
1865
+ this,
1866
+ (node) => {
1867
+ if (self == node) return;
1868
+ if (node.nodeName == name) {
1869
+ ret.push(node);
1870
+ }
1871
+ },
1872
+ null
1873
+ );
1874
+ }
1875
+ return ret;
1876
+ }
1877
+ getElementsByTagNameNS(namespace, localName) {
1878
+ const ret = [];
1879
+ const self = this;
1880
+ if ("*" == namespace && "*" == localName) {
1881
+ this.domTraverseElements(
1882
+ this,
1883
+ (node) => {
1884
+ if (self == node) return;
1885
+ ret.push(node);
1886
+ },
1887
+ null
1888
+ );
1889
+ } else if ("*" == namespace) {
1890
+ this.domTraverseElements(
1891
+ this,
1892
+ (node) => {
1893
+ if (self == node) return;
1894
+ if (node.localName == localName) ret.push(node);
1895
+ },
1896
+ null
1897
+ );
1898
+ } else if ("*" == localName) {
1899
+ this.domTraverseElements(
1900
+ this,
1901
+ (node) => {
1902
+ if (self == node) return;
1903
+ if (node.namespaceUri == namespace) ret.push(node);
1904
+ },
1905
+ null
1906
+ );
1907
+ } else {
1908
+ this.domTraverseElements(
1909
+ this,
1910
+ (node) => {
1911
+ if (self == node) return;
1912
+ if (node.localName == localName && node.namespaceUri == namespace) {
1913
+ ret.push(node);
1914
+ }
1915
+ },
1916
+ null
1917
+ );
1918
+ }
1919
+ return ret;
1920
+ }
1921
+ getElementById(id) {
1922
+ let ret = null;
1923
+ this.domTraverseElements(
1924
+ this,
1925
+ (node) => {
1926
+ if (node.getAttributeValue("id") == id) {
1927
+ ret = node;
1928
+ return false;
1929
+ }
1930
+ },
1931
+ null
1932
+ );
1933
+ return ret;
1934
+ }
1935
+ getAncestorByLocalName(localName) {
1936
+ if (this.parentNode === null || this.parentNode === void 0) {
1937
+ return void 0;
1938
+ }
1939
+ if (this.parentNode.localName === localName) {
1940
+ return this.parentNode;
1941
+ }
1942
+ return this.parentNode.getAncestorByLocalName(localName);
1943
+ }
1944
+ getAncestorById(id) {
1945
+ if (this.parentNode === null || this.parentNode === void 0) {
1946
+ return void 0;
1947
+ }
1948
+ if (this.parentNode.id === id) {
1949
+ return this.parentNode;
1950
+ }
1951
+ return this.parentNode.getAncestorById(id);
1952
+ }
1953
+ toString() {
1954
+ return `${this.nodeType}, ${this.nodeName}, ${this.nodeValue}`;
1955
+ }
1956
+ };
1957
+ _XNode._unusedXNodes = [];
1958
+ var XNode = _XNode;
1959
+
1960
+ // src/dom/xdocument.ts
1961
+ var XDocument = class extends XNode {
1962
+ constructor() {
1963
+ super(DOM_DOCUMENT_NODE, "#document", null, null);
1964
+ this.documentElement = null;
1965
+ }
1966
+ // TODO: Do we still need this?
1967
+ /* clear() {
1968
+ XNode.recycle(this.documentElement);
1969
+ this.documentElement = null;
1970
+ } */
1971
+ appendChild(node) {
1972
+ super.appendChild(node);
1973
+ this.documentElement = this.childNodes[0];
1974
+ }
1975
+ createElement(name) {
1976
+ return XNode.create(DOM_ELEMENT_NODE, name, null, this);
1977
+ }
1978
+ createElementNS(namespace, name) {
1979
+ return XNode.create(DOM_ELEMENT_NODE, name, null, this, namespace);
1980
+ }
1981
+ createDocumentFragment() {
1982
+ return XNode.create(DOM_DOCUMENT_FRAGMENT_NODE, "#document-fragment", null, this);
1983
+ }
1984
+ createTextNode(value) {
1985
+ return XNode.create(DOM_TEXT_NODE, "#text", value, this);
1986
+ }
1987
+ createAttribute(name) {
1988
+ return XNode.create(DOM_ATTRIBUTE_NODE, name, null, this);
1989
+ }
1990
+ createAttributeNS(namespace, name) {
1991
+ return XNode.create(DOM_ATTRIBUTE_NODE, name, null, this, namespace);
1992
+ }
1993
+ createComment(data) {
1994
+ return XNode.create(DOM_COMMENT_NODE, "#comment", data, this);
1995
+ }
1996
+ createCDATASection(data) {
1997
+ return XNode.create(DOM_CDATA_SECTION_NODE, "#cdata-section", data, this);
1998
+ }
1999
+ createDTDSection(data) {
2000
+ return XNode.create(DOM_DOCUMENT_TYPE_NODE, "#dtd-section", data, this);
2001
+ }
2002
+ };
2003
+
2004
+ // src/dom/xml-functions.ts
2005
+ var import_he = __toESM(require("he"));
2006
+ function xmlValue(node, disallowBrowserSpecificOptimization = false) {
2007
+ if (!node) {
2008
+ return "";
2009
+ }
2010
+ let ret = "";
2011
+ switch (node.nodeType) {
2012
+ case DOM_DOCUMENT_TYPE_NODE:
2013
+ return `<!DOCTYPE ${node.nodeValue}>`;
2014
+ case DOM_TEXT_NODE:
2015
+ case DOM_CDATA_SECTION_NODE:
2016
+ case DOM_ATTRIBUTE_NODE:
2017
+ return node.nodeValue;
2018
+ case DOM_ELEMENT_NODE:
2019
+ case DOM_DOCUMENT_NODE:
2020
+ case DOM_DOCUMENT_FRAGMENT_NODE:
2021
+ if (!disallowBrowserSpecificOptimization) {
2022
+ const browserNode = node;
2023
+ const innerText = browserNode.innerText;
2024
+ if (innerText !== void 0) {
2025
+ return innerText;
2026
+ }
2027
+ const textContent = browserNode.textContent;
2028
+ if (textContent !== void 0) {
2029
+ return textContent;
2030
+ }
2031
+ }
2032
+ const textNodes = node.childNodes.filter((n) => n.nodeType !== DOM_ATTRIBUTE_NODE);
2033
+ for (let i = 0; i < textNodes.length; ++i) {
2034
+ ret += xmlValue(textNodes[i]);
2035
+ }
2036
+ return ret;
2037
+ }
2038
+ }
2039
+ function xmlValueLegacyBehavior(node, disallowBrowserSpecificOptimization = false) {
2040
+ if (!node) {
2041
+ return "";
2042
+ }
2043
+ let returnedXmlString = "";
2044
+ switch (node.nodeType) {
2045
+ case DOM_ATTRIBUTE_NODE:
2046
+ case DOM_TEXT_NODE:
2047
+ returnedXmlString += node.nodeValue;
2048
+ break;
2049
+ case DOM_CDATA_SECTION_NODE:
2050
+ returnedXmlString += node.nodeValue;
2051
+ break;
2052
+ case DOM_DOCUMENT_NODE:
2053
+ case DOM_DOCUMENT_FRAGMENT_NODE:
2054
+ case DOM_ELEMENT_NODE:
2055
+ if (!disallowBrowserSpecificOptimization) {
2056
+ const browserNode = node;
2057
+ const innerText = browserNode.innerText;
2058
+ if (innerText !== void 0) {
2059
+ return innerText;
2060
+ }
2061
+ const textContent = browserNode.textContent;
2062
+ if (textContent !== void 0) {
2063
+ return textContent;
2064
+ }
2065
+ }
2066
+ const len = node.childNodes.length;
2067
+ for (let i = 0; i < len; ++i) {
2068
+ returnedXmlString += xmlValue(node.childNodes[i]);
2069
+ }
2070
+ break;
2071
+ }
2072
+ return returnedXmlString;
2073
+ }
2074
+ function xmlTransformedText(node, options = {
2075
+ cData: true,
2076
+ escape: true,
2077
+ selfClosingTags: true,
2078
+ outputMethod: "xml"
2079
+ }) {
2080
+ const buffer = [];
2081
+ xmlTransformedTextRecursive(node, buffer, options);
2082
+ return buffer.join("");
2083
+ }
2084
+ function xmlTransformedTextRecursive(node, buffer, options) {
2085
+ if (node.visited) return;
2086
+ const nodeType = node.nodeType;
2087
+ const nodeValue = node.nodeValue;
2088
+ if (nodeType === DOM_TEXT_NODE) {
2089
+ if (node.nodeValue && node.nodeValue.trim() !== "") {
2090
+ const finalText = node.escape && options.escape ? xmlEscapeText(node.nodeValue) : xmlUnescapeText(node.nodeValue);
2091
+ buffer.push(finalText);
2092
+ }
2093
+ } else if (nodeType === DOM_CDATA_SECTION_NODE) {
2094
+ if (options.cData) {
2095
+ buffer.push(xmlEscapeText(nodeValue));
2096
+ } else {
2097
+ buffer.push(`<![CDATA[${nodeValue}]]>`);
2098
+ }
2099
+ } else if (nodeType == DOM_COMMENT_NODE) {
2100
+ buffer.push(`<!-- ${nodeValue} -->`);
2101
+ } else if (nodeType == DOM_ELEMENT_NODE) {
2102
+ if (node.nodeName !== null && node.nodeName !== void 0) {
2103
+ xmlElementLogicTrivial(node, buffer, options);
2104
+ } else {
2105
+ xmlElementLogicMuted(node, buffer, options);
2106
+ }
2107
+ } else if (nodeType === DOM_DOCUMENT_NODE || nodeType === DOM_DOCUMENT_FRAGMENT_NODE) {
2108
+ let childNodes = node.firstChild ? [] : node.childNodes;
2109
+ if (node.firstChild) {
2110
+ let child = node.firstChild;
2111
+ while (child) {
2112
+ childNodes.push(child);
2113
+ child = child.nextSibling;
2114
+ }
2115
+ }
2116
+ childNodes.sort((a, b) => a.siblingPosition - b.siblingPosition);
2117
+ for (let i = 0; i < childNodes.length; ++i) {
2118
+ xmlTransformedTextRecursive(childNodes[i], buffer, options);
2119
+ }
2120
+ }
2121
+ node.visited = true;
2122
+ }
2123
+ function xmlElementLogicTrivial(node, buffer, options) {
2124
+ buffer.push(`<${xmlFullNodeName(node)}`);
2125
+ let attributes = [];
2126
+ if (node.firstChild) {
2127
+ let child = node.firstChild;
2128
+ while (child) {
2129
+ if (child.nodeType === DOM_ATTRIBUTE_NODE) {
2130
+ attributes.push(child);
2131
+ }
2132
+ child = child.nextSibling;
2133
+ }
2134
+ }
2135
+ if (attributes.length === 0) {
2136
+ attributes = node.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
2137
+ }
2138
+ for (let i = 0; i < attributes.length; ++i) {
2139
+ const attribute = attributes[i];
2140
+ if (!attribute) {
2141
+ continue;
2142
+ }
2143
+ if (attribute.nodeName && attribute.nodeValue) {
2144
+ buffer.push(` ${xmlFullNodeName(attribute)}="${xmlEscapeAttr(attribute.nodeValue)}"`);
2145
+ }
2146
+ }
2147
+ let childNodes = [];
2148
+ if (node.firstChild) {
2149
+ let child = node.firstChild;
2150
+ while (child) {
2151
+ if (child.nodeType !== DOM_ATTRIBUTE_NODE) {
2152
+ childNodes.push(child);
2153
+ }
2154
+ child = child.nextSibling;
2155
+ }
2156
+ }
2157
+ if (childNodes.length === 0) {
2158
+ childNodes = node.childNodes.filter((n) => n.nodeType !== DOM_ATTRIBUTE_NODE);
2159
+ }
2160
+ childNodes = childNodes.sort((a, b) => a.siblingPosition - b.siblingPosition);
2161
+ if (childNodes.length === 0) {
2162
+ if (options.outputMethod === "html" && ["hr", "link", "meta"].includes(node.nodeName)) {
2163
+ buffer.push(">");
2164
+ } else if (options.selfClosingTags) {
2165
+ buffer.push("/>");
2166
+ } else {
2167
+ buffer.push(`></${xmlFullNodeName(node)}>`);
2168
+ }
2169
+ } else {
2170
+ buffer.push(">");
2171
+ for (let i = 0; i < childNodes.length; ++i) {
2172
+ xmlTransformedTextRecursive(childNodes[i], buffer, options);
2173
+ }
2174
+ buffer.push(`</${xmlFullNodeName(node)}>`);
2175
+ }
2176
+ }
2177
+ function xmlElementLogicMuted(node, buffer, options) {
2178
+ let childNodes = [];
2179
+ if (node.firstChild) {
2180
+ let child = node.firstChild;
2181
+ while (child) {
2182
+ childNodes.push(child);
2183
+ child = child.nextSibling;
2184
+ }
2185
+ } else {
2186
+ childNodes = node.childNodes;
2187
+ }
2188
+ childNodes = childNodes.sort((a, b) => a.siblingPosition - b.siblingPosition);
2189
+ for (let i = 0; i < childNodes.length; ++i) {
2190
+ xmlTransformedTextRecursive(childNodes[i], buffer, options);
2191
+ }
2192
+ }
2193
+ function xmlFullNodeName(node) {
2194
+ const nodeName = node.nodeName;
2195
+ if (node.prefix && nodeName.indexOf(`${node.prefix}:`) != 0) {
2196
+ return `${node.prefix}:${nodeName}`;
2197
+ }
2198
+ return nodeName;
2199
+ }
2200
+ function xmlUnescapeText(text) {
2201
+ return `${text}`.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
2202
+ }
2203
+ function xmlEscapeText(s) {
2204
+ return `${s}`.replace(/&/g, "&amp;").replace(/&amp;amp;/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
2205
+ }
2206
+ function xmlEscapeAttr(s) {
2207
+ return xmlEscapeText(s).replace(/"/g, "&quot;");
2208
+ }
2209
+ function xmlGetAttribute(node, name) {
2210
+ const value = domGetAttributeValue(node, name);
2211
+ if (value) {
2212
+ return import_he.default.decode(value);
2213
+ }
2214
+ return value;
2215
+ }
2216
+
2217
+ // src/dom/xml-parser.ts
2218
+ var import_he2 = __toESM(require("he"));
2219
+
2220
+ // src/dom/xmltoken.ts
2221
+ var XML_S = "[ \r\n]+";
2222
+ var XML_EQ = `(${XML_S})?=(${XML_S})?`;
2223
+ var XML_CHAR_REF = "&#[0-9]+;|&#x[0-9a-fA-F]+;";
2224
+ var XML10_VERSION_INFO = `${XML_S}version${XML_EQ}("1\\.0"|'1\\.0')`;
2225
+ var XML10_BASE_CHAR = "A-Za-z\xC0-\xD6\xD8-\xF6\xF8-\xFF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3";
2226
+ var XML10_IDEOGRAPHIC = "\u4E00-\u9FA5\u3007\u3021-\u3029";
2227
+ var XML10_COMBINING_CHAR = "\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05A1\u05A3-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4\u064B-\u0652\u0670\u06D6-\u06DC\u06DD-\u06DF\u06E0-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0901-\u0903\u093C\u093E-\u094C\u094D\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09BC\u09BE\u09BF\u09C0-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7\u09E2-\u09E3\u0A02\u0A3C\u0A3E\u0A3F\u0A40-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D\u0B56-\u0B57\u0B82-\u0B83\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C82-\u0C83\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F95\u0F97\u0F99-\u0FAD\u0FB1-\u0FB7\u0FB9\u20D0-\u20DC\u20E1\u302A-\u302F\u3099\u309A";
2228
+ var XML10_DIGIT = "0-9\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE7-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29";
2229
+ var XML10_EXTENDER = "\xB7\u02D0\u02D1\u0387\u0640\u0E46\u0EC6\u3005\u3031-\u3035\u309D-\u309E\u30FC-\u30FE";
2230
+ var XML10_LETTER = XML10_BASE_CHAR + XML10_IDEOGRAPHIC;
2231
+ var XML10_NAME_CHAR = `${XML10_LETTER + XML10_DIGIT}\\._:${XML10_COMBINING_CHAR}${XML10_EXTENDER}-`;
2232
+ var XML10_NAME = `[${XML10_LETTER}_:][${XML10_NAME_CHAR}]*`;
2233
+ var XML10_ENTITY_REF = `&${XML10_NAME};`;
2234
+ var XML10_REFERENCE = `${XML10_ENTITY_REF}|${XML_CHAR_REF}`;
2235
+ var XML10_ATT_VALUE = `"(([^<&"]|${XML10_REFERENCE})*)"|'(([^<&']|${XML10_REFERENCE})*)'`;
2236
+ var XML10_ATTRIBUTE = `(${XML10_NAME})${XML_EQ}(${XML10_ATT_VALUE})`;
2237
+ var XML11_VERSION_INFO = `${XML_S}version${XML_EQ}("1\\.1"|'1\\.1')`;
2238
+ var XML11_NAME_START_CHAR = ":A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
2239
+ var XML11_NAME_CHAR = XML11_NAME_START_CHAR + "\\.0-9\xB7\u0300-\u036F\u203F-\u2040-";
2240
+ var XML11_NAME = `[${XML11_NAME_START_CHAR}][${XML11_NAME_CHAR}]*`;
2241
+ var XML11_ENTITY_REF = `&${XML11_NAME};`;
2242
+ var XML11_REFERENCE = `${XML11_ENTITY_REF}|${XML_CHAR_REF}`;
2243
+ var XML11_ATT_VALUE = `"(([^<&"]|${XML11_REFERENCE})*)"|'(([^<&']|${XML11_REFERENCE})*)'`;
2244
+ var XML11_ATTRIBUTE = `(${XML11_NAME})${XML_EQ}(${XML11_ATT_VALUE})`;
2245
+ var XML_NC_NAME_CHAR = `${XML10_LETTER + XML10_DIGIT}\\._${XML10_COMBINING_CHAR}${XML10_EXTENDER}-`;
2246
+ var XML_NC_NAME = `[${XML10_LETTER}_][${XML_NC_NAME_CHAR}]*`;
2247
+
2248
+ // src/dom/xml-parser.ts
2249
+ var XmlParser = class {
2250
+ constructor() {
2251
+ this.regexEmpty = /\/$/;
2252
+ this.XML10_TAGNAME_REGEXP = new RegExp(`^(${XML10_NAME})`);
2253
+ this.XML10_ATTRIBUTE_REGEXP = new RegExp(XML10_ATTRIBUTE, "g");
2254
+ this.XML11_TAGNAME_REGEXP = new RegExp(`^(${XML11_NAME})`);
2255
+ this.XML11_ATTRIBUTE_REGEXP = new RegExp(XML11_ATTRIBUTE, "g");
2256
+ this.lenientHtmlTags = ["hr", "link", "meta"];
2257
+ }
2258
+ /**
2259
+ * The entry point for this parser.
2260
+ * It verifies whether the document seems to be HTML.
2261
+ * HTML is a special case if XML and it should be parsed differently.
2262
+ * @param xmlOrHtml The XML or HTML content to be parsed.
2263
+ * @returns A DOM document.
2264
+ */
2265
+ xmlParse(xmlOrHtml) {
2266
+ if (xmlOrHtml.toUpperCase().startsWith("<!DOCTYPE HTML")) {
2267
+ return this.htmlParse(xmlOrHtml);
2268
+ }
2269
+ return this.xmlStrictParse(xmlOrHtml);
2270
+ }
2271
+ /**
2272
+ * Given an XNode, returns an object mapping prefixes to their corresponding namespaces in its scope.
2273
+ * Default namespace is treated as if its prefix were the empty string.
2274
+ * @param node The Node.
2275
+ * @returns An object with prefixes and namespace URLs.
2276
+ */
2277
+ namespaceMapAt(node) {
2278
+ const map = {
2279
+ // reserved namespaces: https://www.w3.org/TR/REC-xml-names/#xmlReserved
2280
+ xmlns: "http://www.w3.org/2000/xmlns/",
2281
+ xml: "http://www.w3.org/XML/1998/namespace"
2282
+ };
2283
+ let n = node;
2284
+ while (n !== null) {
2285
+ for (let i = 0; i < n.childNodes.length; i++) {
2286
+ const childNode = n.childNodes[i];
2287
+ if (childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
2288
+ continue;
2289
+ }
2290
+ if (childNode.nodeName.startsWith("xmlns:")) {
2291
+ const prefix = childNode.nodeName.split(":")[1];
2292
+ if (!(prefix in map)) map[prefix] = childNode.nodeValue;
2293
+ } else if (childNode.nodeName == "xmlns") {
2294
+ if (!("" in map)) map[""] = childNode.nodeValue || null;
2295
+ }
2296
+ }
2297
+ n = n.parentNode;
2298
+ }
2299
+ return map;
2300
+ }
2301
+ /**
2302
+ * HTML needs to be parsed differently because it's a special case of XML.
2303
+ * Sources:
2304
+ *
2305
+ * - https://blog.teamtreehouse.com/to-close-or-not-to-close-tags-in-html5
2306
+ * @param htmlText The HTML text
2307
+ * @returns A DOM document.
2308
+ */
2309
+ htmlParse(htmlText) {
2310
+ const xmlDocument = new XDocument();
2311
+ const root = xmlDocument;
2312
+ const stack = [];
2313
+ let parent = root;
2314
+ stack.push(parent);
2315
+ let tag = false, quotes = false, doublequotes = false, start = 0;
2316
+ for (let i = 0; i < htmlText.length; ++i) {
2317
+ let char = htmlText.charAt(i);
2318
+ if (tag) {
2319
+ if (!doublequotes && char === "'") {
2320
+ quotes = !quotes;
2321
+ } else if (!quotes && char === '"') {
2322
+ doublequotes = !doublequotes;
2323
+ } else if (!quotes && !doublequotes && char === ">") {
2324
+ let text = htmlText.slice(start, i);
2325
+ if (text.charAt(0) === "/") {
2326
+ stack.pop();
2327
+ parent = stack[stack.length - 1];
2328
+ } else if (text.charAt(0) === "!") {
2329
+ } else {
2330
+ const empty = text.match(this.regexEmpty);
2331
+ const tagName = this.XML10_TAGNAME_REGEXP.exec(text)[1];
2332
+ let node = domCreateElement(xmlDocument, tagName);
2333
+ let attribute;
2334
+ while (attribute = this.XML10_ATTRIBUTE_REGEXP.exec(text)) {
2335
+ const val = import_he2.default.decode(attribute[5] || attribute[7] || "");
2336
+ domSetAttribute(node, attribute[1], val);
2337
+ }
2338
+ node.siblingPosition = parent.childNodes.length;
2339
+ domAppendChild(parent, node);
2340
+ if (!empty && !this.lenientHtmlTags.includes(tagName)) {
2341
+ parent = node;
2342
+ stack.push(node);
2343
+ }
2344
+ }
2345
+ start = i + 1;
2346
+ tag = false;
2347
+ quotes = false;
2348
+ doublequotes = false;
2349
+ }
2350
+ } else {
2351
+ if (char === "<") {
2352
+ let text = htmlText.slice(start, i);
2353
+ if (text && parent !== root) {
2354
+ domAppendChild(parent, domCreateTextNode(xmlDocument, text));
2355
+ }
2356
+ if (htmlText.slice(i + 1, i + 4) === "!--") {
2357
+ let endTagIndex = htmlText.slice(i + 4).indexOf("-->");
2358
+ if (endTagIndex) {
2359
+ let node = domCreateComment(xmlDocument, htmlText.slice(i + 4, i + endTagIndex + 4));
2360
+ domAppendChild(parent, node);
2361
+ i += endTagIndex + 6;
2362
+ }
2363
+ } else if (htmlText.slice(i + 1, i + 9) === "!DOCTYPE") {
2364
+ let endTagIndex = htmlText.slice(i + 9).indexOf(">");
2365
+ if (endTagIndex) {
2366
+ const dtdValue = htmlText.slice(i + 9, i + endTagIndex + 9).trimStart();
2367
+ const node = domCreateDTDSection(xmlDocument, dtdValue);
2368
+ domAppendChild(parent, node);
2369
+ i += endTagIndex + dtdValue.length + 5;
2370
+ }
2371
+ } else {
2372
+ tag = true;
2373
+ }
2374
+ start = i + 1;
2375
+ }
2376
+ }
2377
+ }
2378
+ return xmlDocument;
2379
+ }
2380
+ /**
2381
+ * Parses the given XML string with our custom, JavaScript XML parser.
2382
+ * @param xml The XML String.
2383
+ * @returns A XDocument.
2384
+ * @author Steffen Meschkat <mesch@google.com>
2385
+ */
2386
+ xmlStrictParse(xml) {
2387
+ let regexTagname;
2388
+ let regexAttribute;
2389
+ if (xml.match(/^<\?xml/)) {
2390
+ if (xml.search(new RegExp(XML10_VERSION_INFO)) === 5) {
2391
+ regexTagname = this.XML10_TAGNAME_REGEXP;
2392
+ regexAttribute = this.XML10_ATTRIBUTE_REGEXP;
2393
+ } else if (xml.search(new RegExp(XML11_VERSION_INFO)) === 5) {
2394
+ regexTagname = this.XML11_TAGNAME_REGEXP;
2395
+ regexAttribute = this.XML11_ATTRIBUTE_REGEXP;
2396
+ } else {
2397
+ throw new Error("XML VersionInfo has an unknown version number.");
2398
+ }
2399
+ } else {
2400
+ regexTagname = this.XML10_TAGNAME_REGEXP;
2401
+ regexAttribute = this.XML10_ATTRIBUTE_REGEXP;
2402
+ }
2403
+ const xmlDocument = new XDocument();
2404
+ const root = xmlDocument;
2405
+ const stack = [];
2406
+ let parent = root;
2407
+ stack.push(parent);
2408
+ let tag = false, quotes = false, doublequotes = false, start = 0;
2409
+ for (let i = 0; i < xml.length; ++i) {
2410
+ let char = xml.charAt(i);
2411
+ if (tag && !doublequotes && char === "'") {
2412
+ quotes = !quotes;
2413
+ } else if (tag && !quotes && char === '"') {
2414
+ doublequotes = !doublequotes;
2415
+ } else if (tag && char === ">" && !quotes && !doublequotes) {
2416
+ let text = xml.slice(start, i);
2417
+ if (text.charAt(0) === "/") {
2418
+ stack.pop();
2419
+ parent = stack[stack.length - 1];
2420
+ } else if (text.charAt(0) === "?") {
2421
+ } else if (text.charAt(0) === "!") {
2422
+ } else {
2423
+ const empty = text.match(this.regexEmpty);
2424
+ const tagname = regexTagname.exec(text)[1];
2425
+ let node = domCreateElement(xmlDocument, tagname);
2426
+ let attribute;
2427
+ while (attribute = regexAttribute.exec(text)) {
2428
+ const val = import_he2.default.decode(attribute[5] || attribute[7] || "");
2429
+ domSetAttribute(node, attribute[1], val);
2430
+ }
2431
+ node.siblingPosition = parent.childNodes.length;
2432
+ domAppendChild(parent, node);
2433
+ if (!empty) {
2434
+ parent = node;
2435
+ stack.push(node);
2436
+ }
2437
+ const namespaceMap = this.namespaceMapAt(node);
2438
+ if (node.prefix !== null) {
2439
+ if (node.prefix in namespaceMap) node.namespaceUri = namespaceMap[node.prefix];
2440
+ } else {
2441
+ if ("" in namespaceMap) node.namespaceUri = namespaceMap[""];
2442
+ }
2443
+ for (let i2 = 0; i2 < node.childNodes.length; ++i2) {
2444
+ const childNode = node.childNodes[i2];
2445
+ if (childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
2446
+ continue;
2447
+ }
2448
+ if (childNode.prefix !== null && childNode.prefix in namespaceMap) {
2449
+ childNode.namespaceUri = namespaceMap[childNode.prefix];
2450
+ }
2451
+ }
2452
+ }
2453
+ start = i + 1;
2454
+ tag = false;
2455
+ quotes = false;
2456
+ doublequotes = false;
2457
+ } else if (!tag && char === "<") {
2458
+ let text = xml.slice(start, i);
2459
+ if (text && parent !== root) {
2460
+ domAppendChild(parent, domCreateTextNode(xmlDocument, text));
2461
+ }
2462
+ if (xml.slice(i + 1, i + 4) === "!--") {
2463
+ let endTagIndex = xml.slice(i + 4).indexOf("-->");
2464
+ if (endTagIndex) {
2465
+ let node = domCreateComment(xmlDocument, xml.slice(i + 4, i + endTagIndex + 4));
2466
+ domAppendChild(parent, node);
2467
+ i += endTagIndex + 6;
2468
+ }
2469
+ } else if (xml.slice(i + 1, i + 9) === "![CDATA[") {
2470
+ let endTagIndex = xml.slice(i + 9).indexOf("]]>");
2471
+ if (endTagIndex) {
2472
+ let node = domCreateCDATASection(xmlDocument, xml.slice(i + 9, i + endTagIndex + 9));
2473
+ domAppendChild(parent, node);
2474
+ i += endTagIndex + 11;
2475
+ }
2476
+ } else if (xml.slice(i + 1, i + 9) === "!DOCTYPE") {
2477
+ let endTagIndex = xml.slice(i + 9).indexOf(">");
2478
+ if (endTagIndex) {
2479
+ const dtdValue = xml.slice(i + 9, i + endTagIndex + 9).trimStart();
2480
+ const node = domCreateDTDSection(xmlDocument, dtdValue);
2481
+ domAppendChild(parent, node);
2482
+ i += endTagIndex + dtdValue.length + 5;
2483
+ }
2484
+ } else {
2485
+ tag = true;
2486
+ }
2487
+ start = i + 1;
2488
+ }
2489
+ }
2490
+ return root;
2491
+ }
2492
+ };
2493
+
2494
+ // src/xpath/values/node-set-value.ts
2495
+ var NodeSetValue = class {
2496
+ constructor(value) {
2497
+ this.value = value;
2498
+ this.type = "node-set";
2499
+ }
2500
+ stringValue() {
2501
+ if (this.value.length === 0) {
2502
+ return "";
2503
+ }
2504
+ return xmlValue(this.value[0]);
2505
+ }
2506
+ booleanValue() {
2507
+ return this.value.length > 0;
2508
+ }
2509
+ numberValue() {
2510
+ return parseInt(this.stringValue()) - 0;
2511
+ }
2512
+ nodeSetValue() {
2513
+ return this.value;
2514
+ }
2515
+ };
2516
+
2517
+ // src/xpath/xpath.ts
2518
+ var Expression = class {
2519
+ constructor(xpathExpression, nodeConverter) {
2520
+ this.xpathExpression = xpathExpression;
2521
+ this.nodeConverter = nodeConverter;
2522
+ if (xpathExpression instanceof XPathLocationPath) {
2523
+ this.absolute = xpathExpression.absolute;
2524
+ this.steps = xpathExpression.steps.map((step, index) => ({
2525
+ axis: step.axis,
2526
+ nodeTest: step.nodeTest,
2527
+ predicates: step.predicates,
2528
+ // Add methods needed by old code
2529
+ hasPositionalPredicate: false,
2530
+ // TODO: implement proper detection
2531
+ predicate: step.predicates || [],
2532
+ evaluate: (ctx) => {
2533
+ const xpathCtx = this.nodeConverter.exprContextToXPathContext(ctx);
2534
+ const result = step.evaluate(xpathCtx);
2535
+ return this.nodeConverter.wrapResult(result, ctx);
2536
+ }
2537
+ }));
2538
+ }
2539
+ }
2540
+ /**
2541
+ * Evaluate the expression in the given context.
2542
+ */
2543
+ evaluate(context) {
2544
+ const xpathContext = this.nodeConverter.exprContextToXPathContext(context);
2545
+ const result = this.xpathExpression.evaluate(xpathContext);
2546
+ return this.nodeConverter.wrapResult(result, context);
2547
+ }
2548
+ };
2549
+ var LocationExpr = class extends Expression {
2550
+ constructor(xpathExpression, nodeConverter) {
2551
+ super(xpathExpression, nodeConverter);
2552
+ this.absolute = xpathExpression.absolute;
2553
+ this.steps = xpathExpression.steps.map((step) => ({
2554
+ axis: step.axis,
2555
+ nodeTest: step.nodeTest,
2556
+ predicates: step.predicates || [],
2557
+ predicate: step.predicates || [],
2558
+ hasPositionalPredicate: this.hasPositionalPredicate(step.predicates || [])
2559
+ }));
2560
+ }
2561
+ hasPositionalPredicate(predicates) {
2562
+ return false;
2563
+ }
2564
+ appendStep(step) {
2565
+ this.steps.push(step);
2566
+ }
2567
+ prependStep(step) {
2568
+ this.steps.unshift(step);
2569
+ }
2570
+ };
2571
+ var UnionExpr = class extends Expression {
2572
+ constructor(xpathExpression, nodeConverter, expr1, expr2) {
2573
+ super(xpathExpression, nodeConverter);
2574
+ this.expr1 = expr1;
2575
+ this.expr2 = expr2;
2576
+ }
2577
+ };
2578
+ var NodeConverter = class {
2579
+ /**
2580
+ * Convert ExprContext to XPathContext for the new XPath implementation.
2581
+ * XNodes are used directly since they implement enough of the XPathNode interface.
2582
+ */
2583
+ exprContextToXPathContext(exprContext) {
2584
+ const currentNode = exprContext.nodeList[exprContext.position];
2585
+ const xpathNode = this.adaptXNode(currentNode);
2586
+ const nodeList = exprContext.nodeList.map((node) => this.adaptXNode(node));
2587
+ return createContext(xpathNode, {
2588
+ position: exprContext.position + 1,
2589
+ // XPath is 1-based
2590
+ size: exprContext.nodeList.length,
2591
+ nodeList,
2592
+ variables: this.convertVariables(exprContext),
2593
+ functions: this.createCustomFunctions(exprContext),
2594
+ namespaces: exprContext.knownNamespaces
2595
+ });
2596
+ }
2597
+ /**
2598
+ * Adapt XNode to be compatible with XPathNode interface.
2599
+ * We add missing properties but keep the original XNode reference.
2600
+ */
2601
+ adaptXNode(node) {
2602
+ if (!node) return null;
2603
+ const adapted = node;
2604
+ if (!("namespaceURI" in adapted)) {
2605
+ Object.defineProperty(adapted, "namespaceURI", {
2606
+ get() {
2607
+ return this.namespaceUri;
2608
+ },
2609
+ enumerable: true,
2610
+ configurable: true
2611
+ });
2612
+ }
2613
+ if (!("textContent" in adapted)) {
2614
+ Object.defineProperty(adapted, "textContent", {
2615
+ get() {
2616
+ return this._getTextContent();
2617
+ },
2618
+ enumerable: true,
2619
+ configurable: true
2620
+ });
2621
+ }
2622
+ if (!("_getTextContent" in adapted)) {
2623
+ adapted._getTextContent = function() {
2624
+ if (this.nodeType === 3 || this.nodeType === 2) {
2625
+ return this.nodeValue || "";
2626
+ }
2627
+ if (!this.childNodes) return "";
2628
+ let text = "";
2629
+ for (const child of this.childNodes) {
2630
+ if (child.nodeType === 3) {
2631
+ text += child.nodeValue || "";
2632
+ } else if (child.nodeType === 1) {
2633
+ text += this._getTextContent.call(child);
2634
+ }
2635
+ }
2636
+ return text;
2637
+ };
2638
+ }
2639
+ if (!("attributes" in adapted)) {
2640
+ Object.defineProperty(adapted, "attributes", {
2641
+ get() {
2642
+ return this.childNodes ? this.childNodes.filter((n) => n.nodeType === 2) : [];
2643
+ },
2644
+ enumerable: true,
2645
+ configurable: true
2646
+ });
2647
+ }
2648
+ if (!("getAttribute" in adapted)) {
2649
+ adapted.getAttribute = function(name) {
2650
+ return this.getAttributeValue ? this.getAttributeValue(name) : null;
2651
+ };
2652
+ }
2653
+ return adapted;
2654
+ }
2655
+ /**
2656
+ * Convert XPathNode result back to XNode.
2657
+ * Since we're now using XNodes directly, this is mostly a type cast.
2658
+ */
2659
+ xPathNodeToXNode(xpathNode) {
2660
+ if (!xpathNode) return null;
2661
+ return xpathNode;
2662
+ }
2663
+ /**
2664
+ * Get text content from an XNode.
2665
+ */
2666
+ getTextContent(node) {
2667
+ if (node.nodeType === 3 || node.nodeType === 2) {
2668
+ return node.nodeValue || "";
2669
+ }
2670
+ if (!node.childNodes) return "";
2671
+ let text = "";
2672
+ for (const child of node.childNodes) {
2673
+ if (child.nodeType === 3) {
2674
+ text += child.nodeValue || "";
2675
+ } else if (child.nodeType === 1) {
2676
+ text += this.getTextContent(child);
2677
+ }
2678
+ }
2679
+ return text;
2680
+ }
2681
+ /**
2682
+ * Convert variables from ExprContext format to XPathContext format.
2683
+ */
2684
+ convertVariables(exprContext) {
2685
+ const variables = {};
2686
+ for (const [name, value] of Object.entries(exprContext.variables || {})) {
2687
+ if (value && typeof value === "object" && "stringValue" in value) {
2688
+ const nodeValue = value;
2689
+ if (nodeValue.type === "node-set") {
2690
+ variables[name] = value.nodeSetValue().map((n) => this.adaptXNode(n));
2691
+ } else if (nodeValue.type === "string") {
2692
+ variables[name] = value.stringValue();
2693
+ } else if (nodeValue.type === "number") {
2694
+ variables[name] = value.numberValue();
2695
+ } else if (nodeValue.type === "boolean") {
2696
+ variables[name] = value.booleanValue();
2697
+ } else {
2698
+ variables[name] = value.stringValue();
2699
+ }
2700
+ } else {
2701
+ variables[name] = value;
2702
+ }
2703
+ }
2704
+ return variables;
2705
+ }
2706
+ /**
2707
+ * Create custom functions for XPath context (like key(), document(), etc.).
2708
+ */
2709
+ createCustomFunctions(exprContext) {
2710
+ const functions = {};
2711
+ functions["key"] = (keyName, keyValue) => {
2712
+ var _a;
2713
+ const keyDef = (_a = exprContext.keys) == null ? void 0 : _a[keyName];
2714
+ if (keyDef && keyDef[keyValue]) {
2715
+ const nodeSetValue = keyDef[keyValue];
2716
+ return nodeSetValue.nodeSetValue().map((n) => this.adaptXNode(n));
2717
+ }
2718
+ return [];
2719
+ };
2720
+ functions["current"] = () => {
2721
+ const currentNode = exprContext.nodeList[exprContext.position];
2722
+ return [this.adaptXNode(currentNode)];
2723
+ };
2724
+ functions["format-number"] = (number, format, decimalFormatName) => {
2725
+ const settings = exprContext.decimalFormatSettings;
2726
+ return number.toLocaleString();
2727
+ };
2728
+ functions["xml-to-json"] = (nodes) => {
2729
+ if (exprContext.xsltVersion === "1.0") {
2730
+ throw new Error('xml-to-json() is not supported in XSLT 1.0. Use version="3.0" in your stylesheet.');
2731
+ }
2732
+ const node = Array.isArray(nodes) ? nodes[0] : nodes;
2733
+ if (!node) {
2734
+ return '""';
2735
+ }
2736
+ return this.xmlToJson(node);
2737
+ };
2738
+ return functions;
2739
+ }
2740
+ /**
2741
+ * Convert an XML node to a JSON string representation.
2742
+ * This is a simplified implementation of XSLT 3.0's xml-to-json().
2743
+ */
2744
+ xmlToJson(node) {
2745
+ if (!node) {
2746
+ return '""';
2747
+ }
2748
+ if (node.nodeType === 3) {
2749
+ const text = node.nodeValue || "";
2750
+ return JSON.stringify(text);
2751
+ }
2752
+ if (node.nodeType === 1) {
2753
+ const textContent = this.getTextContent(node);
2754
+ return JSON.stringify(textContent);
2755
+ }
2756
+ if (node.nodeType === 2) {
2757
+ return JSON.stringify(node.nodeValue || "");
2758
+ }
2759
+ return '""';
2760
+ }
2761
+ /**
2762
+ * Wrap XPath result in appropriate NodeValue type.
2763
+ */
2764
+ wrapResult(result, exprContext) {
2765
+ if (Array.isArray(result)) {
2766
+ const xnodes = result.map((node) => this.xPathNodeToXNode(node)).filter((n) => n !== null);
2767
+ return new NodeSetValue(xnodes);
2768
+ }
2769
+ if (typeof result === "string") {
2770
+ return new StringValue(result);
2771
+ }
2772
+ if (typeof result === "number") {
2773
+ return new NumberValue(result);
2774
+ }
2775
+ if (typeof result === "boolean") {
2776
+ return new BooleanValue(result);
2777
+ }
2778
+ return new NodeSetValue([]);
2779
+ }
2780
+ /**
2781
+ * Clear any internal state if needed.
2782
+ */
2783
+ clearCache() {
2784
+ }
2785
+ };
2786
+ var XPath = class {
2787
+ constructor() {
2788
+ this.parseCache = /* @__PURE__ */ new Map();
2789
+ this.lexer = new XPathLexer();
2790
+ this.parser = new XPathParser();
2791
+ this.nodeConverter = new NodeConverter();
2792
+ }
2793
+ /**
2794
+ * Parse an XPath expression and return an Expression object.
2795
+ * @param expression The XPath expression string.
2796
+ * @param axis Optional axis override for relative paths.
2797
+ */
2798
+ xPathParse(expression, axis) {
2799
+ const cacheKey = `${expression}:${axis || ""}`;
2800
+ if (this.parseCache.has(cacheKey)) {
2801
+ return this.parseCache.get(cacheKey);
2802
+ }
2803
+ const tokens = this.lexer.scan(expression);
2804
+ const xpathExpr = this.parser.parse(tokens);
2805
+ const wrappedExpr = this.wrapExpression(xpathExpr, axis);
2806
+ this.parseCache.set(cacheKey, wrappedExpr);
2807
+ return wrappedExpr;
2808
+ }
2809
+ /**
2810
+ * Parse and evaluate an XPath expression.
2811
+ * @param select The XPath expression string.
2812
+ * @param context The expression context.
2813
+ */
2814
+ xPathEval(select, context) {
2815
+ const expression = this.xPathParse(select);
2816
+ return expression.evaluate(context);
2817
+ }
2818
+ /**
2819
+ * Sort nodes in context according to sort specifications.
2820
+ * @param context The expression context with nodes to sort.
2821
+ * @param sort Array of sort specifications.
2822
+ */
2823
+ xPathSort(context, sort) {
2824
+ if (sort.length === 0) {
2825
+ return;
2826
+ }
2827
+ const sortList = [];
2828
+ for (let i = 0; i < context.contextSize(); ++i) {
2829
+ const node = context.nodeList[i];
2830
+ const sortItem = {
2831
+ node,
2832
+ key: []
2833
+ };
2834
+ const clonedContext = context.clone([node], 0);
2835
+ for (const s of sort) {
2836
+ const value = s.expr.evaluate(clonedContext);
2837
+ let evalue;
2838
+ if (s.type === "text") {
2839
+ evalue = value.stringValue();
2840
+ } else if (s.type === "number") {
2841
+ evalue = value.numberValue();
2842
+ }
2843
+ sortItem.key.push({
2844
+ value: evalue,
2845
+ order: s.order
2846
+ });
2847
+ }
2848
+ sortItem.key.push({
2849
+ value: i,
2850
+ order: "ascending"
2851
+ });
2852
+ sortList.push(sortItem);
2853
+ }
2854
+ sortList.sort(this.xPathSortByKey);
2855
+ const nodes = [];
2856
+ for (let i = 0; i < sortList.length; ++i) {
2857
+ const node = sortList[i].node;
2858
+ node.siblingPosition = i;
2859
+ nodes.push(node);
2860
+ }
2861
+ context.nodeList = nodes;
2862
+ context.setNode(0);
2863
+ }
2864
+ /**
2865
+ * Comparison function for sorting.
2866
+ */
2867
+ xPathSortByKey(v1, v2) {
2868
+ for (let i = 0; i < v1.key.length; ++i) {
2869
+ const o = v1.key[i].order === "descending" ? -1 : 1;
2870
+ if (v1.key[i].value > v2.key[i].value) {
2871
+ return 1 * o;
2872
+ }
2873
+ if (v1.key[i].value < v2.key[i].value) {
2874
+ return -1 * o;
2875
+ }
2876
+ }
2877
+ return 0;
2878
+ }
2879
+ /**
2880
+ * Wrap a new XPath expression in the backward-compatible Expression class.
2881
+ */
2882
+ wrapExpression(xpathExpr, axis) {
2883
+ if (xpathExpr instanceof XPathLocationPath) {
2884
+ if (axis && xpathExpr.steps.length > 0 && !xpathExpr.absolute) {
2885
+ xpathExpr.steps[0].axis = axis;
2886
+ }
2887
+ return new LocationExpr(xpathExpr, this.nodeConverter);
2888
+ }
2889
+ if (xpathExpr instanceof XPathUnionExpression) {
2890
+ const expr1 = this.wrapExpression(xpathExpr.left, axis);
2891
+ const expr2 = this.wrapExpression(xpathExpr.right, axis);
2892
+ return new UnionExpr(xpathExpr, this.nodeConverter, expr1, expr2);
2893
+ }
2894
+ return new Expression(xpathExpr, this.nodeConverter);
2895
+ }
2896
+ /**
2897
+ * Clear parse cache (useful for testing or memory management).
2898
+ */
2899
+ clearCache() {
2900
+ this.parseCache.clear();
2901
+ this.nodeConverter.clearCache();
2902
+ }
2903
+ };
2904
+
2905
+ // src/xpath/tokens.ts
2906
+ var TOK_NUMBER = {
2907
+ label: "[number]",
2908
+ prec: 35,
2909
+ re: new RegExp("^\\d+(\\.\\d*)?"),
2910
+ key: void 0
2911
+ };
2912
+
2913
+ // src/xpath/expr-context.ts
2914
+ var ExprContext = class _ExprContext {
2915
+ /**
2916
+ * Constructor -- gets the node, its position, the node set it
2917
+ * belongs to, and a parent context as arguments. The parent context
2918
+ * is used to implement scoping rules for variables: if a variable
2919
+ * is not found in the current context, it is looked for in the
2920
+ * parent context, recursively. Except for node, all arguments have
2921
+ * default values: default position is 0, default node set is the
2922
+ * set that contains only the node, and the default parent is null.
2923
+ *
2924
+ * Notice that position starts at 0 at the outside interface;
2925
+ * inside XPath expressions this shows up as position()=1.
2926
+ * @param nodeList TODO
2927
+ * @param opt_position TODO
2928
+ * @param opt_parent TODO
2929
+ * @param opt_caseInsensitive TODO
2930
+ * @param opt_ignoreAttributesWithoutValue TODO
2931
+ * @param opt_returnOnFirstMatch TODO
2932
+ * @param opt_ignoreNonElementNodesForNTA TODO
2933
+ */
2934
+ constructor(nodeList, xsltVersion = "1.0", opt_position, opt_decimalFormatSettings, opt_variables, opt_knownNamespaces, opt_parent, opt_caseInsensitive, opt_ignoreAttributesWithoutValue, opt_returnOnFirstMatch, opt_ignoreNonElementNodesForNTA) {
2935
+ this.nodeList = nodeList;
2936
+ this.xsltVersion = xsltVersion;
2937
+ this.position = opt_position || 0;
2938
+ this.variables = opt_variables || {};
2939
+ this.keys = (opt_parent == null ? void 0 : opt_parent.keys) || {};
2940
+ this.knownNamespaces = opt_knownNamespaces || {};
2941
+ this.parent = opt_parent || null;
2942
+ this.caseInsensitive = opt_caseInsensitive || false;
2943
+ this.ignoreAttributesWithoutValue = opt_ignoreAttributesWithoutValue || false;
2944
+ this.returnOnFirstMatch = opt_returnOnFirstMatch || false;
2945
+ this.ignoreNonElementNodesForNTA = opt_ignoreNonElementNodesForNTA || false;
2946
+ this.inApplyTemplates = false;
2947
+ this.baseTemplateMatched = false;
2948
+ this.decimalFormatSettings = opt_decimalFormatSettings || {
2949
+ decimalSeparator: ".",
2950
+ groupingSeparator: ",",
2951
+ infinity: "Infinity",
2952
+ minusSign: "-",
2953
+ naN: "NaN",
2954
+ percent: "%",
2955
+ perMille: "\u2030",
2956
+ zeroDigit: "0",
2957
+ digit: "#",
2958
+ patternSeparator: ";"
2959
+ };
2960
+ if (opt_parent) {
2961
+ this.root = opt_parent.root;
2962
+ } else if (this.nodeList[this.position].nodeType == DOM_DOCUMENT_NODE) {
2963
+ this.root = this.nodeList[this.position];
2964
+ } else {
2965
+ this.root = this.nodeList[this.position].ownerDocument;
2966
+ }
2967
+ }
2968
+ /**
2969
+ * clone() -- creates a new context with the current context as
2970
+ * parent. If passed as argument to clone(), the new context has a
2971
+ * different node, position, or node set. What is not passed is
2972
+ * inherited from the cloned context.
2973
+ * @param opt_nodeList TODO
2974
+ * @param opt_position TODO
2975
+ * @returns TODO
2976
+ */
2977
+ clone(opt_nodeList, opt_position) {
2978
+ return new _ExprContext(
2979
+ opt_nodeList || this.nodeList,
2980
+ this.xsltVersion,
2981
+ typeof opt_position !== "undefined" ? opt_position : this.position,
2982
+ this.decimalFormatSettings,
2983
+ this.variables,
2984
+ this.knownNamespaces,
2985
+ this,
2986
+ this.caseInsensitive,
2987
+ this.ignoreAttributesWithoutValue,
2988
+ this.returnOnFirstMatch,
2989
+ this.ignoreNonElementNodesForNTA
2990
+ );
2991
+ }
2992
+ setVariable(name, value) {
2993
+ if (value instanceof StringValue || value instanceof BooleanValue || value instanceof NumberValue || value instanceof NodeSetValue) {
2994
+ this.variables[name] = value;
2995
+ return;
2996
+ }
2997
+ if ("true" === value) {
2998
+ this.variables[name] = new BooleanValue(true);
2999
+ } else if ("false" === value) {
3000
+ this.variables[name] = new BooleanValue(false);
3001
+ } else if (TOK_NUMBER.re.test(String(value))) {
3002
+ this.variables[name] = new NumberValue(value);
3003
+ } else {
3004
+ this.variables[name] = new StringValue(value);
3005
+ }
3006
+ }
3007
+ getVariable(name) {
3008
+ if (typeof this.variables[name] != "undefined") {
3009
+ return this.variables[name];
3010
+ }
3011
+ if (this.parent) {
3012
+ return this.parent.getVariable(name);
3013
+ }
3014
+ return null;
3015
+ }
3016
+ setNode(position) {
3017
+ this.position = position;
3018
+ }
3019
+ contextSize() {
3020
+ return this.nodeList.length;
3021
+ }
3022
+ isCaseInsensitive() {
3023
+ return this.caseInsensitive;
3024
+ }
3025
+ setCaseInsensitive(caseInsensitive) {
3026
+ return this.caseInsensitive = caseInsensitive;
3027
+ }
3028
+ isIgnoreAttributesWithoutValue() {
3029
+ return this.ignoreAttributesWithoutValue;
3030
+ }
3031
+ setIgnoreAttributesWithoutValue(ignore) {
3032
+ return this.ignoreAttributesWithoutValue = ignore;
3033
+ }
3034
+ isReturnOnFirstMatch() {
3035
+ return this.returnOnFirstMatch;
3036
+ }
3037
+ setReturnOnFirstMatch(returnOnFirstMatch) {
3038
+ return this.returnOnFirstMatch = returnOnFirstMatch;
3039
+ }
3040
+ isIgnoreNonElementNodesForNTA() {
3041
+ return this.ignoreNonElementNodesForNTA;
3042
+ }
3043
+ setIgnoreNonElementNodesForNTA(ignoreNonElementNodesForNTA) {
3044
+ return this.ignoreNonElementNodesForNTA = ignoreNonElementNodesForNTA;
3045
+ }
3046
+ };
3047
+
3048
+ // src/xpath/match-resolver.ts
3049
+ var MatchResolver = class {
3050
+ /**
3051
+ * Entry point for expression matching.
3052
+ * @param expression The expression to be resolved.
3053
+ * @param context The Expression Context.
3054
+ * @returns An array of nodes.
3055
+ */
3056
+ expressionMatch(expression, context) {
3057
+ if (expression instanceof LocationExpr) {
3058
+ return this.locationExpressionMatch(expression, context);
3059
+ }
3060
+ if (expression instanceof UnionExpr) {
3061
+ return this.unionExpressionMatch(expression, context);
3062
+ }
3063
+ try {
3064
+ const result = expression.evaluate(context);
3065
+ return result.nodeSetValue();
3066
+ } catch (e) {
3067
+ return [];
3068
+ }
3069
+ }
3070
+ /**
3071
+ * Resolves a LocationExpr.
3072
+ * @param expression The Location Expression.
3073
+ * @param context The Expression Context.
3074
+ * @returns Either the results of a relative resolution, or the results of an
3075
+ * absolute resolution.
3076
+ */
3077
+ locationExpressionMatch(expression, context) {
3078
+ if (!expression.steps || expression.steps.length <= 0) {
3079
+ if (expression.absolute) {
3080
+ const contextNode = context.nodeList[context.position];
3081
+ if (contextNode.nodeName === "#document") {
3082
+ return [contextNode];
3083
+ }
3084
+ return [];
3085
+ }
3086
+ return [context.nodeList[context.position]];
3087
+ }
3088
+ if (expression.absolute) {
3089
+ const firstStep = expression.steps[0];
3090
+ if (firstStep.axis === "self") {
3091
+ return this.absoluteXsltMatchByDocumentNode(expression, context);
3092
+ }
3093
+ return this.absoluteXsltMatch(expression, context);
3094
+ }
3095
+ return this.relativeXsltMatch(expression, context);
3096
+ }
3097
+ /**
3098
+ * Resolves a UnionExpr.
3099
+ * @param expression The Union Expression.
3100
+ * @param context The Expression Context.
3101
+ * @returns The concatenated result of evaluating both sides of the expression.
3102
+ */
3103
+ unionExpressionMatch(expression, context) {
3104
+ const expr1Nodes = this.expressionMatch(expression.expr1, context);
3105
+ return expr1Nodes.concat(this.expressionMatch(expression.expr2, context));
3106
+ }
3107
+ /**
3108
+ * Finds all the nodes through absolute XPath search, starting on
3109
+ * the #document parent node.
3110
+ * @param expression The Expression.
3111
+ * @param context The Expression Context.
3112
+ * @returns The list of found nodes.
3113
+ */
3114
+ absoluteXsltMatchByDocumentNode(expression, context) {
3115
+ const clonedContext = context.clone([context.root], 0);
3116
+ const matchedNodes = expression.evaluate(clonedContext).nodeSetValue();
3117
+ const finalList = [];
3118
+ for (const element of matchedNodes) {
3119
+ if (element.id === context.nodeList[context.position].id) {
3120
+ finalList.push(element);
3121
+ }
3122
+ }
3123
+ return finalList;
3124
+ }
3125
+ /**
3126
+ * Finds all the nodes through absolute XPath search, starting with the
3127
+ * first child of the #document node.
3128
+ * @param expression The Expression.
3129
+ * @param context The Expression Context.
3130
+ * @returns The list of found nodes.
3131
+ */
3132
+ absoluteXsltMatch(expression, context) {
3133
+ var _a;
3134
+ const firstChildOfRoot = context.root.childNodes.find((c) => c.nodeName !== "#dtd-section");
3135
+ if (!firstChildOfRoot) return [];
3136
+ const clonedContext = context.clone([firstChildOfRoot], 0);
3137
+ const matchedNodes = expression.evaluate(clonedContext).nodeSetValue();
3138
+ const finalList = [];
3139
+ let nodeList;
3140
+ if (context.nodeList.length === 1 && context.nodeList[0].nodeName === "#document") {
3141
+ nodeList = [context.nodeList[0].childNodes.find((c) => c.nodeName !== "#dtd-section")];
3142
+ } else {
3143
+ nodeList = context.nodeList;
3144
+ }
3145
+ for (const element of matchedNodes) {
3146
+ if (element.id === ((_a = nodeList[context.position]) == null ? void 0 : _a.id)) {
3147
+ finalList.push(element);
3148
+ }
3149
+ }
3150
+ return finalList;
3151
+ }
3152
+ /**
3153
+ * Tries to find relative nodes from the actual context position.
3154
+ * If found nodes are already in the context, or if they are children of
3155
+ * nodes in the context, they are returned.
3156
+ * @param expression The expression used.
3157
+ * @param context The Expression Context.
3158
+ * @returns The list of found nodes.
3159
+ */
3160
+ relativeXsltMatch(expression, context) {
3161
+ const clonedContext = context.clone();
3162
+ const nodes = expression.evaluate(clonedContext).nodeSetValue();
3163
+ if (nodes.length === 1 && nodes[0].nodeName === "#document") {
3164
+ return [nodes[0].childNodes[0]];
3165
+ }
3166
+ return nodes;
3167
+ }
3168
+ };
3169
+
3170
+ // src/xpath/node-tests/node-test-any.ts
3171
+ var NodeTestAny = class {
3172
+ constructor() {
3173
+ this.value = new BooleanValue(true);
3174
+ }
3175
+ evaluate() {
3176
+ return this.value;
3177
+ }
3178
+ };
3179
+
3180
+ // src/xpath/node-tests/node-test-comment.ts
3181
+ var NodeTestComment = class {
3182
+ evaluate(ctx) {
3183
+ return new BooleanValue(ctx.nodeList[ctx.position].nodeType == DOM_COMMENT_NODE);
3184
+ }
3185
+ };
3186
+
3187
+ // src/xpath/node-tests/node-test-element-or-attribute.ts
3188
+ var NodeTestElementOrAttribute = class {
3189
+ evaluate(context) {
3190
+ const node = context.nodeList[context.position];
3191
+ return new BooleanValue(node.nodeType == DOM_ELEMENT_NODE || node.nodeType == DOM_ATTRIBUTE_NODE);
3192
+ }
3193
+ };
3194
+
3195
+ // src/xpath/node-tests/node-test-name.ts
3196
+ var NodeTestName = class {
3197
+ constructor(name) {
3198
+ this.name = name;
3199
+ if (name.indexOf(":") > 0) {
3200
+ const nameAndNamespacePrefix = name.split(":");
3201
+ this.namespacePrefix = nameAndNamespacePrefix[0];
3202
+ this.name = nameAndNamespacePrefix[1];
3203
+ }
3204
+ this.re = new RegExp(`^${name}$`, "i");
3205
+ }
3206
+ evaluate(context) {
3207
+ const node = context.nodeList[context.position];
3208
+ if (this.namespacePrefix !== void 0) {
3209
+ const namespaceValue = context.knownNamespaces[this.namespacePrefix];
3210
+ if (namespaceValue !== node.namespaceUri) {
3211
+ return new BooleanValue(false);
3212
+ }
3213
+ if (context.caseInsensitive) {
3214
+ if (node.localName.length !== this.name.length) return new BooleanValue(false);
3215
+ return new BooleanValue(this.re.test(node.localName));
3216
+ }
3217
+ return new BooleanValue(node.localName === this.name);
3218
+ }
3219
+ if (context.caseInsensitive) {
3220
+ if (node.nodeName.length !== this.name.length) return new BooleanValue(false);
3221
+ return new BooleanValue(this.re.test(node.nodeName));
3222
+ }
3223
+ return new BooleanValue(node.nodeName === this.name);
3224
+ }
3225
+ };
3226
+
3227
+ // src/xpath/node-tests/node-test-nc.ts
3228
+ var NodeTestNC = class {
3229
+ constructor(nsprefix) {
3230
+ this.regex = new RegExp(`^${nsprefix}:`);
3231
+ this.nsprefix = nsprefix;
3232
+ }
3233
+ evaluate(ctx) {
3234
+ const n = ctx.nodeList[ctx.position];
3235
+ return new BooleanValue(n.nodeName.match(this.regex));
3236
+ }
3237
+ };
3238
+
3239
+ // src/xpath/node-tests/node-test-pi.ts
3240
+ var NodeTestPI = class {
3241
+ constructor(target) {
3242
+ this.target = target;
3243
+ }
3244
+ evaluate(context) {
3245
+ const node = context.nodeList[context.position];
3246
+ return new BooleanValue(
3247
+ node.nodeType == DOM_PROCESSING_INSTRUCTION_NODE && (!this.target || node.nodeName == this.target)
3248
+ );
3249
+ }
3250
+ };
3251
+
3252
+ // src/xpath/node-tests/node-test-text.ts
3253
+ var NodeTestText = class {
3254
+ evaluate(ctx) {
3255
+ return new BooleanValue(ctx.nodeList[ctx.position].nodeType == DOM_TEXT_NODE);
3256
+ }
3257
+ };
3258
+
3259
+ // src/xslt/functions.ts
3260
+ function calculateStepPriority(step) {
3261
+ const nodeTest = step.nodeTest;
3262
+ const hasPredicates = step.predicate && step.predicate.length > 0 || step.predicates && step.predicates.length > 0;
3263
+ if (hasPredicates) {
3264
+ return 0.5;
3265
+ }
3266
+ if (nodeTest && typeof nodeTest === "object" && "type" in nodeTest) {
3267
+ switch (nodeTest.type) {
3268
+ case "wildcard":
3269
+ if (nodeTest.name && nodeTest.name.endsWith(":*")) {
3270
+ return -0.25;
3271
+ }
3272
+ return -0.5;
3273
+ case "node-type":
3274
+ if (nodeTest.nodeType === "processing-instruction" && nodeTest.name) {
3275
+ return 0;
3276
+ }
3277
+ return -0.5;
3278
+ case "processing-instruction":
3279
+ return nodeTest.name ? 0 : -0.5;
3280
+ case "name":
3281
+ return 0;
3282
+ default:
3283
+ return 0;
3284
+ }
3285
+ }
3286
+ if (nodeTest instanceof NodeTestAny) {
3287
+ return -0.5;
3288
+ }
3289
+ if (nodeTest instanceof NodeTestElementOrAttribute) {
3290
+ return -0.5;
3291
+ }
3292
+ if (nodeTest instanceof NodeTestText) {
3293
+ return -0.5;
3294
+ }
3295
+ if (nodeTest instanceof NodeTestComment) {
3296
+ return -0.5;
3297
+ }
3298
+ if (nodeTest instanceof NodeTestPI) {
3299
+ return nodeTest.target ? 0 : -0.5;
3300
+ }
3301
+ if (nodeTest instanceof NodeTestNC) {
3302
+ return -0.25;
3303
+ }
3304
+ if (nodeTest instanceof NodeTestName) {
3305
+ return 0;
3306
+ }
3307
+ return 0;
3308
+ }
3309
+ function calculateLocationPathPriority(expr) {
3310
+ if (!expr.steps || expr.steps.length === 0) {
3311
+ if (expr.absolute) {
3312
+ return -0.5;
3313
+ }
3314
+ return 0;
3315
+ }
3316
+ if (expr.steps.length > 1) {
3317
+ return 0.5;
3318
+ }
3319
+ return calculateStepPriority(expr.steps[0]);
3320
+ }
3321
+ function calculateUnionExprPriority(expr, xPath) {
3322
+ const priority1 = calculateDefaultPriorityFromExpression(expr.expr1, xPath);
3323
+ const priority2 = calculateDefaultPriorityFromExpression(expr.expr2, xPath);
3324
+ return Math.min(priority1, priority2);
3325
+ }
3326
+ function calculateDefaultPriorityFromExpression(expr, xPath) {
3327
+ if (expr instanceof LocationExpr) {
3328
+ return calculateLocationPathPriority(expr);
3329
+ }
3330
+ if (expr instanceof UnionExpr) {
3331
+ return calculateUnionExprPriority(expr, xPath);
3332
+ }
3333
+ return 0.5;
3334
+ }
3335
+ function calculateDefaultPriority(pattern, xPath) {
3336
+ try {
3337
+ const expr = xPath.xPathParse(pattern, "self-and-siblings");
3338
+ return calculateDefaultPriorityFromExpression(expr, xPath);
3339
+ } catch (e) {
3340
+ console.warn(`Failed to parse pattern "${pattern}" for priority calculation:`, e);
3341
+ return 0;
3342
+ }
3343
+ }
3344
+ function matchesMode(template, mode) {
3345
+ const templateMode = template.getAttributeValue("mode");
3346
+ if (!mode) {
3347
+ return !templateMode || templateMode === "#default";
3348
+ }
3349
+ if (mode === "#all") {
3350
+ return true;
3351
+ }
3352
+ if (templateMode === "#all") {
3353
+ return true;
3354
+ }
3355
+ return templateMode === mode;
3356
+ }
3357
+ function isTemplate(node) {
3358
+ if (node.nodeType !== DOM_ELEMENT_NODE) {
3359
+ return false;
3360
+ }
3361
+ if (node.namespaceUri === "http://www.w3.org/1999/XSL/Transform") {
3362
+ return node.localName === "template";
3363
+ }
3364
+ return node.prefix === "xsl" && node.localName === "template";
3365
+ }
3366
+ function collectAndExpandTemplates(stylesheetElement, mode, xPath) {
3367
+ const templates = [];
3368
+ let docOrder = 0;
3369
+ for (const child of stylesheetElement.childNodes) {
3370
+ if (!isTemplate(child)) {
3371
+ continue;
3372
+ }
3373
+ if (!matchesMode(child, mode)) {
3374
+ continue;
3375
+ }
3376
+ const match = child.getAttributeValue("match");
3377
+ if (!match) {
3378
+ continue;
3379
+ }
3380
+ const priorityAttr = child.getAttributeValue("priority");
3381
+ const explicitPriority = priorityAttr ? parseFloat(priorityAttr) : null;
3382
+ const defaultPriority = calculateDefaultPriority(match, xPath);
3383
+ const effectivePriority = explicitPriority !== null && !isNaN(explicitPriority) ? explicitPriority : defaultPriority;
3384
+ templates.push({
3385
+ template: child,
3386
+ explicitPriority: explicitPriority !== null && !isNaN(explicitPriority) ? explicitPriority : null,
3387
+ defaultPriority,
3388
+ effectivePriority,
3389
+ importPrecedence: 0,
3390
+ // TODO: Set properly when xsl:import is fully implemented
3391
+ documentOrder: docOrder++,
3392
+ matchPattern: match
3393
+ });
3394
+ }
3395
+ return templates;
3396
+ }
3397
+ function splitUnionPattern(pattern) {
3398
+ const alternatives = [];
3399
+ let current = "";
3400
+ let depth = 0;
3401
+ let inSingleQuote = false;
3402
+ let inDoubleQuote = false;
3403
+ for (let i = 0; i < pattern.length; i++) {
3404
+ const char = pattern[i];
3405
+ if (char === "'" && !inDoubleQuote) {
3406
+ inSingleQuote = !inSingleQuote;
3407
+ current += char;
3408
+ } else if (char === '"' && !inSingleQuote) {
3409
+ inDoubleQuote = !inDoubleQuote;
3410
+ current += char;
3411
+ } else if (!inSingleQuote && !inDoubleQuote) {
3412
+ if (char === "[" || char === "(") {
3413
+ depth++;
3414
+ current += char;
3415
+ } else if (char === "]" || char === ")") {
3416
+ depth--;
3417
+ current += char;
3418
+ } else if (char === "|" && depth === 0) {
3419
+ alternatives.push(current.trim());
3420
+ current = "";
3421
+ } else {
3422
+ current += char;
3423
+ }
3424
+ } else {
3425
+ current += char;
3426
+ }
3427
+ }
3428
+ if (current.trim()) {
3429
+ alternatives.push(current.trim());
3430
+ }
3431
+ return alternatives;
3432
+ }
3433
+ function nodeMatchesSinglePattern(node, pattern, context, matchResolver, xPath) {
3434
+ if (pattern === "/") {
3435
+ return node.nodeName === "#document";
3436
+ }
3437
+ if (pattern.startsWith("@")) {
3438
+ if (node.nodeType !== 2) {
3439
+ return false;
3440
+ }
3441
+ const attrPattern = pattern.substring(1);
3442
+ if (attrPattern === "*") {
3443
+ return true;
3444
+ }
3445
+ const attrName = node.localName || node.nodeName;
3446
+ const patternLocalName = attrPattern.includes(":") ? attrPattern.substring(attrPattern.indexOf(":") + 1) : attrPattern;
3447
+ return attrName === patternLocalName || node.nodeName === attrPattern;
3448
+ }
3449
+ const nodeContext = context.clone([node], 0);
3450
+ try {
3451
+ const expr = xPath.xPathParse(pattern, "self-and-siblings");
3452
+ const nodes = matchResolver.expressionMatch(expr, nodeContext);
3453
+ if (nodes.some((n) => n.id === node.id)) {
3454
+ return true;
3455
+ }
3456
+ } catch (e) {
3457
+ }
3458
+ if (pattern === "*" && node.nodeType === DOM_ELEMENT_NODE) {
3459
+ return true;
3460
+ }
3461
+ if (pattern.includes("[") || pattern.includes("/")) {
3462
+ try {
3463
+ const rootContext = context.clone([context.root], 0);
3464
+ const descendantPattern = pattern.startsWith("/") ? pattern : "//" + pattern;
3465
+ const expr = xPath.xPathParse(descendantPattern);
3466
+ const nodes = matchResolver.expressionMatch(expr, rootContext);
3467
+ if (nodes.some((n) => n.id === node.id)) {
3468
+ return true;
3469
+ }
3470
+ } catch (e) {
3471
+ }
3472
+ }
3473
+ return false;
3474
+ }
3475
+ function nodeMatchesPattern(node, pattern, context, matchResolver, xPath) {
3476
+ const alternatives = splitUnionPattern(pattern);
3477
+ for (const alt of alternatives) {
3478
+ if (nodeMatchesSinglePattern(node, alt, context, matchResolver, xPath)) {
3479
+ return true;
3480
+ }
3481
+ }
3482
+ return false;
3483
+ }
3484
+ function selectBestTemplate(templates, context, matchResolver, xPath) {
3485
+ const matching = [];
3486
+ const currentNode = context.nodeList[context.position];
3487
+ for (const t of templates) {
3488
+ try {
3489
+ if (nodeMatchesPattern(currentNode, t.matchPattern, context, matchResolver, xPath)) {
3490
+ matching.push(t);
3491
+ }
3492
+ } catch (e) {
3493
+ console.warn(`Failed to match pattern "${t.matchPattern}":`, e);
3494
+ }
3495
+ }
3496
+ if (matching.length === 0) {
3497
+ return {
3498
+ selectedTemplate: null,
3499
+ hasConflict: false,
3500
+ conflictingTemplates: []
3501
+ };
3502
+ }
3503
+ matching.sort((a, b) => {
3504
+ if (a.importPrecedence !== b.importPrecedence) {
3505
+ return b.importPrecedence - a.importPrecedence;
3506
+ }
3507
+ if (a.effectivePriority !== b.effectivePriority) {
3508
+ return b.effectivePriority - a.effectivePriority;
3509
+ }
3510
+ return b.documentOrder - a.documentOrder;
3511
+ });
3512
+ const winner = matching[0];
3513
+ const conflicts = matching.filter(
3514
+ (t) => t.importPrecedence === winner.importPrecedence && t.effectivePriority === winner.effectivePriority
3515
+ );
3516
+ return {
3517
+ selectedTemplate: winner.template,
3518
+ hasConflict: conflicts.length > 1,
3519
+ conflictingTemplates: conflicts.length > 1 ? conflicts : []
3520
+ };
3521
+ }
3522
+ function emitConflictWarning(result, node) {
3523
+ if (!result.hasConflict || result.conflictingTemplates.length < 2) {
3524
+ return;
3525
+ }
3526
+ const patterns = result.conflictingTemplates.map((t) => `"${t.matchPattern}" (priority: ${t.effectivePriority})`).join(", ");
3527
+ console.warn(
3528
+ `XSLT Warning: Ambiguous template match for node <${node.nodeName}>. Multiple templates match with equal priority: ${patterns}. Using the last one in document order.`
3529
+ );
3530
+ }
3531
+
3532
+ // src/xslt/xslt.ts
3533
+ var Xslt = class {
3534
+ constructor(options = {
3535
+ cData: true,
3536
+ escape: true,
3537
+ selfClosingTags: true,
3538
+ parameters: []
3539
+ }) {
3540
+ this.xPath = new XPath();
3541
+ this.xmlParser = new XmlParser();
3542
+ this.matchResolver = new MatchResolver();
3543
+ this.options = {
3544
+ cData: options.cData === true,
3545
+ escape: options.escape === true,
3546
+ selfClosingTags: options.selfClosingTags === true,
3547
+ parameters: options.parameters || []
3548
+ };
3549
+ this.outputMethod = "xml";
3550
+ this.outputOmitXmlDeclaration = "no";
3551
+ this.decimalFormatSettings = {
3552
+ decimalSeparator: ".",
3553
+ groupingSeparator: ",",
3554
+ infinity: "Infinity",
3555
+ minusSign: "-",
3556
+ naN: "NaN",
3557
+ percent: "%",
3558
+ perMille: "\u2030",
3559
+ zeroDigit: "0",
3560
+ digit: "#",
3561
+ patternSeparator: ";"
3562
+ };
3563
+ this.firstTemplateRan = false;
3564
+ }
3565
+ /**
3566
+ * The exported entry point of the XSL-T processor.
3567
+ * @param xmlDoc The input document root, as DOM node.
3568
+ * @param stylesheet The stylesheet document root, as DOM node.
3569
+ * @returns the processed document, as XML text in a string.
3570
+ */
3571
+ xsltProcess(xmlDoc, stylesheet) {
3572
+ return __async(this, null, function* () {
3573
+ const outputDocument = new XDocument();
3574
+ this.outputDocument = outputDocument;
3575
+ const expressionContext = new ExprContext([xmlDoc]);
3576
+ if (this.options.parameters.length > 0) {
3577
+ for (const parameter of this.options.parameters) {
3578
+ expressionContext.setVariable(parameter.name, new StringValue(parameter.value));
3579
+ }
3580
+ }
3581
+ yield this.xsltProcessContext(expressionContext, stylesheet, this.outputDocument);
3582
+ const transformedOutputXml = xmlTransformedText(outputDocument, {
3583
+ cData: this.options.cData,
3584
+ escape: this.options.escape,
3585
+ selfClosingTags: this.options.selfClosingTags,
3586
+ outputMethod: this.outputMethod
3587
+ });
3588
+ return transformedOutputXml;
3589
+ });
3590
+ }
3591
+ /**
3592
+ * The main entry point of the XSL-T processor, as explained on the top of the file.
3593
+ * @param context The input document root, as XPath `ExprContext`.
3594
+ * @param template The stylesheet document root, as DOM node.
3595
+ * @param output If set, the output where the transformation should occur.
3596
+ */
3597
+ xsltProcessContext(context, template, output) {
3598
+ return __async(this, null, function* () {
3599
+ if (!this.isXsltElement(template)) {
3600
+ yield this.xsltPassThrough(context, template, output);
3601
+ } else {
3602
+ let node, select, value, nodes;
3603
+ switch (template.localName) {
3604
+ case "apply-imports":
3605
+ throw new Error(`not implemented: ${template.localName}`);
3606
+ case "apply-templates":
3607
+ yield this.xsltApplyTemplates(context, template, output);
3608
+ break;
3609
+ case "attribute":
3610
+ yield this.xsltAttribute(context, template, output);
3611
+ break;
3612
+ case "attribute-set":
3613
+ throw new Error(`not implemented: ${template.localName}`);
3614
+ case "call-template":
3615
+ yield this.xsltCallTemplate(context, template, output);
3616
+ break;
3617
+ case "choose":
3618
+ yield this.xsltChoose(context, template, output);
3619
+ break;
3620
+ case "comment":
3621
+ yield this.xsltComment(context, template, output);
3622
+ break;
3623
+ case "copy":
3624
+ node = this.xsltCopy(output || this.outputDocument, context.nodeList[context.position]);
3625
+ if (node) {
3626
+ yield this.xsltChildNodes(context, template, node);
3627
+ }
3628
+ break;
3629
+ case "copy-of":
3630
+ select = xmlGetAttribute(template, "select");
3631
+ value = this.xPath.xPathEval(select, context);
3632
+ const destinationNode = output || this.outputDocument;
3633
+ if (value.type === "node-set") {
3634
+ nodes = value.nodeSetValue();
3635
+ for (let i = 0; i < nodes.length; ++i) {
3636
+ this.xsltCopyOf(destinationNode, nodes[i]);
3637
+ }
3638
+ } else {
3639
+ let node2 = domCreateTextNode(this.outputDocument, value.stringValue());
3640
+ node2.siblingPosition = destinationNode.childNodes.length;
3641
+ domAppendChild(destinationNode, node2);
3642
+ }
3643
+ break;
3644
+ case "decimal-format":
3645
+ this.xsltDecimalFormat(context, template);
3646
+ break;
3647
+ case "element":
3648
+ yield this.xsltElement(context, template, output);
3649
+ break;
3650
+ case "fallback":
3651
+ throw new Error(`not implemented: ${template.localName}`);
3652
+ case "for-each":
3653
+ yield this.xsltForEach(context, template, output);
3654
+ break;
3655
+ case "if":
3656
+ yield this.xsltIf(context, template, output);
3657
+ break;
3658
+ case "import":
3659
+ yield this.xsltImport(context, template, output);
3660
+ break;
3661
+ case "include":
3662
+ yield this.xsltInclude(context, template, output);
3663
+ break;
3664
+ case "key":
3665
+ this.xsltKey(context, template);
3666
+ break;
3667
+ case "message":
3668
+ throw new Error(`not implemented: ${template.localName}`);
3669
+ case "namespace-alias":
3670
+ throw new Error(`not implemented: ${template.localName}`);
3671
+ case "number":
3672
+ throw new Error(`not implemented: ${template.localName}`);
3673
+ case "otherwise":
3674
+ throw new Error(`xsl:otherwise can't be used outside of xsl:choose.`);
3675
+ case "output":
3676
+ this.outputMethod = xmlGetAttribute(template, "method");
3677
+ this.outputOmitXmlDeclaration = xmlGetAttribute(template, "omit-xml-declaration");
3678
+ break;
3679
+ case "param":
3680
+ yield this.xsltVariable(context, template, false);
3681
+ break;
3682
+ case "preserve-space":
3683
+ throw new Error(`not implemented: ${template.localName}`);
3684
+ case "processing-instruction":
3685
+ throw new Error(`not implemented: ${template.localName}`);
3686
+ case "sort":
3687
+ this.xsltSort(context, template);
3688
+ break;
3689
+ case "strip-space":
3690
+ throw new Error(`not implemented: ${template.localName}`);
3691
+ case "stylesheet":
3692
+ case "transform":
3693
+ yield this.xsltTransformOrStylesheet(context, template, output);
3694
+ break;
3695
+ case "template":
3696
+ yield this.xsltTemplate(context, template, output);
3697
+ break;
3698
+ case "text":
3699
+ this.xsltText(context, template, output);
3700
+ break;
3701
+ case "value-of":
3702
+ this.xsltValueOf(context, template, output);
3703
+ break;
3704
+ case "variable":
3705
+ yield this.xsltVariable(context, template, true);
3706
+ break;
3707
+ case "when":
3708
+ throw new Error(`xsl:when can't be used outside of xsl:choose.`);
3709
+ case "with-param":
3710
+ throw new Error(`error if here: ${template.localName}`);
3711
+ default:
3712
+ throw new Error(`error if here: ${template.localName}`);
3713
+ }
3714
+ }
3715
+ });
3716
+ }
3717
+ /**
3718
+ * Implements `xsl:apply-templates`.
3719
+ * @param context The Expression Context.
3720
+ * @param template The template.
3721
+ * @param output The output. Only used if there's no corresponding output node already defined.
3722
+ * @protected
3723
+ */
3724
+ xsltApplyTemplates(context, template, output) {
3725
+ return __async(this, null, function* () {
3726
+ const select = xmlGetAttribute(template, "select");
3727
+ let nodes = [];
3728
+ if (select) {
3729
+ nodes = this.xPath.xPathEval(select, context).nodeSetValue();
3730
+ } else {
3731
+ nodes = context.nodeList[context.position].childNodes;
3732
+ }
3733
+ const mode = xmlGetAttribute(template, "mode");
3734
+ const top = template.ownerDocument.documentElement;
3735
+ const expandedTemplates = collectAndExpandTemplates(top, mode, this.xPath);
3736
+ const modifiedContext = context.clone(nodes);
3737
+ for (let j = 0; j < modifiedContext.contextSize(); ++j) {
3738
+ const currentNode = modifiedContext.nodeList[j];
3739
+ if (currentNode.nodeType === DOM_TEXT_NODE) {
3740
+ const textNodeContext = context.clone(
3741
+ [currentNode],
3742
+ 0
3743
+ );
3744
+ this.commonLogicTextNode(textNodeContext, currentNode, output);
3745
+ } else {
3746
+ const clonedContext = modifiedContext.clone(
3747
+ [currentNode],
3748
+ 0
3749
+ );
3750
+ clonedContext.inApplyTemplates = true;
3751
+ const selection = selectBestTemplate(
3752
+ expandedTemplates,
3753
+ clonedContext,
3754
+ this.matchResolver,
3755
+ this.xPath
3756
+ );
3757
+ if (selection.hasConflict) {
3758
+ emitConflictWarning(selection, currentNode);
3759
+ }
3760
+ if (selection.selectedTemplate) {
3761
+ yield this.xsltChildNodes(clonedContext, selection.selectedTemplate, output);
3762
+ }
3763
+ }
3764
+ }
3765
+ });
3766
+ }
3767
+ /**
3768
+ * Implements `xsl:attribute`.
3769
+ * @param context The Expression Context.
3770
+ * @param template The template.
3771
+ * @param output The output. Only used if there's no corresponding output node already defined.
3772
+ * @protected
3773
+ */
3774
+ xsltAttribute(context, template, output) {
3775
+ return __async(this, null, function* () {
3776
+ const nameExpr = xmlGetAttribute(template, "name");
3777
+ const name = this.xsltAttributeValue(nameExpr, context);
3778
+ const documentFragment = domCreateDocumentFragment(this.outputDocument);
3779
+ yield this.xsltChildNodes(context, template, documentFragment);
3780
+ const value = xmlValueLegacyBehavior(documentFragment);
3781
+ if (output) {
3782
+ domSetAttribute(output, name, value);
3783
+ }
3784
+ });
3785
+ }
3786
+ /**
3787
+ * Implements `xsl:call-template`.
3788
+ * @param context The Expression Context.
3789
+ * @param template The template.
3790
+ * @param output The output, used when a fragment is passed by a previous step.
3791
+ */
3792
+ xsltCallTemplate(context, template, output) {
3793
+ return __async(this, null, function* () {
3794
+ const name = xmlGetAttribute(template, "name");
3795
+ const top = template.ownerDocument.documentElement;
3796
+ const paramContext = context.clone();
3797
+ yield this.xsltWithParam(paramContext, template);
3798
+ for (let i = 0; i < top.childNodes.length; ++i) {
3799
+ let childNode = top.childNodes[i];
3800
+ if (childNode.nodeType === DOM_ELEMENT_NODE && this.isXsltElement(childNode, "template") && domGetAttributeValue(childNode, "name") === name) {
3801
+ yield this.xsltChildNodes(paramContext, childNode, output);
3802
+ break;
3803
+ }
3804
+ }
3805
+ });
3806
+ }
3807
+ /**
3808
+ * Implements `xsl:choose`, its child nodes `xsl:when`, and
3809
+ * `xsl:otherwise`.
3810
+ * @param context The Expression Context.
3811
+ * @param template The template.
3812
+ * @param output The output. Only used if there's no corresponding output node already defined.
3813
+ */
3814
+ xsltChoose(context, template, output) {
3815
+ return __async(this, null, function* () {
3816
+ for (const childNode of template.childNodes) {
3817
+ if (childNode.nodeType !== DOM_ELEMENT_NODE) {
3818
+ continue;
3819
+ }
3820
+ if (this.isXsltElement(childNode, "when")) {
3821
+ const test = xmlGetAttribute(childNode, "test");
3822
+ if (this.xPath.xPathEval(test, context).booleanValue()) {
3823
+ yield this.xsltChildNodes(context, childNode, output);
3824
+ break;
3825
+ }
3826
+ } else if (this.isXsltElement(childNode, "otherwise")) {
3827
+ yield this.xsltChildNodes(context, childNode, output);
3828
+ break;
3829
+ }
3830
+ }
3831
+ });
3832
+ }
3833
+ /**
3834
+ * Implements `xsl:copy` for all node types.
3835
+ * @param {XNode} destination the node being copied to, part of output document.
3836
+ * @param {XNode} source the node being copied, part in input document.
3837
+ * @returns {XNode|null} If an element node was created, the element node. Otherwise, null.
3838
+ */
3839
+ xsltCopy(destination, source) {
3840
+ if (source.nodeType == DOM_ELEMENT_NODE) {
3841
+ let node = domCreateElement(this.outputDocument, source.nodeName);
3842
+ if (source.namespaceUri !== null && source.namespaceUri !== void 0) {
3843
+ domSetAttribute(node, "xmlns", source.namespaceUri);
3844
+ }
3845
+ node.siblingPosition = destination.childNodes.length;
3846
+ domAppendChild(destination, node);
3847
+ return node;
3848
+ }
3849
+ if (source.nodeType == DOM_TEXT_NODE) {
3850
+ let node = domCreateTextNode(this.outputDocument, source.nodeValue);
3851
+ node.siblingPosition = destination.childNodes.length;
3852
+ domAppendChild(destination, node);
3853
+ } else if (source.nodeType == DOM_CDATA_SECTION_NODE) {
3854
+ let node = domCreateCDATASection(this.outputDocument, source.nodeValue);
3855
+ node.siblingPosition = destination.childNodes.length;
3856
+ domAppendChild(destination, node);
3857
+ } else if (source.nodeType == DOM_COMMENT_NODE) {
3858
+ let node = domCreateComment(this.outputDocument, source.nodeValue);
3859
+ node.siblingPosition = destination.childNodes.length;
3860
+ domAppendChild(destination, node);
3861
+ } else if (source.nodeType == DOM_ATTRIBUTE_NODE) {
3862
+ domSetAttribute(destination, source.nodeName, source.nodeValue);
3863
+ }
3864
+ return null;
3865
+ }
3866
+ /**
3867
+ * Implements `xsl:comment`.
3868
+ * @param context The Expression Context.
3869
+ * @param template The template.
3870
+ * @param output The output. Only used if there's no corresponding output node already defined.
3871
+ */
3872
+ xsltComment(context, template, output) {
3873
+ return __async(this, null, function* () {
3874
+ const node = domCreateDocumentFragment(this.outputDocument);
3875
+ yield this.xsltChildNodes(context, template, node);
3876
+ const commentData = xmlValue(node);
3877
+ const commentNode = domCreateComment(this.outputDocument, commentData);
3878
+ const resolvedOutput = output || this.outputDocument;
3879
+ resolvedOutput.appendChild(commentNode);
3880
+ });
3881
+ }
3882
+ /**
3883
+ * Implements `xsl:copy-of` for node-set values of the select
3884
+ * expression. Recurses down the source node tree, which is part of
3885
+ * the input document.
3886
+ * @param {XNode} destination the node being copied to, part of output document.
3887
+ * @param {XNode} source the node being copied, part in input document.
3888
+ */
3889
+ xsltCopyOf(destination, source) {
3890
+ if (source.nodeType == DOM_DOCUMENT_FRAGMENT_NODE || source.nodeType == DOM_DOCUMENT_NODE) {
3891
+ for (let i = 0; i < source.childNodes.length; ++i) {
3892
+ this.xsltCopyOf(destination, source.childNodes[i]);
3893
+ }
3894
+ } else {
3895
+ const node = this.xsltCopy(destination, source);
3896
+ if (node) {
3897
+ for (let i = 0; i < source.childNodes.length; ++i) {
3898
+ this.xsltCopyOf(node, source.childNodes[i]);
3899
+ }
3900
+ }
3901
+ }
3902
+ }
3903
+ /**
3904
+ * Implements `xsl:decimal-format`, registering the settings in this instance
3905
+ * and the current context.
3906
+ * @param context The Expression Context.
3907
+ * @param template The template.
3908
+ */
3909
+ xsltDecimalFormat(context, template) {
3910
+ const name = xmlGetAttribute(template, "name");
3911
+ const decimalSeparator = xmlGetAttribute(template, "decimal-separator");
3912
+ const groupingSeparator = xmlGetAttribute(template, "grouping-separator");
3913
+ const infinity = xmlGetAttribute(template, "infinity");
3914
+ const minusSign = xmlGetAttribute(template, "minus-sign");
3915
+ const naN = xmlGetAttribute(template, "NaN");
3916
+ const percent = xmlGetAttribute(template, "percent");
3917
+ const perMille = xmlGetAttribute(template, "per-mille");
3918
+ const zeroDigit = xmlGetAttribute(template, "zero-digit");
3919
+ const digit = xmlGetAttribute(template, "digit");
3920
+ const patternSeparator = xmlGetAttribute(template, "pattern-separator");
3921
+ this.decimalFormatSettings = {
3922
+ name: name || this.decimalFormatSettings.name,
3923
+ decimalSeparator: decimalSeparator || this.decimalFormatSettings.decimalSeparator,
3924
+ groupingSeparator: groupingSeparator || this.decimalFormatSettings.groupingSeparator,
3925
+ infinity: infinity || this.decimalFormatSettings.infinity,
3926
+ minusSign: minusSign || this.decimalFormatSettings.minusSign,
3927
+ naN: naN || this.decimalFormatSettings.naN,
3928
+ percent: percent || this.decimalFormatSettings.percent,
3929
+ perMille: perMille || this.decimalFormatSettings.perMille,
3930
+ zeroDigit: zeroDigit || this.decimalFormatSettings.zeroDigit,
3931
+ digit: digit || this.decimalFormatSettings.digit,
3932
+ patternSeparator: patternSeparator || this.decimalFormatSettings.patternSeparator
3933
+ };
3934
+ context.decimalFormatSettings = this.decimalFormatSettings;
3935
+ }
3936
+ /**
3937
+ * Implements `xsl:element`.
3938
+ * @param context The Expression Context.
3939
+ * @param template The template.
3940
+ */
3941
+ xsltElement(context, template, output) {
3942
+ return __async(this, null, function* () {
3943
+ const nameExpr = xmlGetAttribute(template, "name");
3944
+ const name = this.xsltAttributeValue(nameExpr, context);
3945
+ const node = domCreateElement(this.outputDocument, name);
3946
+ domAppendChild(output || this.outputDocument, node);
3947
+ const clonedContext = context.clone(void 0, 0);
3948
+ yield this.xsltChildNodes(clonedContext, template, node);
3949
+ });
3950
+ }
3951
+ /**
3952
+ * Implements `xsl:for-each`.
3953
+ * @param context The Expression Context.
3954
+ * @param template The template.
3955
+ * @param output The output.
3956
+ */
3957
+ xsltForEach(context, template, output) {
3958
+ return __async(this, null, function* () {
3959
+ const select = xmlGetAttribute(template, "select");
3960
+ const nodes = this.xPath.xPathEval(select, context).nodeSetValue();
3961
+ if (nodes.length === 0) {
3962
+ return;
3963
+ }
3964
+ const sortContext = context.clone(nodes);
3965
+ this.xsltSort(sortContext, template);
3966
+ const nodesWithParent = sortContext.nodeList.filter((n) => n.parentNode !== null && n.parentNode !== void 0);
3967
+ if (nodesWithParent.length <= 0) {
3968
+ throw new Error("Nodes with no parents defined.");
3969
+ }
3970
+ for (let i = 0; i < sortContext.contextSize(); ++i) {
3971
+ yield this.xsltChildNodes(sortContext.clone(sortContext.nodeList, i), template, output);
3972
+ }
3973
+ });
3974
+ }
3975
+ /**
3976
+ * Implements `xsl:if`.
3977
+ * @param context The Expression Context.
3978
+ * @param template The template.
3979
+ * @param output The output.
3980
+ */
3981
+ xsltIf(context, template, output) {
3982
+ return __async(this, null, function* () {
3983
+ const test = xmlGetAttribute(template, "test");
3984
+ if (this.xPath.xPathEval(test, context).booleanValue()) {
3985
+ yield this.xsltChildNodes(context, template, output);
3986
+ }
3987
+ });
3988
+ }
3989
+ /**
3990
+ * Common implementation for `<xsl:import>` and `<xsl:include>`.
3991
+ * @param context The Expression Context.
3992
+ * @param template The template.
3993
+ * @param output The output.
3994
+ * @param isImport Whether this is an import (true) or include (false).
3995
+ */
3996
+ xsltImportOrInclude(context, template, output, isImport) {
3997
+ return __async(this, null, function* () {
3998
+ const elementName = isImport ? "xsl:import" : "xsl:include";
3999
+ const [major, minor] = process.versions.node.split(".").map(Number);
4000
+ if (major <= 17 && minor < 5) {
4001
+ throw new Error(`Your Node.js version does not support \`<${elementName}>\`. If possible, please update your Node.js version to at least version 17.5.0.`);
4002
+ }
4003
+ if (!global.globalThis.fetch) {
4004
+ global.globalThis.fetch = fetch;
4005
+ global.globalThis.Headers = Headers;
4006
+ global.globalThis.Request = Request;
4007
+ global.globalThis.Response = Response;
4008
+ }
4009
+ const hrefAttributeFind = template.childNodes.filter((n) => n.nodeName === "href");
4010
+ if (hrefAttributeFind.length <= 0) {
4011
+ throw new Error(`<${elementName}> with no href attribute defined.`);
4012
+ }
4013
+ const hrefAttribute = hrefAttributeFind[0];
4014
+ const fetchTest = yield global.globalThis.fetch(hrefAttribute.nodeValue);
4015
+ const fetchResponse = yield fetchTest.text();
4016
+ const includedXslt = this.xmlParser.xmlParse(fetchResponse);
4017
+ yield this.xsltChildNodes(context, includedXslt.childNodes[0], output);
4018
+ });
4019
+ }
4020
+ /**
4021
+ * Implements `<xsl:import>`. For now the code is nearly identical to `<xsl:include>`, but there's
4022
+ * no precedence evaluation implemented yet.
4023
+ * @param context The Expression Context.
4024
+ * @param template The template.
4025
+ * @param output The output.
4026
+ */
4027
+ xsltImport(context, template, output) {
4028
+ return __async(this, null, function* () {
4029
+ yield this.xsltImportOrInclude(context, template, output, true);
4030
+ });
4031
+ }
4032
+ /**
4033
+ * Implements `xsl:include`.
4034
+ * @param context The Expression Context.
4035
+ * @param template The template.
4036
+ * @param output The output.
4037
+ */
4038
+ xsltInclude(context, template, output) {
4039
+ return __async(this, null, function* () {
4040
+ yield this.xsltImportOrInclude(context, template, output, false);
4041
+ });
4042
+ }
4043
+ /**
4044
+ * Implements `xsl:key`.
4045
+ * @param context The Expression Context.
4046
+ * @param template The template.
4047
+ */
4048
+ xsltKey(context, template) {
4049
+ const name = xmlGetAttribute(template, "name");
4050
+ const match = xmlGetAttribute(template, "match");
4051
+ const use = xmlGetAttribute(template, "use");
4052
+ if (!name || !match || !use) {
4053
+ let errorMessage = "<xsl:key> missing required parameters: ";
4054
+ if (!name) {
4055
+ errorMessage += "name, ";
4056
+ }
4057
+ if (!match) {
4058
+ errorMessage += "match, ";
4059
+ }
4060
+ if (!use) {
4061
+ errorMessage += "use, ";
4062
+ }
4063
+ errorMessage = errorMessage.slice(0, -2);
4064
+ throw new Error(errorMessage);
4065
+ }
4066
+ let keyContext;
4067
+ if (context.nodeList[context.position].nodeName === "#document") {
4068
+ keyContext = context.clone(context.nodeList[context.position].childNodes);
4069
+ } else {
4070
+ keyContext = context;
4071
+ }
4072
+ const nodes = this.xsltMatch(match, keyContext);
4073
+ if (!(name in context.keys)) {
4074
+ context.keys[name] = {};
4075
+ }
4076
+ for (const node of nodes) {
4077
+ const nodeContext = context.clone([node]);
4078
+ const attribute = this.xPath.xPathEval(use, nodeContext);
4079
+ const attributeValue = attribute.stringValue();
4080
+ context.keys[name][attributeValue] = new NodeSetValue([node]);
4081
+ }
4082
+ }
4083
+ /**
4084
+ * Orders the current node list in the input context according to the
4085
+ * sort order specified by xsl:sort child nodes of the current
4086
+ * template node. This happens before the operation specified by the
4087
+ * current template node is executed.
4088
+ * @param context The expression context.
4089
+ * @param template The template node.
4090
+ * @todo case-order is not implemented.
4091
+ */
4092
+ xsltSort(context, template) {
4093
+ const sort = [];
4094
+ for (const childNode of template.childNodes) {
4095
+ if (childNode.nodeType == DOM_ELEMENT_NODE && this.isXsltElement(childNode, "sort")) {
4096
+ const select = xmlGetAttribute(childNode, "select");
4097
+ const expression = this.xPath.xPathParse(select);
4098
+ const type = xmlGetAttribute(childNode, "data-type") || "text";
4099
+ const order = xmlGetAttribute(childNode, "order") || "ascending";
4100
+ sort.push({
4101
+ expr: expression,
4102
+ type,
4103
+ order
4104
+ });
4105
+ }
4106
+ }
4107
+ this.xPath.xPathSort(context, sort);
4108
+ }
4109
+ /**
4110
+ * Implements `xsl:template`.
4111
+ * @param context The Expression Context.
4112
+ * @param template The `<xsl:template>` node.
4113
+ * @param output The output. In general, a fragment that will be used by
4114
+ * the caller.
4115
+ */
4116
+ xsltTemplate(context, template, output) {
4117
+ return __async(this, null, function* () {
4118
+ if (!context.inApplyTemplates && context.baseTemplateMatched) {
4119
+ return;
4120
+ }
4121
+ const match = xmlGetAttribute(template, "match");
4122
+ if (!match) return;
4123
+ const nodes = this.xsltMatch(match, context, "self-and-siblings");
4124
+ if (nodes.length > 0) {
4125
+ this.firstTemplateRan = true;
4126
+ if (!context.inApplyTemplates) {
4127
+ context.baseTemplateMatched = true;
4128
+ }
4129
+ const templateContext = context.clone(nodes, 0);
4130
+ yield this.xsltChildNodes(templateContext, template, output);
4131
+ }
4132
+ });
4133
+ }
4134
+ xsltText(context, template, output) {
4135
+ const text = xmlValue(template);
4136
+ const node = domCreateTextNode(this.outputDocument, text);
4137
+ const disableOutputEscaping = template.childNodes.filter(
4138
+ (a) => a.nodeType === DOM_ATTRIBUTE_NODE && a.nodeName === "disable-output-escaping"
4139
+ );
4140
+ if (disableOutputEscaping.length > 0 && disableOutputEscaping[0].nodeValue === "yes") {
4141
+ node.escape = false;
4142
+ }
4143
+ const destinationTextNode = output || this.outputDocument;
4144
+ destinationTextNode.appendChild(node);
4145
+ }
4146
+ /**
4147
+ * Implements `<xsl:stylesheet>` and `<xsl:transform>`, and its corresponding
4148
+ * validations.
4149
+ * @param context The Expression Context.
4150
+ * @param template The `<xsl:stylesheet>` or `<xsl:transform>` node.
4151
+ * @param output The output. In general, a fragment that will be used by
4152
+ * the caller.
4153
+ */
4154
+ xsltTransformOrStylesheet(context, template, output) {
4155
+ return __async(this, null, function* () {
4156
+ for (let stylesheetAttribute of template.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE)) {
4157
+ switch (stylesheetAttribute.nodeName) {
4158
+ case "version":
4159
+ this.version = stylesheetAttribute.nodeValue;
4160
+ if (!["1.0", "2.0", "3.0"].includes(this.version)) {
4161
+ throw new Error(
4162
+ `XSLT version not defined or invalid. Actual resolved version: ${this.version || "(none)"}.`
4163
+ );
4164
+ }
4165
+ context.xsltVersion = this.version;
4166
+ break;
4167
+ default:
4168
+ if (stylesheetAttribute.prefix === "xmlns") {
4169
+ context.knownNamespaces[stylesheetAttribute.localName] = stylesheetAttribute.nodeValue;
4170
+ }
4171
+ break;
4172
+ }
4173
+ }
4174
+ let importsDone = false;
4175
+ for (const child of template.childNodes) {
4176
+ if (child.nodeType === DOM_ELEMENT_NODE) {
4177
+ if (this.isXsltElement(child, "import")) {
4178
+ if (importsDone) {
4179
+ throw new Error("<xsl:import> should be the first child node of <xsl:stylesheet> or <xsl:transform>.");
4180
+ }
4181
+ } else {
4182
+ importsDone = true;
4183
+ }
4184
+ }
4185
+ }
4186
+ const nonTemplates = [];
4187
+ const templates = [];
4188
+ for (const child of template.childNodes) {
4189
+ if (child.nodeType === DOM_ELEMENT_NODE && this.isXsltElement(child, "template")) {
4190
+ templates.push(child);
4191
+ } else {
4192
+ nonTemplates.push(child);
4193
+ }
4194
+ }
4195
+ const contextClone = context.clone();
4196
+ for (const child of nonTemplates) {
4197
+ yield this.xsltProcessContext(contextClone, child, output);
4198
+ }
4199
+ if (templates.length > 0) {
4200
+ const expandedTemplates = collectAndExpandTemplates(template, null, this.xPath);
4201
+ const matchCandidates = [];
4202
+ for (const t of expandedTemplates) {
4203
+ try {
4204
+ const matchedNodes = this.xsltMatch(t.matchPattern, contextClone);
4205
+ if (matchedNodes.length > 0) {
4206
+ matchCandidates.push({ priority: t, matchedNodes });
4207
+ }
4208
+ } catch (e) {
4209
+ console.warn(`Failed to match pattern "${t.matchPattern}":`, e);
4210
+ }
4211
+ }
4212
+ if (matchCandidates.length > 0) {
4213
+ matchCandidates.sort((a, b) => {
4214
+ if (a.priority.importPrecedence !== b.priority.importPrecedence) {
4215
+ return b.priority.importPrecedence - a.priority.importPrecedence;
4216
+ }
4217
+ if (a.priority.effectivePriority !== b.priority.effectivePriority) {
4218
+ return b.priority.effectivePriority - a.priority.effectivePriority;
4219
+ }
4220
+ return b.priority.documentOrder - a.priority.documentOrder;
4221
+ });
4222
+ const winner = matchCandidates[0];
4223
+ const conflicts = matchCandidates.filter(
4224
+ (t) => t.priority.importPrecedence === winner.priority.importPrecedence && t.priority.effectivePriority === winner.priority.effectivePriority
4225
+ );
4226
+ if (conflicts.length > 1) {
4227
+ const patterns = conflicts.map((t) => `"${t.priority.matchPattern}" (priority: ${t.priority.effectivePriority})`).join(", ");
4228
+ console.warn(
4229
+ `XSLT Warning: Ambiguous template match. Multiple templates match with equal priority: ${patterns}. Using the last one in document order.`
4230
+ );
4231
+ }
4232
+ this.firstTemplateRan = true;
4233
+ contextClone.baseTemplateMatched = true;
4234
+ const templateContext = contextClone.clone(winner.matchedNodes, 0);
4235
+ yield this.xsltChildNodes(templateContext, winner.priority.template, output);
4236
+ }
4237
+ }
4238
+ });
4239
+ }
4240
+ xsltValueOf(context, template, output) {
4241
+ const select = xmlGetAttribute(template, "select");
4242
+ const attribute = this.xPath.xPathEval(select, context);
4243
+ const value = attribute.stringValue();
4244
+ const node = domCreateTextNode(this.outputDocument, value);
4245
+ const targetOutput = output || this.outputDocument;
4246
+ node.siblingPosition = targetOutput.childNodes.length;
4247
+ targetOutput.appendChild(node);
4248
+ }
4249
+ /**
4250
+ * Evaluates a variable or parameter and set it in the current input
4251
+ * context. Implements `xsl:variable`, `xsl:param`, and `xsl:with-param`.
4252
+ *
4253
+ * @param context The expression context.
4254
+ * @param template The template node.
4255
+ * @param override flag that defines if the value computed here
4256
+ * overrides the one already in the input context if that is the
4257
+ * case. I.e. decides if this is a default value or a local
4258
+ * value. `xsl:variable` and `xsl:with-param` override; `xsl:param` doesn't.
4259
+ */
4260
+ xsltVariable(context, template, override) {
4261
+ return __async(this, null, function* () {
4262
+ const name = xmlGetAttribute(template, "name");
4263
+ const select = xmlGetAttribute(template, "select");
4264
+ let value;
4265
+ const nonAttributeChildren = template.childNodes.filter((n) => n.nodeType !== DOM_ATTRIBUTE_NODE);
4266
+ if (nonAttributeChildren.length > 0) {
4267
+ const fragment = domCreateDocumentFragment(template.ownerDocument);
4268
+ yield this.xsltChildNodes(context, template, fragment);
4269
+ value = new NodeSetValue([fragment]);
4270
+ } else if (select) {
4271
+ value = this.xPath.xPathEval(select, context);
4272
+ } else {
4273
+ let parameterValue = "";
4274
+ const filteredParameter = this.options.parameters.filter((p) => p.name === name);
4275
+ if (filteredParameter.length > 0) {
4276
+ parameterValue = filteredParameter[0].value;
4277
+ }
4278
+ value = new StringValue(parameterValue);
4279
+ }
4280
+ if (override || !context.getVariable(name)) {
4281
+ context.setVariable(name, value);
4282
+ }
4283
+ });
4284
+ }
4285
+ /**
4286
+ * Traverses the template node tree. Calls the main processing
4287
+ * function with the current input context for every child node of the
4288
+ * current template node.
4289
+ * @param context Normally the Expression Context.
4290
+ * @param template The XSL-T definition.
4291
+ * @param output If set, the output where the transformation should occur.
4292
+ */
4293
+ xsltChildNodes(context, template, output) {
4294
+ return __async(this, null, function* () {
4295
+ const contextClone = context.clone();
4296
+ for (let i = 0; i < template.childNodes.length; ++i) {
4297
+ yield this.xsltProcessContext(contextClone, template.childNodes[i], output);
4298
+ }
4299
+ });
4300
+ }
4301
+ /**
4302
+ * This logic is used in two different places:
4303
+ * - `xsltPassThrough`, if the template asks this library to write a text node;
4304
+ * - `xsltProcessContext`, `apply-templates` operation, when the current node is text.
4305
+ *
4306
+ * Text nodes always require a parent, and they never have children.
4307
+ * @param context The Expression Context.
4308
+ * @param template The template, that contains the node value to be written.
4309
+ * @param output The output.
4310
+ */
4311
+ commonLogicTextNode(context, template, output) {
4312
+ if (output) {
4313
+ let node = domCreateTextNode(this.outputDocument, template.nodeValue);
4314
+ node.siblingPosition = output.childNodes.length;
4315
+ domAppendChild(output, node);
4316
+ }
4317
+ }
4318
+ /**
4319
+ * Passes template text to the output. The current template node does
4320
+ * not specify an XSL-T operation and therefore is appended to the
4321
+ * output with all its attributes. Then continues traversing the
4322
+ * template node tree.
4323
+ * @param context The Expression Context.
4324
+ * @param template The XSLT stylesheet or transformation.
4325
+ * @param output The output.
4326
+ */
4327
+ xsltPassThrough(context, template, output) {
4328
+ return __async(this, null, function* () {
4329
+ switch (template.nodeType) {
4330
+ case DOM_TEXT_NODE:
4331
+ if (this.xsltPassText(template)) {
4332
+ this.commonLogicTextNode(context, template, output);
4333
+ }
4334
+ break;
4335
+ case DOM_ELEMENT_NODE:
4336
+ let node;
4337
+ let elementContext = context;
4338
+ node = context.nodeList[context.position];
4339
+ let newNode;
4340
+ newNode = domCreateElement(this.outputDocument, template.nodeName);
4341
+ newNode.siblingPosition = node.siblingPosition;
4342
+ domAppendChild(output || this.outputDocument, newNode);
4343
+ yield this.xsltChildNodes(elementContext, template, newNode);
4344
+ const templateAttributes = template.childNodes.filter((a) => (a == null ? void 0 : a.nodeType) === DOM_ATTRIBUTE_NODE);
4345
+ for (const attribute of templateAttributes) {
4346
+ const name = attribute.nodeName;
4347
+ const value = this.xsltAttributeValue(attribute.nodeValue, elementContext);
4348
+ domSetAttribute(newNode, name, value);
4349
+ }
4350
+ break;
4351
+ default:
4352
+ yield this.xsltChildNodes(context, template, output);
4353
+ }
4354
+ });
4355
+ }
4356
+ /**
4357
+ * Determines if a text node in the XSLT template document is to be
4358
+ * stripped according to XSLT whitespace stripping rules.
4359
+ * @see [XSLT], section 3.4.
4360
+ * @param template The XSLT template.
4361
+ * @returns TODO
4362
+ * @todo Whitespace stripping on the input document is
4363
+ * currently not implemented.
4364
+ */
4365
+ xsltPassText(template) {
4366
+ if (!template.nodeValue.match(/^\s*$/)) {
4367
+ return true;
4368
+ }
4369
+ let element = template.parentNode;
4370
+ if (this.isXsltElement(element, "text")) {
4371
+ return true;
4372
+ }
4373
+ while (element && element.nodeType == DOM_ELEMENT_NODE) {
4374
+ const xmlspace = domGetAttributeValue(element, "xml:space");
4375
+ if (xmlspace) {
4376
+ if (xmlspace == "default") {
4377
+ return false;
4378
+ }
4379
+ if (xmlspace == "preserve") {
4380
+ return true;
4381
+ }
4382
+ }
4383
+ element = element.parentNode;
4384
+ }
4385
+ return false;
4386
+ }
4387
+ findAttributeInContext(attributeName, context) {
4388
+ return context.nodeList[context.position].childNodes.find(
4389
+ (a) => a.nodeType === DOM_ATTRIBUTE_NODE && a.nodeName === attributeName
4390
+ );
4391
+ }
4392
+ /**
4393
+ * Evaluates an XSL-T attribute value template. Attribute value
4394
+ * templates are attributes on XSL-T elements that contain XPath
4395
+ * expressions in braces {}. The XSL-T expressions are evaluated in
4396
+ * the current input context.
4397
+ * @param value TODO
4398
+ * @param context TODO
4399
+ * @returns TODO
4400
+ */
4401
+ xsltAttributeValue(value, context) {
4402
+ const parts = value.split("{");
4403
+ if (parts.length === 1) {
4404
+ return value;
4405
+ }
4406
+ let ret = "";
4407
+ for (let i = 0; i < parts.length; ++i) {
4408
+ const rp = parts[i].split("}");
4409
+ if (rp.length != 2) {
4410
+ ret += parts[i];
4411
+ continue;
4412
+ }
4413
+ const val = this.xPath.xPathEval(rp[0], context).stringValue();
4414
+ ret += val + rp[1];
4415
+ }
4416
+ return ret;
4417
+ }
4418
+ /**
4419
+ * Evaluates an XPath expression in the current input context as a
4420
+ * match.
4421
+ * @see [XSLT] section 5.2, paragraph 1
4422
+ * @param match TODO
4423
+ * @param context The Expression Context.
4424
+ * @param axis The XPath axis. Used when the match does not start with the parent.
4425
+ * @returns {XNode[]} A list of the found nodes.
4426
+ */
4427
+ xsltMatch(match, context, axis) {
4428
+ const expression = this.xPath.xPathParse(match, axis);
4429
+ return this.matchResolver.expressionMatch(expression, context);
4430
+ }
4431
+ /**
4432
+ * Sets parameters defined by xsl:with-param child nodes of the
4433
+ * current template node, in the current input context. This happens
4434
+ * before the operation specified by the current template node is
4435
+ * executed.
4436
+ * @param context The Expression Context.
4437
+ * @param template The template node.
4438
+ */
4439
+ xsltWithParam(context, template) {
4440
+ return __async(this, null, function* () {
4441
+ for (const childNode of template.childNodes) {
4442
+ if (childNode.nodeType === DOM_ELEMENT_NODE && this.isXsltElement(childNode, "with-param")) {
4443
+ yield this.xsltVariable(context, childNode, true);
4444
+ }
4445
+ }
4446
+ });
4447
+ }
4448
+ /**
4449
+ * Test if the given element is an XSLT element, optionally the one with the given name.
4450
+ * @param {XNode} element The element.
4451
+ * @param {string} opt_wantedName The name for comparison.
4452
+ * @returns True, if element is an XSL node. False otherwise.
4453
+ */
4454
+ isXsltElement(element, opt_wantedName) {
4455
+ if (opt_wantedName && element.localName != opt_wantedName) return false;
4456
+ if (element.namespaceUri) return element.namespaceUri === "http://www.w3.org/1999/XSL/Transform";
4457
+ return element.prefix === "xsl";
4458
+ }
4459
+ };
4460
+ // Annotate the CommonJS export names for ESM import in node:
4461
+ 0 && (module.exports = {
4462
+ ExprContext,
4463
+ XPath,
4464
+ XmlParser,
4465
+ Xslt,
4466
+ xmlEscapeText
4467
+ });
13
4468
  //# sourceMappingURL=index.js.map