@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.
- package/LICENSE.md +28 -0
- package/README.md +98 -2
- package/package.json +43 -4
- package/src/errors.js +20 -0
- package/src/functions/aggregates.js +144 -0
- package/src/functions/arraySort.js +33 -0
- package/src/functions/arrays.js +181 -0
- package/src/functions/attributeTypes.js +58 -0
- package/src/functions/baseUris.js +82 -0
- package/src/functions/collations.js +127 -0
- package/src/functions/collections.js +84 -0
- package/src/functions/context.js +83 -0
- package/src/functions/core.js +167 -0
- package/src/functions/datetime.js +203 -0
- package/src/functions/deepEqual.js +132 -0
- package/src/functions/diagnostics.js +88 -0
- package/src/functions/focus.js +34 -0
- package/src/functions/format/dateComponents.js +176 -0
- package/src/functions/format/datePicture.js +115 -0
- package/src/functions/format/decimalFormat.js +65 -0
- package/src/functions/format/digitPattern.js +145 -0
- package/src/functions/format/formatDateTime.js +204 -0
- package/src/functions/format/formatInteger.js +109 -0
- package/src/functions/format/formatNumber.js +165 -0
- package/src/functions/format/fractionFormat.js +80 -0
- package/src/functions/format/germanWords.js +89 -0
- package/src/functions/format/numberLanguages.js +41 -0
- package/src/functions/format/numberPicture.js +202 -0
- package/src/functions/format/numberWords.js +155 -0
- package/src/functions/format/place.js +74 -0
- package/src/functions/format/timezoneFormat.js +89 -0
- package/src/functions/higherOrder.js +106 -0
- package/src/functions/ids.js +127 -0
- package/src/functions/json/index.js +17 -0
- package/src/functions/json/jsonChars.js +110 -0
- package/src/functions/json/jsonParser.js +203 -0
- package/src/functions/json/jsonStrings.js +116 -0
- package/src/functions/json/jsonToXml.js +116 -0
- package/src/functions/json/parseJson.js +119 -0
- package/src/functions/json/xmlRepresentation.js +103 -0
- package/src/functions/json/xmlToJson.js +147 -0
- package/src/functions/library.js +47 -0
- package/src/functions/mapArrayEqual.js +41 -0
- package/src/functions/maps.js +152 -0
- package/src/functions/math.js +73 -0
- package/src/functions/nodePaths.js +181 -0
- package/src/functions/nodes.js +199 -0
- package/src/functions/numeric.js +148 -0
- package/src/functions/options.js +58 -0
- package/src/functions/parseIetfDate.js +104 -0
- package/src/functions/parseXml.js +77 -0
- package/src/functions/qnames.js +68 -0
- package/src/functions/random.js +128 -0
- package/src/functions/regex/analyzeString.js +144 -0
- package/src/functions/regex/charClass.js +112 -0
- package/src/functions/regex/compile.js +81 -0
- package/src/functions/regex/escapes.js +109 -0
- package/src/functions/regex/parser.js +169 -0
- package/src/functions/regex/reader.js +37 -0
- package/src/functions/regex/regexFunctions.js +140 -0
- package/src/functions/regex/translate.js +102 -0
- package/src/functions/regex/unicodeBlocks.js +194 -0
- package/src/functions/registry.js +140 -0
- package/src/functions/sequences.js +173 -0
- package/src/functions/serializeFunction.js +53 -0
- package/src/functions/signatures.js +105 -0
- package/src/functions/sort.js +102 -0
- package/src/functions/stringMatch.js +45 -0
- package/src/functions/strings.js +194 -0
- package/src/functions/stringsCore.js +66 -0
- package/src/functions/support.js +106 -0
- package/src/functions/textDecoding.js +117 -0
- package/src/functions/ucaCollation.js +127 -0
- package/src/functions/unparsedText.js +71 -0
- package/src/functions/uri.js +166 -0
- package/src/functions/xqueryModule.js +24 -0
- package/src/index.js +38 -0
- package/src/items/array.js +84 -0
- package/src/items/function.js +45 -0
- package/src/items/map.js +120 -0
- package/src/items/mapKey.js +82 -0
- package/src/serialize/index.js +129 -0
- package/src/serialize/markup/content.js +74 -0
- package/src/serialize/markup/dialect.js +178 -0
- package/src/serialize/markup/htmlData.js +70 -0
- package/src/serialize/markup/namespaces.js +145 -0
- package/src/serialize/markup/prolog.js +91 -0
- package/src/serialize/markup/writer.js +183 -0
- package/src/serialize/methods/adaptive.js +131 -0
- package/src/serialize/methods/json.js +158 -0
- package/src/serialize/methods/text.js +43 -0
- package/src/serialize/output/buffer.js +48 -0
- package/src/serialize/output/encoding.js +146 -0
- package/src/serialize/output/expander.js +204 -0
- package/src/serialize/params/fromElement.js +141 -0
- package/src/serialize/params/fromMap.js +128 -0
- package/src/serialize/params/names.js +69 -0
- package/src/serialize/params/settings.js +153 -0
- package/src/serialize/params/values.js +163 -0
- package/src/serialize/sequence.js +111 -0
- package/src/xdm/arithmetic.js +155 -0
- package/src/xdm/atomic.js +142 -0
- package/src/xdm/binary.js +92 -0
- package/src/xdm/calendar.js +71 -0
- package/src/xdm/cast.js +176 -0
- package/src/xdm/compare.js +192 -0
- package/src/xdm/datetime.js +206 -0
- package/src/xdm/decimal.js +200 -0
- package/src/xdm/duration.js +128 -0
- package/src/xdm/generalCompare.js +152 -0
- package/src/xdm/index.js +47 -0
- package/src/xdm/lexical.js +126 -0
- package/src/xdm/nodes.js +170 -0
- package/src/xdm/numeric.js +122 -0
- package/src/xdm/qname.js +65 -0
- package/src/xdm/strings.js +52 -0
- package/src/xdm/temporalArithmetic.js +180 -0
- package/src/xdm/timeline.js +68 -0
- package/src/xdm/types.js +178 -0
- package/src/xpath/eval/atomics.js +45 -0
- package/src/xpath/eval/axes.js +212 -0
- package/src/xpath/eval/calls.js +168 -0
- package/src/xpath/eval/coercion.js +146 -0
- package/src/xpath/eval/compiler.js +71 -0
- package/src/xpath/eval/constructors.js +129 -0
- package/src/xpath/eval/decimalFormats.js +93 -0
- package/src/xpath/eval/descendantMemo.js +77 -0
- package/src/xpath/eval/documentOrder.js +142 -0
- package/src/xpath/eval/domNodes.js +174 -0
- package/src/xpath/eval/dynamicCall.js +27 -0
- package/src/xpath/eval/dynamicContext.js +161 -0
- package/src/xpath/eval/flow.js +115 -0
- package/src/xpath/eval/functionItems.js +194 -0
- package/src/xpath/eval/groupedChildren.js +88 -0
- package/src/xpath/eval/inline.js +71 -0
- package/src/xpath/eval/namespaceNodes.js +90 -0
- package/src/xpath/eval/nodeTests.js +164 -0
- package/src/xpath/eval/operators.js +190 -0
- package/src/xpath/eval/paths.js +163 -0
- package/src/xpath/eval/positional.js +81 -0
- package/src/xpath/eval/predicates.js +56 -0
- package/src/xpath/eval/primary.js +99 -0
- package/src/xpath/eval/resources.js +149 -0
- package/src/xpath/eval/scope.js +108 -0
- package/src/xpath/eval/sequenceType.js +193 -0
- package/src/xpath/eval/staticContext.js +142 -0
- package/src/xpath/eval/steps.js +98 -0
- package/src/xpath/eval/subtype.js +154 -0
- package/src/xpath/eval/typeExprs.js +147 -0
- package/src/xpath/eval/typeNames.js +101 -0
- package/src/xpath/eval/uris.js +21 -0
- package/src/xpath/eval/values.js +64 -0
- package/src/xpath/index.js +217 -0
- package/src/xpath/syntax/ast.js +130 -0
- package/src/xpath/syntax/chars.js +58 -0
- package/src/xpath/syntax/constructors.js +144 -0
- package/src/xpath/syntax/expressions.js +107 -0
- package/src/xpath/syntax/index.js +44 -0
- package/src/xpath/syntax/kindTests.js +134 -0
- package/src/xpath/syntax/lexer.js +220 -0
- package/src/xpath/syntax/operators.js +111 -0
- package/src/xpath/syntax/paths.js +102 -0
- package/src/xpath/syntax/postfix.js +91 -0
- package/src/xpath/syntax/primaries.js +149 -0
- package/src/xpath/syntax/steps.js +146 -0
- package/src/xpath/syntax/syntaxError.js +31 -0
- package/src/xpath/syntax/tokenStream.js +163 -0
- package/src/xpath/syntax/typeAst.js +76 -0
- package/src/xpath/syntax/typeOperators.js +127 -0
- package/src/xpath/syntax/types.js +158 -0
- package/src/xslt/api.js +153 -0
- package/src/xslt/compiler/acceptance.js +178 -0
- package/src/xslt/compiler/accumulatorDecl.js +146 -0
- package/src/xslt/compiler/attributeValues.js +174 -0
- package/src/xslt/compiler/attributes.js +211 -0
- package/src/xslt/compiler/avt.js +103 -0
- package/src/xslt/compiler/body.js +154 -0
- package/src/xslt/compiler/children.js +105 -0
- package/src/xslt/compiler/compatibility.js +130 -0
- package/src/xslt/compiler/components.js +179 -0
- package/src/xslt/compiler/contextItem.js +95 -0
- package/src/xslt/compiler/decimalFormats.js +132 -0
- package/src/xslt/compiler/declarationKinds.js +82 -0
- package/src/xslt/compiler/elementInfo.js +246 -0
- package/src/xslt/compiler/expressions.js +175 -0
- package/src/xslt/compiler/globalContextItem.js +92 -0
- package/src/xslt/compiler/globals.js +209 -0
- package/src/xslt/compiler/linker.js +134 -0
- package/src/xslt/compiler/miscDecl.js +171 -0
- package/src/xslt/compiler/modeDecl.js +88 -0
- package/src/xslt/compiler/moduleLoading.js +111 -0
- package/src/xslt/compiler/modules.js +158 -0
- package/src/xslt/compiler/outputDecl.js +209 -0
- package/src/xslt/compiler/overrideLinks.js +141 -0
- package/src/xslt/compiler/packageChecks.js +84 -0
- package/src/xslt/compiler/packageRegistry.js +95 -0
- package/src/xslt/compiler/packageTable.js +181 -0
- package/src/xslt/compiler/packageVersions.js +143 -0
- package/src/xslt/compiler/packages.js +138 -0
- package/src/xslt/compiler/registry.js +234 -0
- package/src/xslt/compiler/staticStage.js +197 -0
- package/src/xslt/compiler/staticVariables.js +93 -0
- package/src/xslt/compiler/stylesheet.js +205 -0
- package/src/xslt/compiler/tailPosition.js +74 -0
- package/src/xslt/compiler/templatesDecl.js +180 -0
- package/src/xslt/compiler/useAccumulators.js +76 -0
- package/src/xslt/compiler/useWhen.js +94 -0
- package/src/xslt/compiler/visibility.js +160 -0
- package/src/xslt/index.js +11 -0
- package/src/xslt/instructions/analyzeString.js +137 -0
- package/src/xslt/instructions/assert.js +72 -0
- package/src/xslt/instructions/attributeSets.js +115 -0
- package/src/xslt/instructions/conditional.js +99 -0
- package/src/xslt/instructions/control.js +123 -0
- package/src/xslt/instructions/copy.js +151 -0
- package/src/xslt/instructions/elements.js +161 -0
- package/src/xslt/instructions/evaluate.js +189 -0
- package/src/xslt/instructions/fork.js +35 -0
- package/src/xslt/instructions/grouping.js +106 -0
- package/src/xslt/instructions/index.js +94 -0
- package/src/xslt/instructions/iterate.js +182 -0
- package/src/xslt/instructions/literal.js +142 -0
- package/src/xslt/instructions/maps.js +72 -0
- package/src/xslt/instructions/merge.js +190 -0
- package/src/xslt/instructions/number.js +205 -0
- package/src/xslt/instructions/output.js +102 -0
- package/src/xslt/instructions/params.js +110 -0
- package/src/xslt/instructions/resultDocument.js +143 -0
- package/src/xslt/instructions/sort.js +114 -0
- package/src/xslt/instructions/sourceDocument.js +73 -0
- package/src/xslt/instructions/templates.js +153 -0
- package/src/xslt/instructions/text.js +151 -0
- package/src/xslt/instructions/try.js +186 -0
- package/src/xslt/instructions/variables.js +119 -0
- package/src/xslt/names.js +204 -0
- package/src/xslt/patterns/axisOrigins.js +121 -0
- package/src/xslt/patterns/compile.js +151 -0
- package/src/xslt/patterns/general.js +132 -0
- package/src/xslt/patterns/grammar.js +190 -0
- package/src/xslt/patterns/modes.js +153 -0
- package/src/xslt/patterns/paths.js +130 -0
- package/src/xslt/patterns/patternChecks.js +29 -0
- package/src/xslt/patterns/steps.js +162 -0
- package/src/xslt/processor.js +178 -0
- package/src/xslt/runtime/accumulatorFunctions.js +48 -0
- package/src/xslt/runtime/accumulators.js +174 -0
- package/src/xslt/runtime/apply.js +153 -0
- package/src/xslt/runtime/atomicKeys.js +36 -0
- package/src/xslt/runtime/availability.js +162 -0
- package/src/xslt/runtime/baseUri.js +64 -0
- package/src/xslt/runtime/compilerHook.js +27 -0
- package/src/xslt/runtime/conditional.js +110 -0
- package/src/xslt/runtime/context.js +106 -0
- package/src/xslt/runtime/copy.js +123 -0
- package/src/xslt/runtime/copyFunctions.js +71 -0
- package/src/xslt/runtime/copyOrigins.js +60 -0
- package/src/xslt/runtime/defaultMethod.js +42 -0
- package/src/xslt/runtime/documentContent.js +93 -0
- package/src/xslt/runtime/dynamicXPath.js +90 -0
- package/src/xslt/runtime/functionCache.js +65 -0
- package/src/xslt/runtime/functionCall.js +57 -0
- package/src/xslt/runtime/functions.js +191 -0
- package/src/xslt/runtime/groups.js +108 -0
- package/src/xslt/runtime/invocation.js +156 -0
- package/src/xslt/runtime/iteration.js +107 -0
- package/src/xslt/runtime/keys.js +141 -0
- package/src/xslt/runtime/lazy.js +97 -0
- package/src/xslt/runtime/locations.js +86 -0
- package/src/xslt/runtime/machine.js +137 -0
- package/src/xslt/runtime/merging.js +167 -0
- package/src/xslt/runtime/namespaceScope.js +141 -0
- package/src/xslt/runtime/numberFormat.js +89 -0
- package/src/xslt/runtime/numbering.js +168 -0
- package/src/xslt/runtime/params.js +59 -0
- package/src/xslt/runtime/properties.js +103 -0
- package/src/xslt/runtime/rawResults.js +82 -0
- package/src/xslt/runtime/sequenceReceiver.js +102 -0
- package/src/xslt/runtime/snapshot.js +66 -0
- package/src/xslt/runtime/sortKeys.js +119 -0
- package/src/xslt/runtime/streamAvailable.js +60 -0
- package/src/xslt/runtime/strip.js +102 -0
- package/src/xslt/runtime/transformFunction.js +169 -0
- package/src/xslt/runtime/transformation.js +168 -0
- package/src/xslt/runtime/transformationContext.js +85 -0
- package/src/xslt/runtime/treeReceiver.js +194 -0
- 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
|
+
}
|