@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,143 @@
1
+ /**
2
+ * xsl:result-document (XSLT 3.0 section 25.1): a new result tree, with
3
+ * the serialization parameters of an output definition overridden by
4
+ * the instruction's own attributes (attribute value templates); a raw
5
+ * sequence when build-tree is "no" (see runtime/rawResults.js).
6
+ *
7
+ * @module @tradik/xslt3/xslt/instructions/resultDocument
8
+ */
9
+
10
+ import { resolveUri } from "../../xpath/eval/uris.js";
11
+ import { compileBody } from "../compiler/body.js";
12
+ import { infoOf } from "../compiler/elementInfo.js";
13
+ import {
14
+ expandCharacterMaps,
15
+ readParameterDocument,
16
+ } from "../compiler/outputDecl.js";
17
+ import { derive } from "../runtime/context.js";
18
+ import { resultReceiver } from "../runtime/rawResults.js";
19
+ import { avtEvaluator } from "../runtime/values.js";
20
+ import { attr, clarkOf, resolveQName, tokens, xsltError } from "../names.js";
21
+
22
+ /** Serialization parameters given as attributes. */
23
+ const PARAMETERS = [
24
+ "allow-duplicate-names",
25
+ "build-tree",
26
+ "byte-order-mark",
27
+ "doctype-public",
28
+ "doctype-system",
29
+ "encoding",
30
+ "escape-uri-attributes",
31
+ "html-version",
32
+ "include-content-type",
33
+ "indent",
34
+ "item-separator",
35
+ "json-node-output-method",
36
+ "media-type",
37
+ "method",
38
+ "normalization-form",
39
+ "omit-xml-declaration",
40
+ "standalone",
41
+ "undeclare-prefixes",
42
+ "output-version",
43
+ ];
44
+
45
+ /** Parameters whose value is a list of element names. */
46
+ const NAME_LISTS = ["cdata-section-elements", "suppress-indentation"];
47
+
48
+ /**
49
+ * Compiles the serialization attributes.
50
+ * @param {Element} element
51
+ * @param {object} cx
52
+ * @param {object} scope
53
+ * @returns {(xc: object) => object} the parameters they set
54
+ */
55
+ function compileParameters(element, cx, scope) {
56
+ const namespaces = infoOf(element).namespaces;
57
+ const compiled = [...PARAMETERS, ...NAME_LISTS]
58
+ .filter((name) => attr(element, name) !== undefined)
59
+ .map((name) => [
60
+ name,
61
+ avtEvaluator(cx.exprs.avt(attr(element, name), element, scope.vars)),
62
+ ]);
63
+ const mapNames = tokens(attr(element, "use-character-maps")).map((token) =>
64
+ clarkOf(cx.exprs.qname(token, element)),
65
+ );
66
+ const characterMaps =
67
+ mapNames.length > 0
68
+ ? expandCharacterMaps(mapNames, cx.characterMaps)
69
+ : null;
70
+ const clark = (text, useDefault) =>
71
+ clarkOf(resolveQName(text, namespaces, { useDefault, code: "XTDE1460" }));
72
+ const documentText = attr(element, "parameter-document");
73
+ const document =
74
+ documentText === undefined
75
+ ? null
76
+ : avtEvaluator(cx.exprs.avt(documentText, element, scope.vars));
77
+ return (xc) => {
78
+ // the attributes override the parameter document
79
+ const params = document
80
+ ? readParameterDocument(document(xc), element, cx)
81
+ : {};
82
+ for (const [name, value] of compiled) {
83
+ const text = value(xc).trim();
84
+ if (NAME_LISTS.includes(name)) {
85
+ params[name] = tokens(text).map((token) => clark(token, true));
86
+ } else if (name === "method" && text.includes(":")) {
87
+ params[name] = clark(text, false);
88
+ } else params[name] = name === "item-separator" ? value(xc) : text;
89
+ }
90
+ if (characterMaps) params["use-character-maps"] = characterMaps;
91
+ return params;
92
+ };
93
+ }
94
+
95
+ /**
96
+ * xsl:result-document.
97
+ * @param {Element} element
98
+ * @param {object} cx
99
+ * @param {object} scope
100
+ * @returns {Function}
101
+ */
102
+ export function compileResultDocument(element, cx, scope) {
103
+ const avt = (name) => {
104
+ const text = attr(element, name);
105
+ return text === undefined
106
+ ? null
107
+ : avtEvaluator(cx.exprs.avt(text, element, scope.vars));
108
+ };
109
+ const href = avt("href");
110
+ const format = avt("format");
111
+ const parameters = compileParameters(element, cx, scope);
112
+ const body = compileBody(element, cx, scope);
113
+ return (xc, out, machine) => {
114
+ const { tx } = xc;
115
+ if (xc.temporary) {
116
+ throw xsltError("XTDE1480", "xsl:result-document in a temporary tree");
117
+ }
118
+ const target = href ? href(xc) : "";
119
+ const uri = target === "" ? "" : resolveUri(target, tx.baseOutputUri);
120
+ if (tx.resultUris.has(uri)) {
121
+ throw xsltError(
122
+ "XTDE1490",
123
+ `Two results have the URI ${uri || "(principal)"}`,
124
+ );
125
+ }
126
+ tx.resultUris.add(uri);
127
+ // "#absent" (XSLT 3.0 section 26.1), here too: no item separator,
128
+ // overriding the one of the output definition
129
+ const output = cx.outputFor(
130
+ format ? format(xc) : null,
131
+ element,
132
+ parameters(xc),
133
+ );
134
+ const { receiver, value } = resultReceiver(
135
+ output,
136
+ tx.scratch,
137
+ tx.options.buildTree,
138
+ );
139
+ const context = derive(xc, { outputUri: uri || tx.baseOutputUri });
140
+ machine.runBody(body, context, receiver);
141
+ tx.addResult(uri, value(), output);
142
+ };
143
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Sorting (XSLT 3.0 section 13): xsl:sort keys of xsl:for-each,
3
+ * xsl:apply-templates, xsl:for-each-group and xsl:perform-sort.
4
+ *
5
+ * @module @tradik/xslt3/xslt/instructions/sort
6
+ */
7
+
8
+ import { compileBody } from "../compiler/body.js";
9
+ import { checkAttributes } from "../compiler/attributes.js";
10
+ import { splitLeading } from "../compiler/children.js";
11
+ import { infoOf } from "../compiler/elementInfo.js";
12
+ import { withFocus } from "../runtime/context.js";
13
+ import { compareValues, keyValue, settingsOf } from "../runtime/sortKeys.js";
14
+ import { avtEvaluator } from "../runtime/values.js";
15
+ import { attr, isXsl, xsltError } from "../names.js";
16
+
17
+ /**
18
+ * Separates the leading xsl:sort children from the rest.
19
+ * @param {Node[]} children
20
+ * @returns {{sorts: Element[], rest: Node[]}}
21
+ */
22
+ export function splitSorts(children) {
23
+ const { leading, rest } = splitLeading(children, "sort");
24
+ if (rest.some((child) => isXsl(child, "sort"))) {
25
+ throw xsltError("XTSE0010", "xsl:sort must come first");
26
+ }
27
+ return { sorts: leading, rest };
28
+ }
29
+
30
+ /**
31
+ * @param {Element} element
32
+ * @param {string} name
33
+ * @param {object} cx
34
+ * @param {object} scope
35
+ * @returns {((xc: object) => string)|null}
36
+ */
37
+ function optionalAvt(element, name, cx, scope) {
38
+ const text = attr(element, name);
39
+ return text === undefined
40
+ ? null
41
+ : avtEvaluator(cx.exprs.avt(text, element, scope.vars));
42
+ }
43
+
44
+ /**
45
+ * Compiles one xsl:sort.
46
+ * @param {Element} element
47
+ * @param {object} cx
48
+ * @param {object} scope
49
+ * @returns {object} the compiled key
50
+ */
51
+ export function compileSortKey(element, cx, scope) {
52
+ checkAttributes(element);
53
+ const select = attr(element, "select");
54
+ const children = cx.children(element);
55
+ if (select !== undefined && children.length > 0) {
56
+ throw xsltError("XTSE1015", "xsl:sort cannot have select and content");
57
+ }
58
+ const expr =
59
+ children.length > 0
60
+ ? null
61
+ : cx.exprs.xpath(select ?? ".", element, scope.vars);
62
+ return {
63
+ expr,
64
+ body: children.length > 0 ? compileBody(element, cx, scope) : null,
65
+ order: optionalAvt(element, "order", cx, scope),
66
+ dataType: optionalAvt(element, "data-type", cx, scope),
67
+ caseOrder: optionalAvt(element, "case-order", cx, scope),
68
+ lang: optionalAvt(element, "lang", cx, scope),
69
+ collation: optionalAvt(element, "collation", cx, scope),
70
+ compatible: infoOf(element).version < 2,
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Compiles the xsl:sort elements of an instruction.
76
+ * @param {Element[]} elements
77
+ * @param {object} cx
78
+ * @param {object} scope
79
+ * @returns {((items: Array, xc: object, machine: object) => Array) &
80
+ * {order: Function}} sorts a sequence (the identity without sort keys);
81
+ * `order(items, xc, machine, prepare)` gives the sorted indices, where
82
+ * `prepare(focusContext, index)` adjusts the context of each key
83
+ */
84
+ export function compileSorts(elements, cx, scope) {
85
+ if (
86
+ elements.slice(1).some((element) => attr(element, "stable") !== undefined)
87
+ ) {
88
+ throw xsltError("XTSE1017", "Only the first xsl:sort can have stable");
89
+ }
90
+ const keys = elements.map((element) => compileSortKey(element, cx, scope));
91
+ const order = (items, xc, machine, prepare) => {
92
+ const indices = items.map((_, i) => i);
93
+ if (keys.length === 0) return indices;
94
+ const settings = keys.map((key) => settingsOf(key, xc));
95
+ const size = items.length;
96
+ const rows = items.map((item, i) => {
97
+ let focus = withFocus(xc, item, i + 1, size);
98
+ if (prepare) focus = prepare(focus, i);
99
+ return keys.map((key, k) => keyValue(key, settings[k], focus, machine));
100
+ });
101
+ indices.sort((x, y) => {
102
+ for (let k = 0; k < keys.length; k++) {
103
+ const result = compareValues(rows[x][k], rows[y][k], settings[k], xc);
104
+ if (result !== 0) return settings[k].descending ? -result : result;
105
+ }
106
+ return 0;
107
+ });
108
+ return indices;
109
+ };
110
+ const sort = (items, xc, machine) =>
111
+ keys.length === 0 ? items : order(items, xc, machine).map((i) => items[i]);
112
+ sort.order = order;
113
+ return sort;
114
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * xsl:source-document (XSLT 3.0 section 18.1): reads a document as
3
+ * doc() does and runs its content with the document node as the
4
+ * context item. This processor does not stream: streamable="yes" reads
5
+ * the whole document. The accumulators named by use-accumulators (none
6
+ * by default) apply to it.
7
+ *
8
+ * @module @tradik/xslt3/xslt/instructions/sourceDocument
9
+ */
10
+
11
+ import { resolveUri } from "../../xpath/eval/uris.js";
12
+ import { useAccumulators } from "../compiler/useAccumulators.js";
13
+ import { required, yesNo } from "../compiler/attributes.js";
14
+ import { compileBody } from "../compiler/body.js";
15
+ import { setApplicable } from "../runtime/accumulators.js";
16
+ import { derive, dynamicContextOf } from "../runtime/context.js";
17
+ import { BodyFrame } from "../runtime/machine.js";
18
+ import { avtEvaluator } from "../runtime/values.js";
19
+ import { attr, xsltError } from "../names.js";
20
+
21
+ /**
22
+ * Checks the validation and type attributes of an instruction of a
23
+ * processor that is not schema aware.
24
+ * @param {Element} element
25
+ * @throws {import("../../errors.js").XPathError} XTSE1660 for strict or
26
+ * lax validation or a type, XTSE0020 for an invalid validation
27
+ */
28
+ export function checkNoValidation(element) {
29
+ const validation = attr(element, "validation")?.trim();
30
+ if (
31
+ validation !== undefined &&
32
+ !["strict", "lax", "preserve", "strip"].includes(validation)
33
+ ) {
34
+ throw xsltError("XTSE0020", `Invalid validation "${validation}"`);
35
+ }
36
+ if (
37
+ validation === "strict" ||
38
+ validation === "lax" ||
39
+ attr(element, "type") !== undefined
40
+ ) {
41
+ throw xsltError("XTSE1660", "Schema validation needs schema awareness");
42
+ }
43
+ }
44
+
45
+ /**
46
+ * xsl:source-document.
47
+ * @param {Element} element
48
+ * @param {object} cx
49
+ * @param {object} scope
50
+ * @returns {Function}
51
+ */
52
+ export function compileSourceDocument(element, cx, scope) {
53
+ yesNo(element, "streamable", false);
54
+ checkNoValidation(element);
55
+ const href = avtEvaluator(
56
+ cx.exprs.avt(required(element, "href"), element, scope.vars),
57
+ );
58
+ const accumulators = useAccumulators(
59
+ attr(element, "use-accumulators") ?? "",
60
+ element,
61
+ cx,
62
+ );
63
+ const base = cx.baseUriOf(element);
64
+ const body = compileBody(element, cx, scope);
65
+ return (xc, out, machine) => {
66
+ const uri = resolveUri(href(xc), base);
67
+ const document = dynamicContextOf(xc).loadDocument(uri);
68
+ setApplicable(xc.tx, document, accumulators);
69
+ if (body.length === 0) return;
70
+ const context = derive(xc, { item: document, position: 1, size: 1 });
71
+ machine.push(new BodyFrame(body, context, out));
72
+ };
73
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Template invocation instructions: xsl:apply-templates,
3
+ * xsl:call-template, xsl:apply-imports and xsl:next-match, with their
4
+ * xsl:with-param children (XSLT 3.0 sections 6 and 10.1).
5
+ *
6
+ * @module @tradik/xslt3/xslt/instructions/templates
7
+ */
8
+
9
+ import { isNode } from "../../xdm/atomic.js";
10
+ import { required } from "../compiler/attributes.js";
11
+ import { derive, evaluate } from "../runtime/context.js";
12
+ import {
13
+ applyBuiltIn,
14
+ applyTemplates,
15
+ invokeTemplate,
16
+ } from "../runtime/apply.js";
17
+ import {
18
+ attr,
19
+ clarkOf,
20
+ declaredName,
21
+ isXsl,
22
+ XSL_NS,
23
+ xsltError,
24
+ } from "../names.js";
25
+ import { compileSorts } from "./sort.js";
26
+ import { compileWithParams } from "./params.js";
27
+
28
+ /**
29
+ * Checks the children of an invocation instruction.
30
+ * @param {Element} element
31
+ * @param {Node[]} children
32
+ * @param {string[]} allowed - Local names allowed
33
+ */
34
+ function checkChildren(element, children, allowed) {
35
+ for (const child of children) {
36
+ const ok =
37
+ child.nodeType === 1 &&
38
+ child.namespaceURI === element.namespaceURI &&
39
+ allowed.includes(child.localName);
40
+ if (!ok) {
41
+ throw xsltError(
42
+ "XTSE0010",
43
+ `xsl:${element.localName} may only contain ${allowed.join(", ")}`,
44
+ );
45
+ }
46
+ }
47
+ }
48
+
49
+ /**
50
+ * xsl:apply-templates.
51
+ * @param {Element} element
52
+ * @param {object} cx
53
+ * @param {object} scope
54
+ * @returns {Function}
55
+ */
56
+ export function compileApplyTemplates(element, cx, scope) {
57
+ const children = cx.children(element);
58
+ checkChildren(element, children, ["sort", "with-param"]);
59
+ const selectText = attr(element, "select");
60
+ const select = cx.exprs.xpath(
61
+ selectText ?? "child::node()",
62
+ element,
63
+ scope.vars,
64
+ );
65
+ const mode = cx.modeRef(attr(element, "mode"), element);
66
+ const sort = compileSorts(
67
+ children.filter((child) => isXsl(child, "sort")),
68
+ cx,
69
+ scope,
70
+ );
71
+ const params = compileWithParams(children, cx, scope);
72
+ return (xc, out, machine) => {
73
+ if (selectText === undefined && !isNode(xc.item)) {
74
+ throw xsltError(
75
+ xc.item === undefined ? "XPDY0002" : "XTTE0510",
76
+ "xsl:apply-templates without select needs a context node",
77
+ );
78
+ }
79
+ // XSLT 3.0 applies templates to atomic values too (no XTTE0520)
80
+ const items = sort(evaluate(select, xc), xc, machine);
81
+ const target = mode.current ? xc.mode : cx.mode(mode.name);
82
+ applyTemplates(
83
+ items,
84
+ target,
85
+ xc,
86
+ out,
87
+ machine,
88
+ params.evaluate(xc, machine),
89
+ );
90
+ };
91
+ }
92
+
93
+ /**
94
+ * xsl:call-template.
95
+ * @param {Element} element
96
+ * @param {object} cx
97
+ * @param {object} scope
98
+ * @returns {Function}
99
+ */
100
+ export function compileCallTemplate(element, cx, scope) {
101
+ const children = cx.children(element);
102
+ checkChildren(element, children, ["with-param"]);
103
+ const qname = cx.exprs.qname(required(element, "name"), element);
104
+ const key =
105
+ cx.originalName("template", clarkOf(qname)) ??
106
+ clarkOf(declaredName(qname, `{${XSL_NS}}initial-template`));
107
+ const params = compileWithParams(children, cx, scope);
108
+ cx.deferred.push(() => cx.checkCall(key, params, element));
109
+ return (xc, out, machine) => {
110
+ const template = cx.namedTemplates.get(key);
111
+ invokeTemplate(template, xc, out, machine, params.evaluate(xc, machine));
112
+ };
113
+ }
114
+
115
+ /**
116
+ * xsl:apply-imports and xsl:next-match.
117
+ * @param {Element} element
118
+ * @param {object} cx
119
+ * @param {object} scope
120
+ * @returns {Function}
121
+ */
122
+ export function compileApplyImports(element, cx, scope) {
123
+ const children = cx.children(element);
124
+ const next = element.localName === "next-match";
125
+ // xsl:next-match may have xsl:fallback children (ignored: it exists)
126
+ checkChildren(
127
+ element,
128
+ children,
129
+ next ? ["with-param", "fallback"] : ["with-param"],
130
+ );
131
+ const params = compileWithParams(children, cx, scope);
132
+ return (xc, out, machine) => {
133
+ const current = xc.rule;
134
+ if (!current) {
135
+ throw xsltError(
136
+ "XTDE0560",
137
+ `xsl:${element.localName} needs a current template rule`,
138
+ );
139
+ }
140
+ const { template } = current;
141
+ const accept = next
142
+ ? (rule) => rule.rank > current.rank
143
+ : (rule) =>
144
+ rule.precedence < template.precedence &&
145
+ rule.precedence >= template.importLow;
146
+ const mode = xc.mode;
147
+ const args = params.evaluate(xc, machine);
148
+ const rule = mode.find(xc.item, xc, accept);
149
+ if (rule) {
150
+ invokeTemplate(rule.template, derive(xc, { rule }), out, machine, args);
151
+ } else applyBuiltIn(xc.item, xc, mode, out, machine, args);
152
+ };
153
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Instructions that produce text and leaf nodes: xsl:value-of, xsl:text,
3
+ * xsl:sequence, xsl:comment, xsl:processing-instruction and xsl:namespace
4
+ * (XSLT 3.0 sections 11.4 to 11.7 and 11.9).
5
+ *
6
+ * @module @tradik/xslt3/xslt/instructions/text
7
+ */
8
+
9
+ import { compileBody } from "../compiler/body.js";
10
+ import { required } from "../compiler/attributes.js";
11
+ import { evaluate } from "../runtime/context.js";
12
+ import { avtEvaluator } from "../runtime/values.js";
13
+ import { attr, isNCName, isXsl, xsltError } from "../names.js";
14
+ import { compileSimpleContent } from "./elements.js";
15
+
16
+ /**
17
+ * xsl:value-of.
18
+ * @param {Element} element
19
+ * @param {object} cx
20
+ * @param {object} scope
21
+ * @returns {Function}
22
+ */
23
+ export function compileValueOf(element, cx, scope) {
24
+ // XSLT 3.0: neither select nor content makes a zero-length text node
25
+ const value = compileSimpleContent(element, cx, scope, "", "XTSE0870");
26
+ return (xc, out, machine) => out.text(value(xc, machine));
27
+ }
28
+
29
+ /**
30
+ * xsl:text.
31
+ * @param {Element} element
32
+ * @param {object} cx
33
+ * @param {object} scope
34
+ * @returns {Function}
35
+ */
36
+ export function compileText(element, cx, scope) {
37
+ for (const child of cx.children(element)) {
38
+ if (child.nodeType === 1) {
39
+ throw xsltError("XTSE0010", "xsl:text cannot contain elements");
40
+ }
41
+ }
42
+ // an empty xsl:text makes a zero-length text node
43
+ return compileBody(element, cx, scope)[0] ?? ((xc, out) => out.text(""));
44
+ }
45
+
46
+ /**
47
+ * xsl:sequence.
48
+ * @param {Element} element
49
+ * @param {object} cx
50
+ * @param {object} scope
51
+ * @returns {Function}
52
+ */
53
+ export function compileSequence(element, cx, scope) {
54
+ const select = attr(element, "select");
55
+ const children = cx.children(element);
56
+ const body = compileBody(
57
+ element,
58
+ cx,
59
+ scope,
60
+ children.filter((child) => !isXsl(child, "fallback")),
61
+ );
62
+ if (select === undefined) {
63
+ return (xc, out, machine) => machine.runBody(body, xc, out);
64
+ }
65
+ if (body.length > 0) {
66
+ throw xsltError("XTSE3185", "xsl:sequence cannot have select and content");
67
+ }
68
+ const expr = cx.exprs.xpath(select, element, scope.vars);
69
+ return (xc, out) => {
70
+ for (const item of evaluate(expr, xc)) out.item(item);
71
+ };
72
+ }
73
+
74
+ /**
75
+ * xsl:comment.
76
+ * @param {Element} element
77
+ * @param {object} cx
78
+ * @param {object} scope
79
+ * @returns {Function}
80
+ */
81
+ export function compileComment(element, cx, scope) {
82
+ const value = compileSimpleContent(element, cx, scope, " ", "XTSE0940");
83
+ return (xc, out, machine) => {
84
+ let text = value(xc, machine).replace(/--/g, "- -");
85
+ text = text.replace(/--/g, "- -");
86
+ if (text.endsWith("-")) text += " ";
87
+ out.comment(text);
88
+ };
89
+ }
90
+
91
+ /**
92
+ * xsl:processing-instruction.
93
+ * @param {Element} element
94
+ * @param {object} cx
95
+ * @param {object} scope
96
+ * @returns {Function}
97
+ */
98
+ export function compileProcessingInstruction(element, cx, scope) {
99
+ const name = avtEvaluator(
100
+ cx.exprs.avt(required(element, "name"), element, scope.vars),
101
+ );
102
+ const value = compileSimpleContent(element, cx, scope, " ", "XTSE0880");
103
+ return (xc, out, machine) => {
104
+ const target = name(xc).trim();
105
+ if (!isNCName(target) || target.toLowerCase() === "xml") {
106
+ throw xsltError(
107
+ "XTDE0890",
108
+ `Invalid processing instruction name ${target}`,
109
+ );
110
+ }
111
+ let data = value(xc, machine).replace(/^[ \t\r\n]+/, "");
112
+ data = data.replace(/\?>/g, "? >");
113
+ out.pi(target, data);
114
+ };
115
+ }
116
+
117
+ /**
118
+ * xsl:namespace.
119
+ * @param {Element} element
120
+ * @param {object} cx
121
+ * @param {object} scope
122
+ * @returns {Function}
123
+ */
124
+ export function compileNamespace(element, cx, scope) {
125
+ const name = avtEvaluator(
126
+ cx.exprs.avt(required(element, "name"), element, scope.vars),
127
+ );
128
+ const value = compileSimpleContent(element, cx, scope, " ", "XTSE0910");
129
+ return (xc, out, machine) => {
130
+ const prefix = name(xc).trim();
131
+ if (prefix !== "" && !isNCName(prefix)) {
132
+ throw xsltError("XTDE0920", `Invalid namespace prefix ${prefix}`);
133
+ }
134
+ if (prefix === "xmlns") {
135
+ throw xsltError("XTDE0920", "The prefix xmlns cannot be bound");
136
+ }
137
+ const uri = value(xc, machine);
138
+ const xml = "http://www.w3.org/XML/1998/namespace";
139
+ if ((prefix === "xml") !== (uri === xml)) {
140
+ throw xsltError("XTDE0925", "The xml prefix and namespace go together");
141
+ }
142
+ if (uri === "http://www.w3.org/2000/xmlns/") {
143
+ throw xsltError("XTDE0905", "The xmlns namespace cannot be bound");
144
+ }
145
+ if (uri === "") {
146
+ throw xsltError("XTDE0930", "A namespace node cannot have an empty URI");
147
+ }
148
+ if (prefix === "xml") return;
149
+ out.namespace(prefix, uri);
150
+ };
151
+ }