@tradik/xslt3 0.0.0-stage → 1.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 (286) hide show
  1. package/LICENSE.md +28 -0
  2. package/README.md +98 -2
  3. package/package.json +43 -4
  4. package/src/errors.js +20 -0
  5. package/src/functions/aggregates.js +144 -0
  6. package/src/functions/arraySort.js +33 -0
  7. package/src/functions/arrays.js +181 -0
  8. package/src/functions/attributeTypes.js +58 -0
  9. package/src/functions/baseUris.js +82 -0
  10. package/src/functions/collations.js +127 -0
  11. package/src/functions/collections.js +84 -0
  12. package/src/functions/context.js +83 -0
  13. package/src/functions/core.js +167 -0
  14. package/src/functions/datetime.js +203 -0
  15. package/src/functions/deepEqual.js +132 -0
  16. package/src/functions/diagnostics.js +88 -0
  17. package/src/functions/focus.js +34 -0
  18. package/src/functions/format/dateComponents.js +176 -0
  19. package/src/functions/format/datePicture.js +115 -0
  20. package/src/functions/format/decimalFormat.js +65 -0
  21. package/src/functions/format/digitPattern.js +145 -0
  22. package/src/functions/format/formatDateTime.js +204 -0
  23. package/src/functions/format/formatInteger.js +109 -0
  24. package/src/functions/format/formatNumber.js +165 -0
  25. package/src/functions/format/fractionFormat.js +80 -0
  26. package/src/functions/format/germanWords.js +89 -0
  27. package/src/functions/format/numberLanguages.js +41 -0
  28. package/src/functions/format/numberPicture.js +202 -0
  29. package/src/functions/format/numberWords.js +155 -0
  30. package/src/functions/format/place.js +74 -0
  31. package/src/functions/format/timezoneFormat.js +89 -0
  32. package/src/functions/higherOrder.js +106 -0
  33. package/src/functions/ids.js +127 -0
  34. package/src/functions/json/index.js +17 -0
  35. package/src/functions/json/jsonChars.js +110 -0
  36. package/src/functions/json/jsonParser.js +203 -0
  37. package/src/functions/json/jsonStrings.js +116 -0
  38. package/src/functions/json/jsonToXml.js +116 -0
  39. package/src/functions/json/parseJson.js +119 -0
  40. package/src/functions/json/xmlRepresentation.js +103 -0
  41. package/src/functions/json/xmlToJson.js +147 -0
  42. package/src/functions/library.js +47 -0
  43. package/src/functions/mapArrayEqual.js +41 -0
  44. package/src/functions/maps.js +152 -0
  45. package/src/functions/math.js +73 -0
  46. package/src/functions/nodePaths.js +181 -0
  47. package/src/functions/nodes.js +199 -0
  48. package/src/functions/numeric.js +148 -0
  49. package/src/functions/options.js +58 -0
  50. package/src/functions/parseIetfDate.js +104 -0
  51. package/src/functions/parseXml.js +77 -0
  52. package/src/functions/qnames.js +68 -0
  53. package/src/functions/random.js +128 -0
  54. package/src/functions/regex/analyzeString.js +144 -0
  55. package/src/functions/regex/charClass.js +112 -0
  56. package/src/functions/regex/compile.js +81 -0
  57. package/src/functions/regex/escapes.js +109 -0
  58. package/src/functions/regex/parser.js +169 -0
  59. package/src/functions/regex/reader.js +37 -0
  60. package/src/functions/regex/regexFunctions.js +140 -0
  61. package/src/functions/regex/translate.js +102 -0
  62. package/src/functions/regex/unicodeBlocks.js +194 -0
  63. package/src/functions/registry.js +140 -0
  64. package/src/functions/sequences.js +173 -0
  65. package/src/functions/serializeFunction.js +53 -0
  66. package/src/functions/signatures.js +105 -0
  67. package/src/functions/sort.js +102 -0
  68. package/src/functions/stringMatch.js +45 -0
  69. package/src/functions/strings.js +194 -0
  70. package/src/functions/stringsCore.js +66 -0
  71. package/src/functions/support.js +106 -0
  72. package/src/functions/textDecoding.js +117 -0
  73. package/src/functions/ucaCollation.js +127 -0
  74. package/src/functions/unparsedText.js +71 -0
  75. package/src/functions/uri.js +166 -0
  76. package/src/functions/xqueryModule.js +24 -0
  77. package/src/index.js +38 -0
  78. package/src/items/array.js +84 -0
  79. package/src/items/function.js +45 -0
  80. package/src/items/map.js +120 -0
  81. package/src/items/mapKey.js +82 -0
  82. package/src/serialize/index.js +129 -0
  83. package/src/serialize/markup/content.js +74 -0
  84. package/src/serialize/markup/dialect.js +178 -0
  85. package/src/serialize/markup/htmlData.js +70 -0
  86. package/src/serialize/markup/namespaces.js +145 -0
  87. package/src/serialize/markup/prolog.js +91 -0
  88. package/src/serialize/markup/writer.js +183 -0
  89. package/src/serialize/methods/adaptive.js +131 -0
  90. package/src/serialize/methods/json.js +158 -0
  91. package/src/serialize/methods/text.js +43 -0
  92. package/src/serialize/output/buffer.js +48 -0
  93. package/src/serialize/output/encoding.js +146 -0
  94. package/src/serialize/output/expander.js +204 -0
  95. package/src/serialize/params/fromElement.js +141 -0
  96. package/src/serialize/params/fromMap.js +128 -0
  97. package/src/serialize/params/names.js +69 -0
  98. package/src/serialize/params/settings.js +153 -0
  99. package/src/serialize/params/values.js +163 -0
  100. package/src/serialize/sequence.js +111 -0
  101. package/src/xdm/arithmetic.js +155 -0
  102. package/src/xdm/atomic.js +142 -0
  103. package/src/xdm/binary.js +92 -0
  104. package/src/xdm/calendar.js +71 -0
  105. package/src/xdm/cast.js +176 -0
  106. package/src/xdm/compare.js +192 -0
  107. package/src/xdm/datetime.js +206 -0
  108. package/src/xdm/decimal.js +200 -0
  109. package/src/xdm/duration.js +128 -0
  110. package/src/xdm/generalCompare.js +152 -0
  111. package/src/xdm/index.js +47 -0
  112. package/src/xdm/lexical.js +126 -0
  113. package/src/xdm/nodes.js +170 -0
  114. package/src/xdm/numeric.js +122 -0
  115. package/src/xdm/qname.js +65 -0
  116. package/src/xdm/strings.js +52 -0
  117. package/src/xdm/temporalArithmetic.js +180 -0
  118. package/src/xdm/timeline.js +68 -0
  119. package/src/xdm/types.js +178 -0
  120. package/src/xpath/eval/atomics.js +45 -0
  121. package/src/xpath/eval/axes.js +212 -0
  122. package/src/xpath/eval/calls.js +168 -0
  123. package/src/xpath/eval/coercion.js +146 -0
  124. package/src/xpath/eval/compiler.js +71 -0
  125. package/src/xpath/eval/constructors.js +129 -0
  126. package/src/xpath/eval/decimalFormats.js +93 -0
  127. package/src/xpath/eval/descendantMemo.js +77 -0
  128. package/src/xpath/eval/documentOrder.js +142 -0
  129. package/src/xpath/eval/domNodes.js +174 -0
  130. package/src/xpath/eval/dynamicCall.js +27 -0
  131. package/src/xpath/eval/dynamicContext.js +161 -0
  132. package/src/xpath/eval/flow.js +115 -0
  133. package/src/xpath/eval/functionItems.js +194 -0
  134. package/src/xpath/eval/groupedChildren.js +88 -0
  135. package/src/xpath/eval/inline.js +71 -0
  136. package/src/xpath/eval/namespaceNodes.js +90 -0
  137. package/src/xpath/eval/nodeTests.js +164 -0
  138. package/src/xpath/eval/operators.js +190 -0
  139. package/src/xpath/eval/paths.js +163 -0
  140. package/src/xpath/eval/positional.js +81 -0
  141. package/src/xpath/eval/predicates.js +56 -0
  142. package/src/xpath/eval/primary.js +99 -0
  143. package/src/xpath/eval/resources.js +149 -0
  144. package/src/xpath/eval/scope.js +108 -0
  145. package/src/xpath/eval/sequenceType.js +193 -0
  146. package/src/xpath/eval/staticContext.js +142 -0
  147. package/src/xpath/eval/steps.js +98 -0
  148. package/src/xpath/eval/subtype.js +154 -0
  149. package/src/xpath/eval/typeExprs.js +147 -0
  150. package/src/xpath/eval/typeNames.js +101 -0
  151. package/src/xpath/eval/uris.js +21 -0
  152. package/src/xpath/eval/values.js +64 -0
  153. package/src/xpath/index.js +217 -0
  154. package/src/xpath/syntax/ast.js +130 -0
  155. package/src/xpath/syntax/chars.js +58 -0
  156. package/src/xpath/syntax/constructors.js +144 -0
  157. package/src/xpath/syntax/expressions.js +107 -0
  158. package/src/xpath/syntax/index.js +44 -0
  159. package/src/xpath/syntax/kindTests.js +134 -0
  160. package/src/xpath/syntax/lexer.js +220 -0
  161. package/src/xpath/syntax/operators.js +111 -0
  162. package/src/xpath/syntax/paths.js +102 -0
  163. package/src/xpath/syntax/postfix.js +91 -0
  164. package/src/xpath/syntax/primaries.js +149 -0
  165. package/src/xpath/syntax/steps.js +146 -0
  166. package/src/xpath/syntax/syntaxError.js +31 -0
  167. package/src/xpath/syntax/tokenStream.js +163 -0
  168. package/src/xpath/syntax/typeAst.js +76 -0
  169. package/src/xpath/syntax/typeOperators.js +127 -0
  170. package/src/xpath/syntax/types.js +158 -0
  171. package/src/xslt/api.js +153 -0
  172. package/src/xslt/compiler/acceptance.js +178 -0
  173. package/src/xslt/compiler/accumulatorDecl.js +146 -0
  174. package/src/xslt/compiler/attributeValues.js +174 -0
  175. package/src/xslt/compiler/attributes.js +211 -0
  176. package/src/xslt/compiler/avt.js +103 -0
  177. package/src/xslt/compiler/body.js +154 -0
  178. package/src/xslt/compiler/children.js +105 -0
  179. package/src/xslt/compiler/compatibility.js +130 -0
  180. package/src/xslt/compiler/components.js +179 -0
  181. package/src/xslt/compiler/contextItem.js +95 -0
  182. package/src/xslt/compiler/decimalFormats.js +132 -0
  183. package/src/xslt/compiler/declarationKinds.js +82 -0
  184. package/src/xslt/compiler/elementInfo.js +246 -0
  185. package/src/xslt/compiler/expressions.js +175 -0
  186. package/src/xslt/compiler/globalContextItem.js +92 -0
  187. package/src/xslt/compiler/globals.js +209 -0
  188. package/src/xslt/compiler/linker.js +134 -0
  189. package/src/xslt/compiler/miscDecl.js +171 -0
  190. package/src/xslt/compiler/modeDecl.js +88 -0
  191. package/src/xslt/compiler/moduleLoading.js +111 -0
  192. package/src/xslt/compiler/modules.js +158 -0
  193. package/src/xslt/compiler/outputDecl.js +209 -0
  194. package/src/xslt/compiler/overrideLinks.js +141 -0
  195. package/src/xslt/compiler/packageChecks.js +84 -0
  196. package/src/xslt/compiler/packageRegistry.js +95 -0
  197. package/src/xslt/compiler/packageTable.js +181 -0
  198. package/src/xslt/compiler/packageVersions.js +143 -0
  199. package/src/xslt/compiler/packages.js +138 -0
  200. package/src/xslt/compiler/registry.js +234 -0
  201. package/src/xslt/compiler/staticStage.js +197 -0
  202. package/src/xslt/compiler/staticVariables.js +93 -0
  203. package/src/xslt/compiler/stylesheet.js +205 -0
  204. package/src/xslt/compiler/tailPosition.js +74 -0
  205. package/src/xslt/compiler/templatesDecl.js +180 -0
  206. package/src/xslt/compiler/useAccumulators.js +76 -0
  207. package/src/xslt/compiler/useWhen.js +94 -0
  208. package/src/xslt/compiler/visibility.js +160 -0
  209. package/src/xslt/index.js +11 -0
  210. package/src/xslt/instructions/analyzeString.js +137 -0
  211. package/src/xslt/instructions/assert.js +72 -0
  212. package/src/xslt/instructions/attributeSets.js +115 -0
  213. package/src/xslt/instructions/conditional.js +99 -0
  214. package/src/xslt/instructions/control.js +123 -0
  215. package/src/xslt/instructions/copy.js +151 -0
  216. package/src/xslt/instructions/elements.js +161 -0
  217. package/src/xslt/instructions/evaluate.js +189 -0
  218. package/src/xslt/instructions/fork.js +35 -0
  219. package/src/xslt/instructions/grouping.js +106 -0
  220. package/src/xslt/instructions/index.js +94 -0
  221. package/src/xslt/instructions/iterate.js +182 -0
  222. package/src/xslt/instructions/literal.js +142 -0
  223. package/src/xslt/instructions/maps.js +72 -0
  224. package/src/xslt/instructions/merge.js +190 -0
  225. package/src/xslt/instructions/number.js +205 -0
  226. package/src/xslt/instructions/output.js +102 -0
  227. package/src/xslt/instructions/params.js +110 -0
  228. package/src/xslt/instructions/resultDocument.js +143 -0
  229. package/src/xslt/instructions/sort.js +114 -0
  230. package/src/xslt/instructions/sourceDocument.js +73 -0
  231. package/src/xslt/instructions/templates.js +153 -0
  232. package/src/xslt/instructions/text.js +151 -0
  233. package/src/xslt/instructions/try.js +186 -0
  234. package/src/xslt/instructions/variables.js +119 -0
  235. package/src/xslt/names.js +204 -0
  236. package/src/xslt/patterns/axisOrigins.js +121 -0
  237. package/src/xslt/patterns/compile.js +151 -0
  238. package/src/xslt/patterns/general.js +132 -0
  239. package/src/xslt/patterns/grammar.js +190 -0
  240. package/src/xslt/patterns/modes.js +153 -0
  241. package/src/xslt/patterns/paths.js +130 -0
  242. package/src/xslt/patterns/patternChecks.js +29 -0
  243. package/src/xslt/patterns/steps.js +162 -0
  244. package/src/xslt/processor.js +178 -0
  245. package/src/xslt/runtime/accumulatorFunctions.js +48 -0
  246. package/src/xslt/runtime/accumulators.js +174 -0
  247. package/src/xslt/runtime/apply.js +153 -0
  248. package/src/xslt/runtime/atomicKeys.js +36 -0
  249. package/src/xslt/runtime/availability.js +162 -0
  250. package/src/xslt/runtime/baseUri.js +64 -0
  251. package/src/xslt/runtime/compilerHook.js +27 -0
  252. package/src/xslt/runtime/conditional.js +110 -0
  253. package/src/xslt/runtime/context.js +106 -0
  254. package/src/xslt/runtime/copy.js +123 -0
  255. package/src/xslt/runtime/copyFunctions.js +71 -0
  256. package/src/xslt/runtime/copyOrigins.js +60 -0
  257. package/src/xslt/runtime/defaultMethod.js +42 -0
  258. package/src/xslt/runtime/documentContent.js +93 -0
  259. package/src/xslt/runtime/dynamicXPath.js +90 -0
  260. package/src/xslt/runtime/functionCache.js +65 -0
  261. package/src/xslt/runtime/functionCall.js +57 -0
  262. package/src/xslt/runtime/functions.js +191 -0
  263. package/src/xslt/runtime/groups.js +108 -0
  264. package/src/xslt/runtime/invocation.js +156 -0
  265. package/src/xslt/runtime/iteration.js +107 -0
  266. package/src/xslt/runtime/keys.js +141 -0
  267. package/src/xslt/runtime/lazy.js +97 -0
  268. package/src/xslt/runtime/locations.js +86 -0
  269. package/src/xslt/runtime/machine.js +137 -0
  270. package/src/xslt/runtime/merging.js +167 -0
  271. package/src/xslt/runtime/namespaceScope.js +141 -0
  272. package/src/xslt/runtime/numberFormat.js +89 -0
  273. package/src/xslt/runtime/numbering.js +168 -0
  274. package/src/xslt/runtime/params.js +59 -0
  275. package/src/xslt/runtime/properties.js +103 -0
  276. package/src/xslt/runtime/rawResults.js +82 -0
  277. package/src/xslt/runtime/sequenceReceiver.js +102 -0
  278. package/src/xslt/runtime/snapshot.js +66 -0
  279. package/src/xslt/runtime/sortKeys.js +119 -0
  280. package/src/xslt/runtime/streamAvailable.js +60 -0
  281. package/src/xslt/runtime/strip.js +102 -0
  282. package/src/xslt/runtime/transformFunction.js +169 -0
  283. package/src/xslt/runtime/transformation.js +168 -0
  284. package/src/xslt/runtime/transformationContext.js +85 -0
  285. package/src/xslt/runtime/treeReceiver.js +194 -0
  286. package/src/xslt/runtime/values.js +92 -0
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Conditional and repetition instructions: xsl:if, xsl:choose,
3
+ * xsl:for-each (XSLT 3.0 sections 8 and 7.1).
4
+ *
5
+ * @module @tradik/xslt3/xslt/instructions/control
6
+ */
7
+
8
+ import { effectiveBooleanValue } from "../../xdm/nodes.js";
9
+ import { compileBody } from "../compiler/body.js";
10
+ import { checkAttributes, required } from "../compiler/attributes.js";
11
+ import { derive, evaluate } from "../runtime/context.js";
12
+ import { BodyFrame, LoopFrame } from "../runtime/machine.js";
13
+ import { isXsl, xsltError } from "../names.js";
14
+ import { compileSorts, splitSorts } from "./sort.js";
15
+
16
+ /**
17
+ * xsl:if.
18
+ * @param {Element} element
19
+ * @param {object} cx
20
+ * @param {object} scope
21
+ * @returns {Function}
22
+ */
23
+ export function compileIf(element, cx, scope) {
24
+ const test = cx.exprs.xpath(required(element, "test"), element, scope.vars);
25
+ const body = compileBody(element, cx, scope);
26
+ return (xc, out, machine) => {
27
+ if (effectiveBooleanValue(evaluate(test, xc)) && body.length > 0) {
28
+ machine.push(new BodyFrame(body, xc, out));
29
+ }
30
+ };
31
+ }
32
+
33
+ /**
34
+ * xsl:choose.
35
+ * @param {Element} element
36
+ * @param {object} cx
37
+ * @param {object} scope
38
+ * @returns {Function}
39
+ */
40
+ export function compileChoose(element, cx, scope) {
41
+ const branches = [];
42
+ let otherwise = null;
43
+ for (const child of cx.children(element)) {
44
+ const misplaced =
45
+ child.nodeType !== 1 ||
46
+ otherwise !== null ||
47
+ !(isXsl(child, "when") || isXsl(child, "otherwise"));
48
+ if (misplaced) {
49
+ throw xsltError(
50
+ "XTSE0010",
51
+ "xsl:choose may only contain xsl:when then xsl:otherwise",
52
+ );
53
+ }
54
+ checkAttributes(child);
55
+ if (isXsl(child, "when")) {
56
+ branches.push({
57
+ test: cx.exprs.xpath(required(child, "test"), child, scope.vars),
58
+ body: compileBody(child, cx, scope),
59
+ });
60
+ } else otherwise = compileBody(child, cx, scope);
61
+ }
62
+ if (branches.length === 0) {
63
+ throw xsltError("XTSE0010", "xsl:choose needs at least one xsl:when");
64
+ }
65
+ return (xc, out, machine) => {
66
+ let body = otherwise;
67
+ for (const branch of branches) {
68
+ if (effectiveBooleanValue(evaluate(branch.test, xc))) {
69
+ body = branch.body;
70
+ break;
71
+ }
72
+ }
73
+ if (body && body.length > 0) machine.push(new BodyFrame(body, xc, out));
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Runs a body once per item, with that item as the focus.
79
+ * @param {Array} items
80
+ * @param {import("../runtime/machine.js").Body} body
81
+ * @param {object} xc - Context of the instruction
82
+ * @param {object} out
83
+ * @param {import("../runtime/machine.js").Machine} machine
84
+ * @param {object} [changes] - Further changes to the context
85
+ */
86
+ export function forEachItem(items, body, xc, out, machine, changes = {}) {
87
+ if (items.length === 0 || body.length === 0) return;
88
+ const size = items.length;
89
+ const base = derive(xc, { rule: null, ...changes });
90
+ machine.push(
91
+ new LoopFrame(size, (i) =>
92
+ machine.push(
93
+ new BodyFrame(
94
+ body,
95
+ derive(base, { item: items[i], position: i + 1, size }),
96
+ out,
97
+ ),
98
+ ),
99
+ ),
100
+ );
101
+ }
102
+
103
+ /**
104
+ * xsl:for-each.
105
+ * @param {Element} element
106
+ * @param {object} cx
107
+ * @param {object} scope
108
+ * @returns {Function}
109
+ */
110
+ export function compileForEach(element, cx, scope) {
111
+ const select = cx.exprs.xpath(
112
+ required(element, "select"),
113
+ element,
114
+ scope.vars,
115
+ );
116
+ const { sorts, rest } = splitSorts(cx.children(element));
117
+ const sort = compileSorts(sorts, cx, scope);
118
+ const body = compileBody(element, cx, scope, rest);
119
+ return (xc, out, machine) => {
120
+ const items = sort(evaluate(select, xc), xc, machine);
121
+ forEachItem(items, body, xc, out, machine);
122
+ };
123
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Copying and new documents: xsl:copy, xsl:copy-of, xsl:document and
3
+ * xsl:perform-sort (XSLT 3.0 sections 11.8, 11.9.1 and 13.2).
4
+ *
5
+ * @module @tradik/xslt3/xslt/instructions/copy
6
+ */
7
+
8
+ import { isAtomic, isNode } from "../../xdm/atomic.js";
9
+ import { compileBody } from "../compiler/body.js";
10
+ import { required, yesNo } from "../compiler/attributes.js";
11
+ import { derive, evaluate, withFocus } from "../runtime/context.js";
12
+ import { setOrigin } from "../runtime/accumulators.js";
13
+ import { markCopied, markDocumentCopied } from "../runtime/baseUri.js";
14
+ import { copyLeaf, copyNamespaceNodes } from "../runtime/copy.js";
15
+ import { BodyFrame } from "../runtime/machine.js";
16
+ import { bodySequence } from "../runtime/values.js";
17
+ import { attr, isXsl, xsltError } from "../names.js";
18
+ import { applyAttributeSets, attributeSetNames } from "./attributeSets.js";
19
+ import { compileSorts, splitSorts } from "./sort.js";
20
+
21
+ /**
22
+ * xsl:copy.
23
+ * @param {Element} element
24
+ * @param {object} cx
25
+ * @param {object} scope
26
+ * @returns {Function}
27
+ */
28
+ export function compileCopy(element, cx, scope) {
29
+ const selectText = attr(element, "select");
30
+ const select =
31
+ selectText === undefined
32
+ ? null
33
+ : cx.exprs.xpath(selectText, element, scope.vars);
34
+ const copyNamespaces = yesNo(element, "copy-namespaces", true);
35
+ const sets = attributeSetNames(
36
+ attr(element, "use-attribute-sets"),
37
+ element,
38
+ cx,
39
+ );
40
+ const body = compileBody(element, cx, scope);
41
+ return (xc, out, machine) => {
42
+ let context = xc;
43
+ if (select) {
44
+ const items = evaluate(select, xc);
45
+ if (items.length === 0) return;
46
+ if (items.length > 1) {
47
+ throw xsltError("XTTE3180", "xsl:copy select gives several items");
48
+ }
49
+ // a new focus: no current template rule (XTDE0560 for next-match)
50
+ context = derive(withFocus(xc, items[0], 1, 1), { rule: null });
51
+ }
52
+ const item = context.item;
53
+ if (item === undefined) {
54
+ throw xsltError("XTTE0945", "xsl:copy needs a context item");
55
+ }
56
+ let content;
57
+ if (isAtomic(item) || !isNode(item)) {
58
+ out.item(item);
59
+ return;
60
+ }
61
+ if (item.nodeType === 1) {
62
+ content = out.element(item.namespaceURI ?? "", item.nodeName);
63
+ markCopied(item, content.parent, false);
64
+ if (copyNamespaces) copyNamespaceNodes(item, content);
65
+ } else if (item.nodeType === 9 || item.nodeType === 11) {
66
+ content = out.document();
67
+ markDocumentCopied(item, content);
68
+ } else {
69
+ copyLeaf(item, out);
70
+ return;
71
+ }
72
+ if (sets.length > 0) {
73
+ applyAttributeSets(sets, context, content, machine, cx);
74
+ }
75
+ if (body.length > 0) machine.push(new BodyFrame(body, context, content));
76
+ };
77
+ }
78
+
79
+ /**
80
+ * xsl:copy-of.
81
+ * @param {Element} element
82
+ * @param {object} cx
83
+ * @param {object} scope
84
+ * @returns {Function}
85
+ */
86
+ export function compileCopyOf(element, cx, scope) {
87
+ if (cx.children(element).some((child) => !isXsl(child, "fallback"))) {
88
+ throw xsltError("XTSE0260", "xsl:copy-of must be empty");
89
+ }
90
+ const select = cx.exprs.xpath(
91
+ required(element, "select"),
92
+ element,
93
+ scope.vars,
94
+ );
95
+ const copyNamespaces = yesNo(element, "copy-namespaces", true);
96
+ const copyAccumulators = yesNo(element, "copy-accumulators", false);
97
+ return (xc, out) => {
98
+ for (const item of evaluate(select, xc)) {
99
+ if (isNode(item)) {
100
+ out.copy(item, copyNamespaces);
101
+ // a parentless copy keeps the accumulator values of the original
102
+ if (copyAccumulators && out.items) {
103
+ setOrigin(xc.tx, out.items.at(-1), item);
104
+ }
105
+ } else out.item(item);
106
+ }
107
+ };
108
+ }
109
+
110
+ /**
111
+ * xsl:document.
112
+ * @param {Element} element
113
+ * @param {object} cx
114
+ * @param {object} scope
115
+ * @returns {Function}
116
+ */
117
+ export function compileDocument(element, cx, scope) {
118
+ const body = compileBody(element, cx, scope);
119
+ return (xc, out, machine) => {
120
+ const content = out.document();
121
+ if (body.length > 0) machine.push(new BodyFrame(body, xc, content));
122
+ };
123
+ }
124
+
125
+ /**
126
+ * xsl:perform-sort.
127
+ * @param {Element} element
128
+ * @param {object} cx
129
+ * @param {object} scope
130
+ * @returns {Function}
131
+ */
132
+ export function compilePerformSort(element, cx, scope) {
133
+ const { sorts, rest } = splitSorts(cx.children(element));
134
+ const content = rest.filter((child) => !isXsl(child, "fallback"));
135
+ const selectText = attr(element, "select");
136
+ if (selectText !== undefined && content.length > 0) {
137
+ throw xsltError("XTSE1040", "xsl:perform-sort has select and content");
138
+ }
139
+ const sort = compileSorts(sorts, cx, scope);
140
+ const select =
141
+ selectText === undefined
142
+ ? null
143
+ : cx.exprs.xpath(selectText, element, scope.vars);
144
+ const body = compileBody(element, cx, scope, content);
145
+ return (xc, out, machine) => {
146
+ const items = select
147
+ ? evaluate(select, xc)
148
+ : bodySequence(body, xc, machine, false);
149
+ for (const item of sort(items, xc, machine)) out.item(item);
150
+ };
151
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * xsl:element and xsl:attribute (XSLT 3.0 sections 11.2 and 11.3):
3
+ * nodes with computed names.
4
+ *
5
+ * @module @tradik/xslt3/xslt/instructions/elements
6
+ */
7
+
8
+ import { compileBody } from "../compiler/body.js";
9
+ import { required } from "../compiler/attributes.js";
10
+ import { infoOf } from "../compiler/elementInfo.js";
11
+ import { evaluate } from "../runtime/context.js";
12
+ import { markConstructed } from "../runtime/baseUri.js";
13
+ import { BodyFrame } from "../runtime/machine.js";
14
+ import {
15
+ avtEvaluator,
16
+ bodySequence,
17
+ simpleContent,
18
+ } from "../runtime/values.js";
19
+ import { attr, isQName, XML_NS, XMLNS_NS, xsltError } from "../names.js";
20
+ import { applyAttributeSets, attributeSetNames } from "./attributeSets.js";
21
+
22
+ /**
23
+ * Compiles the computed name of an element or attribute.
24
+ * @param {Element} element - The instruction
25
+ * @param {object} cx
26
+ * @param {object} scope
27
+ * @param {object} codes - Error codes: `name` (invalid QName), `prefix`
28
+ * (undeclared prefix), `namespace` (reserved namespace)
29
+ * @param {boolean} useDefault - Unprefixed names take the default namespace
30
+ * @returns {(xc: object) => {uri: string, qname: string, prefix: string, local: string}}
31
+ */
32
+ function compileName(element, cx, scope, codes, useDefault) {
33
+ const name = avtEvaluator(
34
+ cx.exprs.avt(required(element, "name"), element, scope.vars),
35
+ );
36
+ const nsText = attr(element, "namespace");
37
+ const namespace =
38
+ nsText === undefined
39
+ ? null
40
+ : avtEvaluator(cx.exprs.avt(nsText, element, scope.vars));
41
+ const namespaces = infoOf(element).namespaces;
42
+ return (xc) => {
43
+ const qname = name(xc).trim();
44
+ if (!isQName(qname)) {
45
+ throw xsltError(codes.name, `Invalid name "${qname}"`);
46
+ }
47
+ const colon = qname.indexOf(":");
48
+ const prefix = colon < 0 ? "" : qname.slice(0, colon);
49
+ const local = qname.slice(colon + 1);
50
+ let uri;
51
+ if (namespace) uri = namespace(xc);
52
+ else if (prefix === "xml") uri = XML_NS;
53
+ else if (prefix) {
54
+ uri = namespaces.get(prefix);
55
+ if (!uri) throw xsltError(codes.prefix, `Undeclared prefix ${prefix}`);
56
+ } else uri = useDefault ? (namespaces.get("") ?? "") : "";
57
+ if (uri === XMLNS_NS || (uri !== XML_NS && prefix === "xml")) {
58
+ throw xsltError(codes.namespace, `The namespace ${uri} is reserved`);
59
+ }
60
+ if (uri === "") return { uri, qname: local, prefix: "", local };
61
+ return { uri, qname, prefix, local };
62
+ };
63
+ }
64
+
65
+ /**
66
+ * xsl:element.
67
+ * @param {Element} element
68
+ * @param {object} cx
69
+ * @param {object} scope
70
+ * @returns {Function}
71
+ */
72
+ export function compileElement(element, cx, scope) {
73
+ const name = compileName(
74
+ element,
75
+ cx,
76
+ scope,
77
+ { name: "XTDE0820", prefix: "XTDE0830", namespace: "XTDE0835" },
78
+ true,
79
+ );
80
+ const sets = attributeSetNames(
81
+ attr(element, "use-attribute-sets"),
82
+ element,
83
+ cx,
84
+ );
85
+ const body = compileBody(element, cx, scope);
86
+ const base = infoOf(element).baseUri;
87
+ return (xc, out, machine) => {
88
+ const { uri, qname } = name(xc);
89
+ const content = out.element(uri, qname);
90
+ markConstructed(content, base);
91
+ if (sets.length > 0) applyAttributeSets(sets, xc, content, machine, cx);
92
+ if (body.length > 0) machine.push(new BodyFrame(body, xc, content));
93
+ };
94
+ }
95
+
96
+ /**
97
+ * The value of an instruction with simple content: its select
98
+ * expression or its content, joined with a separator.
99
+ * @param {Element} element
100
+ * @param {object} cx
101
+ * @param {object} scope
102
+ * @param {string} contentSeparator - Default separator for content
103
+ * @param {string} conflictCode - Error code for select and content
104
+ * @returns {(xc: object, machine: object) => string}
105
+ */
106
+ export function compileSimpleContent(
107
+ element,
108
+ cx,
109
+ scope,
110
+ contentSeparator,
111
+ conflictCode,
112
+ ) {
113
+ const select = attr(element, "select");
114
+ const body = compileBody(element, cx, scope);
115
+ if (select !== undefined && body.length > 0) {
116
+ throw xsltError(
117
+ conflictCode,
118
+ `xsl:${element.localName} cannot have both select and content`,
119
+ );
120
+ }
121
+ const separatorText = attr(element, "separator");
122
+ const separator =
123
+ separatorText === undefined
124
+ ? () => (select === undefined ? contentSeparator : " ")
125
+ : avtEvaluator(cx.exprs.avt(separatorText, element, scope.vars));
126
+ if (select === undefined) {
127
+ return (xc, machine) =>
128
+ simpleContent(bodySequence(body, xc, machine, false), separator(xc));
129
+ }
130
+ const expr = cx.exprs.xpath(select, element, scope.vars);
131
+ if (infoOf(element).version < 2 && separatorText === undefined) {
132
+ return (xc) => simpleContent(evaluate(expr, xc).slice(0, 1), "");
133
+ }
134
+ return (xc) => simpleContent(evaluate(expr, xc), separator(xc));
135
+ }
136
+
137
+ /**
138
+ * xsl:attribute.
139
+ * @param {Element} element
140
+ * @param {object} cx
141
+ * @param {object} scope
142
+ * @returns {Function}
143
+ */
144
+ export function compileAttribute(element, cx, scope) {
145
+ const name = compileName(
146
+ element,
147
+ cx,
148
+ scope,
149
+ { name: "XTDE0850", prefix: "XTDE0860", namespace: "XTDE0865" },
150
+ false,
151
+ );
152
+ const value = compileSimpleContent(element, cx, scope, "", "XTSE0840");
153
+ return (xc, out, machine) => {
154
+ const { uri, qname, prefix, local } = name(xc);
155
+ if (qname === "xmlns" || (uri === "" && local === "xmlns")) {
156
+ throw xsltError("XTDE0855", "An attribute cannot be named xmlns");
157
+ }
158
+ const actual = prefix === "xmlns" ? local : qname;
159
+ out.attribute(uri, actual, value(xc, machine));
160
+ };
161
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * xsl:evaluate (XSLT 3.0 section 10.4): compiles the string of the xpath
3
+ * attribute and evaluates it with the parameters of the xsl:with-param
4
+ * children and of the with-params map, and the context item of the
5
+ * context-item attribute. The transform() option `dynamicEvaluation:
6
+ * false` disables it: then the xsl:fallback children run, or XTDE3175 is
7
+ * raised.
8
+ *
9
+ * @module @tradik/xslt3/xslt/instructions/evaluate
10
+ */
11
+
12
+ import { isMap, isNode } from "../../xdm/atomic.js";
13
+ import { types } from "../../xdm/types.js";
14
+ import { resolveUri } from "../../xpath/eval/uris.js";
15
+ import { compileFallback } from "../compiler/body.js";
16
+ import { required } from "../compiler/attributes.js";
17
+ import { infoOf } from "../compiler/elementInfo.js";
18
+ import { derive, dynamicContextOf, evaluate } from "../runtime/context.js";
19
+ import { compileTarget, nodeNamespaces } from "../runtime/dynamicXPath.js";
20
+ import { avtEvaluator } from "../runtime/values.js";
21
+ import { attr, isXsl, xsltError } from "../names.js";
22
+ import { compileWithParams } from "./params.js";
23
+ import { typeConverter } from "./variables.js";
24
+
25
+ /**
26
+ * The variables given by the with-params map.
27
+ * @param {Array} value
28
+ * @returns {Map<string, Array>} values by Clark name
29
+ * @throws {import("../../errors.js").XPathError} XTTE3165
30
+ */
31
+ function mapParams(value) {
32
+ const map = value[0];
33
+ if (value.length !== 1 || !isMap(map)) {
34
+ throw xsltError("XTTE3165", "with-params must be a single map");
35
+ }
36
+ const params = new Map();
37
+ for (const { key, value: item } of map.entries.values()) {
38
+ if (key.type !== types.QName) {
39
+ throw xsltError("XTTE3165", "The keys of with-params must be QNames");
40
+ }
41
+ params.set(`{${key.value.namespaceURI}}${key.value.localName}`, item);
42
+ }
43
+ return params;
44
+ }
45
+
46
+ /**
47
+ * The values of the xsl:with-param children; a value that does not
48
+ * match its declared type is a type error of the target (XPTY0004).
49
+ * @param {object} params - Compiled xsl:with-param children
50
+ * @param {object} xc
51
+ * @param {object} machine
52
+ * @returns {Map<string, Array>}
53
+ */
54
+ function withParamValues(params, xc, machine) {
55
+ try {
56
+ return params.evaluate(xc, machine).params;
57
+ } catch (error) {
58
+ if (error.code !== "XTTE0570") throw error;
59
+ throw xsltError("XPTY0004", error.message.replace(/^[A-Z]+\d+: /, ""));
60
+ }
61
+ }
62
+
63
+ /**
64
+ * The boolean value of schema-aware.
65
+ * @param {string} text
66
+ * @returns {boolean}
67
+ * @throws {import("../../errors.js").XPathError} XTDE0030 for another value
68
+ */
69
+ function schemaAware(text) {
70
+ const value = text.trim();
71
+ if (["yes", "true", "1"].includes(value)) return true;
72
+ if (["no", "false", "0"].includes(value)) return false;
73
+ throw xsltError("XTDE0030", `Invalid schema-aware value "${text}"`);
74
+ }
75
+
76
+ /**
77
+ * xsl:evaluate.
78
+ * @param {Element} element
79
+ * @param {object} cx
80
+ * @param {object} scope
81
+ * @returns {Function}
82
+ */
83
+ export function compileEvaluate(element, cx, scope) {
84
+ const children = cx.children(element);
85
+ if (!children.every((c) => isXsl(c, "with-param") || isXsl(c, "fallback"))) {
86
+ throw xsltError("XTSE0010", "xsl:evaluate contains xsl:with-param");
87
+ }
88
+ const xpath = (name) => {
89
+ const text = attr(element, name);
90
+ return text === undefined
91
+ ? null
92
+ : cx.exprs.xpath(text, element, scope.vars);
93
+ };
94
+ const target = cx.exprs.xpath(
95
+ required(element, "xpath"),
96
+ element,
97
+ scope.vars,
98
+ );
99
+ const toString = typeConverter(
100
+ cx.exprs.sequenceType("xs:string", element),
101
+ "XPTY0004",
102
+ "xpath attribute of xsl:evaluate",
103
+ );
104
+ const contextItem = xpath("context-item");
105
+ const withParamsMap = xpath("with-params");
106
+ const namespaceContext = xpath("namespace-context");
107
+ const avt = (name) => {
108
+ const text = attr(element, name);
109
+ return text === undefined
110
+ ? null
111
+ : avtEvaluator(cx.exprs.avt(text, element, scope.vars));
112
+ };
113
+ const baseUri = avt("base-uri");
114
+ const schema = avt("schema-aware");
115
+ const asText = attr(element, "as");
116
+ const convert = typeConverter(
117
+ asText === undefined ? null : cx.exprs.sequenceType(asText, element),
118
+ "XPTY0004",
119
+ "result of xsl:evaluate",
120
+ );
121
+ const params = compileWithParams(children, cx, scope);
122
+ const fallback = children.some((c) => isXsl(c, "fallback"))
123
+ ? compileFallback(element, cx, scope)
124
+ : null;
125
+ const info = infoOf(element);
126
+ const staticPart = {
127
+ namespaces: new Map([...info.namespaces].filter(([p]) => p !== "")),
128
+ defaultElementNamespace: info.xpathDefaultNs,
129
+ baseUri: info.baseUri,
130
+ library: cx.exprs.library,
131
+ decimalFormats: cx.exprs.decimalFormats,
132
+ };
133
+ const cache = new Map();
134
+ return (xc, out, machine) => {
135
+ if (!xc.tx.dynamicEvaluation) {
136
+ if (fallback) return fallback(xc, out, machine);
137
+ throw xsltError("XTDE3175", "xsl:evaluate is disabled");
138
+ }
139
+ const text = toString(evaluate(target, xc))[0].value;
140
+ if (schema) schemaAware(schema(xc));
141
+ const values = withParamValues(params, xc, machine);
142
+ if (withParamsMap) {
143
+ for (const [key, value] of mapParams(evaluate(withParamsMap, xc))) {
144
+ values.set(key, value);
145
+ }
146
+ }
147
+ const context = { ...staticPart };
148
+ if (namespaceContext) {
149
+ const nodes = evaluate(namespaceContext, xc);
150
+ if (nodes.length !== 1 || !isNode(nodes[0])) {
151
+ throw xsltError("XTTE3170", "namespace-context must be a single node");
152
+ }
153
+ Object.assign(context, nodeNamespaces(nodes[0]));
154
+ }
155
+ if (baseUri) context.baseUri = resolveUri(baseUri(xc), info.baseUri);
156
+ const keys = [...values.keys()];
157
+ const cacheKey = `${text}\u0000${keys.join(" ")}`;
158
+ let run = namespaceContext || baseUri ? null : cache.get(cacheKey);
159
+ if (!run) {
160
+ run = compileTarget(text, context, keys);
161
+ if (!namespaceContext && !baseUri) cache.set(cacheKey, run);
162
+ }
163
+ const focus = contextItem ? evaluate(contextItem, xc) : [];
164
+ if (focus.length > 1) {
165
+ throw xsltError("XTTE3210", "context-item must be at most one item");
166
+ }
167
+ let env = null;
168
+ for (const key of keys) env = { value: values.get(key), next: env };
169
+ const targetXc = derive(xc, {
170
+ group: undefined,
171
+ groupKey: undefined,
172
+ regex: undefined,
173
+ merge: undefined,
174
+ });
175
+ const dyn = dynamicContextOf(targetXc);
176
+ dyn.sc = run.sc;
177
+ dyn.staticBaseUri = run.sc.baseUri;
178
+ dyn.decimalFormats = run.sc.decimalFormats;
179
+ if (info.defaultCollation) dyn.defaultCollation = info.defaultCollation;
180
+ const result = run({
181
+ item: focus[0],
182
+ position: focus.length,
183
+ size: focus.length,
184
+ env,
185
+ dyn,
186
+ });
187
+ for (const item of convert(result)) out.item(item);
188
+ };
189
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * xsl:fork (XSLT 3.0 section 16.1): its xsl:sequence or
3
+ * xsl:for-each-group children run one after the other (this processor
4
+ * does not stream, so there is nothing to fork) and their results are
5
+ * concatenated.
6
+ *
7
+ * @module @tradik/xslt3/xslt/instructions/fork
8
+ */
9
+
10
+ import { compileBody } from "../compiler/body.js";
11
+ import { isXsl, xsltError } from "../names.js";
12
+
13
+ /**
14
+ * xsl:fork.
15
+ * @param {Element} element
16
+ * @param {object} cx
17
+ * @param {object} scope
18
+ * @returns {Function}
19
+ */
20
+ export function compileFork(element, cx, scope) {
21
+ const children = cx.children(element);
22
+ const branches = children.filter((c) => !isXsl(c, "fallback"));
23
+ const groups = branches.filter((c) => isXsl(c, "for-each-group")).length;
24
+ const valid =
25
+ branches.every((c) => isXsl(c, "sequence") || isXsl(c, "for-each-group")) &&
26
+ (groups === 0 || branches.length === 1);
27
+ if (!valid) {
28
+ throw xsltError(
29
+ "XTSE0010",
30
+ "xsl:fork contains xsl:sequence elements or one xsl:for-each-group",
31
+ );
32
+ }
33
+ const body = compileBody(element, cx, scope, branches);
34
+ return (xc, out, machine) => machine.runBody(body, xc, out);
35
+ }