@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,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xsl:decimal-format declarations (XSLT 3.0 section 21.2.1): the
|
|
3
|
+
* properties of each format merged by import precedence and checked,
|
|
4
|
+
* as definitions for the XPath static context (see
|
|
5
|
+
* xpath/eval/decimalFormats.js).
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/compiler/decimalFormats
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { clarkOf, xsltError } from "../names.js";
|
|
11
|
+
|
|
12
|
+
/** Properties holding one character. */
|
|
13
|
+
const CHARACTERS = [
|
|
14
|
+
"decimal-separator",
|
|
15
|
+
"grouping-separator",
|
|
16
|
+
"minus-sign",
|
|
17
|
+
"exponent-separator",
|
|
18
|
+
"percent",
|
|
19
|
+
"per-mille",
|
|
20
|
+
"zero-digit",
|
|
21
|
+
"digit",
|
|
22
|
+
"pattern-separator",
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
/** Properties holding a string. */
|
|
26
|
+
const STRINGS = ["infinity", "NaN"];
|
|
27
|
+
|
|
28
|
+
/** Properties whose characters must differ (XTSE1300). */
|
|
29
|
+
const DISTINCT = [
|
|
30
|
+
"decimal-separator",
|
|
31
|
+
"grouping-separator",
|
|
32
|
+
"exponent-separator",
|
|
33
|
+
"percent",
|
|
34
|
+
"per-mille",
|
|
35
|
+
"digit",
|
|
36
|
+
"pattern-separator",
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/** Default values of the distinct properties. */
|
|
40
|
+
const DEFAULTS = {
|
|
41
|
+
"decimal-separator": ".",
|
|
42
|
+
"grouping-separator": ",",
|
|
43
|
+
"exponent-separator": "e",
|
|
44
|
+
percent: "%",
|
|
45
|
+
"per-mille": "‰",
|
|
46
|
+
digit: "#",
|
|
47
|
+
"pattern-separator": ";",
|
|
48
|
+
"zero-digit": "0",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether a code point is a decimal digit with value zero: Unicode
|
|
53
|
+
* decimal digits come in runs of ten, from zero to nine.
|
|
54
|
+
* @param {number} codePoint
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
function isZeroDigit(codePoint) {
|
|
58
|
+
const digit = (cp) => /^\p{Nd}$/u.test(String.fromCodePoint(cp));
|
|
59
|
+
if (!digit(codePoint)) return false;
|
|
60
|
+
let before = 0;
|
|
61
|
+
while (codePoint - before - 1 >= 0 && digit(codePoint - before - 1)) {
|
|
62
|
+
before++;
|
|
63
|
+
}
|
|
64
|
+
return before % 10 === 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Checks a merged format: zero-digit is a digit with value 0, and the
|
|
69
|
+
* picture characters are distinct (the ten digits included).
|
|
70
|
+
* @param {object} format
|
|
71
|
+
*/
|
|
72
|
+
function checkFormat(format) {
|
|
73
|
+
const zero = format["zero-digit"] ?? "0";
|
|
74
|
+
const base = zero.codePointAt(0);
|
|
75
|
+
if (!isZeroDigit(base)) {
|
|
76
|
+
throw xsltError("XTSE1295", "zero-digit must be a digit with value zero");
|
|
77
|
+
}
|
|
78
|
+
const used = new Set();
|
|
79
|
+
for (let i = 0; i < 10; i++) used.add(String.fromCodePoint(base + i));
|
|
80
|
+
for (const property of DISTINCT) {
|
|
81
|
+
const value = format[property] ?? DEFAULTS[property];
|
|
82
|
+
if (used.has(value)) {
|
|
83
|
+
throw xsltError("XTSE1300", `The decimal format uses ${value} twice`);
|
|
84
|
+
}
|
|
85
|
+
used.add(value);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Collects the decimal formats.
|
|
91
|
+
* @param {object[]} declarations
|
|
92
|
+
* @param {object} cx
|
|
93
|
+
* @returns {object[]} definitions with a `name` (Q{uri}local, "" for the
|
|
94
|
+
* default format)
|
|
95
|
+
*/
|
|
96
|
+
export function collectDecimalFormats(declarations, cx) {
|
|
97
|
+
const formats = new Map();
|
|
98
|
+
for (const { element, precedence } of declarations) {
|
|
99
|
+
const nameText = element.getAttribute("name");
|
|
100
|
+
const name = nameText
|
|
101
|
+
? `Q${clarkOf(cx.exprs.qname(nameText, element))}`
|
|
102
|
+
: "";
|
|
103
|
+
const format = formats.get(name) ?? { name, from: {}, conflict: {} };
|
|
104
|
+
for (const property of [...CHARACTERS, ...STRINGS]) {
|
|
105
|
+
if (!element.hasAttribute(property)) continue;
|
|
106
|
+
const value = element.getAttribute(property);
|
|
107
|
+
if (CHARACTERS.includes(property) && [...value].length !== 1) {
|
|
108
|
+
throw xsltError("XTSE0020", `${property} must be one character`);
|
|
109
|
+
}
|
|
110
|
+
if (format.from[property] === precedence && format[property] !== value) {
|
|
111
|
+
format.conflict[property] = precedence;
|
|
112
|
+
}
|
|
113
|
+
if (
|
|
114
|
+
format.from[property] === undefined ||
|
|
115
|
+
format.from[property] <= precedence
|
|
116
|
+
) {
|
|
117
|
+
format[property] = value;
|
|
118
|
+
format.from[property] = precedence;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
formats.set(name, format);
|
|
122
|
+
}
|
|
123
|
+
for (const format of formats.values()) {
|
|
124
|
+
for (const [property, precedence] of Object.entries(format.conflict)) {
|
|
125
|
+
if (format.from[property] === precedence) {
|
|
126
|
+
throw xsltError("XTSE1290", `Conflicting values of ${property}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
checkFormat(format);
|
|
130
|
+
}
|
|
131
|
+
return [...formats.values()];
|
|
132
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The top-level declarations of a stylesheet module tree, grouped by kind
|
|
3
|
+
* and checked: known XSLT declarations (XTSE0010), elements in no
|
|
4
|
+
* namespace (XTSE0130), xsl:expose only in xsl:package, empty
|
|
5
|
+
* declarations (XTSE0260), no xsl:import-schema (XTSE1650: this
|
|
6
|
+
* processor is not schema aware).
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/xslt/compiler/declarationKinds
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { isXsl, XSL_NS, xsltError } from "../names.js";
|
|
12
|
+
import { checkAttributes, checkEmpty } from "./attributes.js";
|
|
13
|
+
import { infoOf } from "./elementInfo.js";
|
|
14
|
+
import { declarationsOf } from "./modules.js";
|
|
15
|
+
|
|
16
|
+
/** Top-level XSLT declarations. */
|
|
17
|
+
const DECLARATIONS = new Set([
|
|
18
|
+
"template",
|
|
19
|
+
"function",
|
|
20
|
+
"variable",
|
|
21
|
+
"param",
|
|
22
|
+
"key",
|
|
23
|
+
"output",
|
|
24
|
+
"decimal-format",
|
|
25
|
+
"namespace-alias",
|
|
26
|
+
"strip-space",
|
|
27
|
+
"preserve-space",
|
|
28
|
+
"character-map",
|
|
29
|
+
"attribute-set",
|
|
30
|
+
"mode",
|
|
31
|
+
"import-schema",
|
|
32
|
+
"global-context-item",
|
|
33
|
+
"accumulator",
|
|
34
|
+
"use-package",
|
|
35
|
+
"expose",
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
/** Declarations that must be empty. */
|
|
39
|
+
const EMPTY_DECLARATIONS = new Set([
|
|
40
|
+
"strip-space",
|
|
41
|
+
"preserve-space",
|
|
42
|
+
"namespace-alias",
|
|
43
|
+
"output",
|
|
44
|
+
"decimal-format",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The declarations of a module tree by kind, checked.
|
|
49
|
+
* @param {object} tree - See modules.js
|
|
50
|
+
* @param {object} cx - Stylesheet compiler (records the precedences)
|
|
51
|
+
* @returns {(kind: string) => object[]} the declarations of a kind
|
|
52
|
+
*/
|
|
53
|
+
export function collectDeclarations(tree, cx) {
|
|
54
|
+
const packageRoot = isXsl(tree.root, "package") ? tree.root : null;
|
|
55
|
+
const byKind = new Map();
|
|
56
|
+
for (const declaration of declarationsOf(tree)) {
|
|
57
|
+
const { element, simplified } = declaration;
|
|
58
|
+
const kind = simplified ? "simplified" : element.localName;
|
|
59
|
+
if (!simplified && element.namespaceURI !== XSL_NS) {
|
|
60
|
+
if (!element.namespaceURI) {
|
|
61
|
+
throw xsltError("XTSE0130", `${element.nodeName} has no namespace`);
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (!simplified && !DECLARATIONS.has(kind)) {
|
|
66
|
+
if (infoOf(element).version > 3) continue;
|
|
67
|
+
throw xsltError("XTSE0010", `xsl:${kind} is not a declaration`);
|
|
68
|
+
}
|
|
69
|
+
if (kind === "expose" && element.parentNode !== packageRoot) {
|
|
70
|
+
throw xsltError("XTSE0010", "xsl:expose belongs in xsl:package");
|
|
71
|
+
}
|
|
72
|
+
if (!simplified) checkAttributes(element);
|
|
73
|
+
if (EMPTY_DECLARATIONS.has(kind)) checkEmpty(element, cx);
|
|
74
|
+
if (!byKind.has(kind)) byKind.set(kind, []);
|
|
75
|
+
byKind.get(kind).push(declaration);
|
|
76
|
+
cx.declarationPrecedence.set(element, declaration.precedence);
|
|
77
|
+
}
|
|
78
|
+
if (byKind.has("import-schema")) {
|
|
79
|
+
throw xsltError("XTSE1650", "xsl:import-schema needs schema awareness");
|
|
80
|
+
}
|
|
81
|
+
return (kind) => byKind.get(kind) ?? [];
|
|
82
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a stylesheet element inherits from its ancestors: in-scope
|
|
3
|
+
* namespaces, the effective version, the standard attributes
|
|
4
|
+
* xpath-default-namespace, default-collation, exclude-result-prefixes,
|
|
5
|
+
* extension-element-prefixes and expand-text, and the base URI (xml:base).
|
|
6
|
+
* Computed once per element and cached.
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/xslt/compiler/elementInfo
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { getCollation } from "../../functions/collations.js";
|
|
12
|
+
import { resolveUri } from "../../xpath/eval/uris.js";
|
|
13
|
+
import {
|
|
14
|
+
clarkOf,
|
|
15
|
+
RESERVED_NAMESPACES,
|
|
16
|
+
resolveQName,
|
|
17
|
+
standardAttr,
|
|
18
|
+
tokens,
|
|
19
|
+
XML_NS,
|
|
20
|
+
XMLNS_NS,
|
|
21
|
+
XSL_NS,
|
|
22
|
+
xsltError,
|
|
23
|
+
} from "../names.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {object} ElementInfo
|
|
27
|
+
* @property {Map<string, string>} namespaces - Prefix to URI ("" default)
|
|
28
|
+
* @property {number} version - Effective version
|
|
29
|
+
* @property {string} xpathDefaultNs - Default element namespace of XPath
|
|
30
|
+
* @property {string|undefined} defaultCollation - Collation URI
|
|
31
|
+
* @property {string|undefined} baseUri
|
|
32
|
+
* @property {Set<string>} excluded - Excluded result namespace URIs
|
|
33
|
+
* @property {Set<string>} extension - Extension namespace URIs
|
|
34
|
+
* @property {boolean} expandText - Text value templates enabled
|
|
35
|
+
* @property {string} defaultMode - Clark name, "" for the unnamed mode
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/** @type {WeakMap<Element, ElementInfo>} */
|
|
39
|
+
const cache = new WeakMap();
|
|
40
|
+
/** @type {WeakMap<Element, string>} base URIs of module roots */
|
|
41
|
+
const moduleUris = new WeakMap();
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Records the URI of a stylesheet module, the base URI of its root.
|
|
45
|
+
* @param {Element} root
|
|
46
|
+
* @param {string|undefined} uri
|
|
47
|
+
*/
|
|
48
|
+
export function setModuleUri(root, uri) {
|
|
49
|
+
if (uri !== undefined) moduleUris.set(root, uri);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Forgets the info of an element whose attributes changed (shadow
|
|
54
|
+
* attributes evaluated after its use-when condition read its info).
|
|
55
|
+
* @param {Element} element
|
|
56
|
+
*/
|
|
57
|
+
export function forgetInfo(element) {
|
|
58
|
+
cache.delete(element);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The URI of the stylesheet module an element belongs to.
|
|
63
|
+
* @param {Node} element
|
|
64
|
+
* @returns {string|undefined}
|
|
65
|
+
*/
|
|
66
|
+
export function moduleUriOf(element) {
|
|
67
|
+
for (let node = element; node?.nodeType === 1; node = node.parentNode) {
|
|
68
|
+
if (moduleUris.has(node)) return moduleUris.get(node);
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const ROOT_INFO = Object.freeze({
|
|
74
|
+
namespaces: new Map([["xml", XML_NS]]),
|
|
75
|
+
version: 3,
|
|
76
|
+
xpathDefaultNs: "",
|
|
77
|
+
defaultCollation: undefined,
|
|
78
|
+
baseUri: undefined,
|
|
79
|
+
excluded: new Set([XSL_NS]),
|
|
80
|
+
extension: new Set(),
|
|
81
|
+
expandText: false,
|
|
82
|
+
defaultMode: "",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {Element} element
|
|
87
|
+
* @param {Map<string, string>} inherited
|
|
88
|
+
* @returns {Map<string, string>} the in-scope namespaces of the element
|
|
89
|
+
*/
|
|
90
|
+
function namespacesOf(element, inherited) {
|
|
91
|
+
let namespaces = inherited;
|
|
92
|
+
for (const attribute of element.attributes) {
|
|
93
|
+
const name = attribute.name;
|
|
94
|
+
const declaration =
|
|
95
|
+
attribute.namespaceURI === XMLNS_NS ||
|
|
96
|
+
name === "xmlns" ||
|
|
97
|
+
name.startsWith("xmlns:");
|
|
98
|
+
if (!declaration) continue;
|
|
99
|
+
if (namespaces === inherited) namespaces = new Map(inherited);
|
|
100
|
+
namespaces.set(name === "xmlns" ? "" : name.slice(6), attribute.value);
|
|
101
|
+
}
|
|
102
|
+
if (element.namespaceURI && !namespaces.has(element.prefix ?? "")) {
|
|
103
|
+
if (namespaces === inherited) namespaces = new Map(inherited);
|
|
104
|
+
namespaces.set(element.prefix ?? "", element.namespaceURI);
|
|
105
|
+
}
|
|
106
|
+
return namespaces;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* URIs of a list of prefixes (exclude-result-prefixes and friends).
|
|
111
|
+
* @param {string} text
|
|
112
|
+
* @param {Map<string, string>} namespaces
|
|
113
|
+
* @param {Set<string>} into - Receives the URIs
|
|
114
|
+
* @param {string} code - Error code for an undeclared prefix
|
|
115
|
+
*/
|
|
116
|
+
function addPrefixUris(text, namespaces, into, code) {
|
|
117
|
+
for (const token of tokens(text)) {
|
|
118
|
+
if (token === "#all") {
|
|
119
|
+
for (const uri of namespaces.values()) into.add(uri);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const prefix = token === "#default" ? "" : token;
|
|
123
|
+
const uri = namespaces.get(prefix);
|
|
124
|
+
if (uri === undefined || (uri === "" && prefix !== "")) {
|
|
125
|
+
throw xsltError(
|
|
126
|
+
prefix === "" ? "XTSE0809" : code,
|
|
127
|
+
`No namespace is bound to the prefix "${token}"`,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
into.add(uri);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The first collation of a default-collation list that is supported.
|
|
136
|
+
* @param {string} text
|
|
137
|
+
* @param {string|undefined} base
|
|
138
|
+
* @returns {string}
|
|
139
|
+
*/
|
|
140
|
+
function chooseCollation(text, base) {
|
|
141
|
+
for (const token of tokens(text)) {
|
|
142
|
+
const uri = resolveUri(token, base);
|
|
143
|
+
try {
|
|
144
|
+
getCollation(uri);
|
|
145
|
+
return uri;
|
|
146
|
+
} catch {
|
|
147
|
+
// try the next one
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
throw xsltError("XTSE0125", `No supported collation in "${text}"`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* The parsed version attribute.
|
|
155
|
+
* @param {string} text
|
|
156
|
+
* @returns {number}
|
|
157
|
+
*/
|
|
158
|
+
function parseVersion(text) {
|
|
159
|
+
if (!/^\s*\+?(\d+(\.\d*)?|\.\d+)\s*$/.test(text)) {
|
|
160
|
+
throw xsltError("XTSE0110", `Invalid version "${text}"`);
|
|
161
|
+
}
|
|
162
|
+
return Number(text);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Computes the info of an element from the info of its parent.
|
|
167
|
+
* @param {Element} element
|
|
168
|
+
* @param {ElementInfo} parent
|
|
169
|
+
* @returns {ElementInfo}
|
|
170
|
+
*/
|
|
171
|
+
function computeInfo(element, parent) {
|
|
172
|
+
const info = { ...parent };
|
|
173
|
+
info.namespaces = namespacesOf(element, parent.namespaces);
|
|
174
|
+
const own = (name) => standardAttr(element, name);
|
|
175
|
+
const xmlBase = element.getAttributeNS(XML_NS, "base");
|
|
176
|
+
const moduleUri = moduleUris.get(element);
|
|
177
|
+
if (moduleUri !== undefined) info.baseUri = moduleUri;
|
|
178
|
+
if (xmlBase) info.baseUri = resolveUri(xmlBase, info.baseUri);
|
|
179
|
+
const version = own("version");
|
|
180
|
+
if (version !== undefined) info.version = parseVersion(version);
|
|
181
|
+
const xpathNs = own("xpath-default-namespace");
|
|
182
|
+
if (xpathNs !== undefined) info.xpathDefaultNs = xpathNs.trim();
|
|
183
|
+
const collation = own("default-collation");
|
|
184
|
+
if (collation !== undefined) {
|
|
185
|
+
info.defaultCollation = chooseCollation(collation, info.baseUri);
|
|
186
|
+
}
|
|
187
|
+
const excluded = own("exclude-result-prefixes");
|
|
188
|
+
const extension = own("extension-element-prefixes");
|
|
189
|
+
if (excluded !== undefined || extension !== undefined) {
|
|
190
|
+
info.excluded = new Set(parent.excluded);
|
|
191
|
+
addPrefixUris(excluded, info.namespaces, info.excluded, "XTSE0808");
|
|
192
|
+
}
|
|
193
|
+
if (extension !== undefined) {
|
|
194
|
+
info.extension = new Set(parent.extension);
|
|
195
|
+
addPrefixUris(extension, info.namespaces, info.extension, "XTSE1430");
|
|
196
|
+
for (const uri of info.extension) {
|
|
197
|
+
if (RESERVED_NAMESPACES.has(uri)) {
|
|
198
|
+
throw xsltError("XTSE0085", `${uri} cannot be an extension namespace`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const uri of info.extension) info.excluded.add(uri);
|
|
202
|
+
}
|
|
203
|
+
const defaultMode = own("default-mode");
|
|
204
|
+
if (defaultMode !== undefined) {
|
|
205
|
+
const text = defaultMode.trim();
|
|
206
|
+
info.defaultMode =
|
|
207
|
+
text === "#unnamed"
|
|
208
|
+
? ""
|
|
209
|
+
: clarkOf(resolveQName(text, info.namespaces, { code: "XTSE0545" }));
|
|
210
|
+
}
|
|
211
|
+
const expand = own("expand-text");
|
|
212
|
+
if (expand !== undefined) {
|
|
213
|
+
const value = expand.trim();
|
|
214
|
+
if (!["yes", "true", "1", "no", "false", "0"].includes(value)) {
|
|
215
|
+
throw xsltError("XTSE0020", `Invalid expand-text "${expand}"`);
|
|
216
|
+
}
|
|
217
|
+
info.expandText = ["yes", "true", "1"].includes(value);
|
|
218
|
+
}
|
|
219
|
+
return info;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The info of a stylesheet element.
|
|
224
|
+
* @param {Element} element
|
|
225
|
+
* @returns {ElementInfo}
|
|
226
|
+
*/
|
|
227
|
+
export function infoOf(element) {
|
|
228
|
+
let info = cache.get(element);
|
|
229
|
+
if (info) return info;
|
|
230
|
+
const chain = [];
|
|
231
|
+
let current = element;
|
|
232
|
+
while (current && current.nodeType === 1 && !cache.has(current)) {
|
|
233
|
+
chain.push(current);
|
|
234
|
+
if (moduleUris.has(current)) break;
|
|
235
|
+
current = current.parentNode;
|
|
236
|
+
}
|
|
237
|
+
info =
|
|
238
|
+
current && current.nodeType === 1 && cache.has(current)
|
|
239
|
+
? cache.get(current)
|
|
240
|
+
: ROOT_INFO;
|
|
241
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
242
|
+
info = computeInfo(chain[i], info);
|
|
243
|
+
cache.set(chain[i], info);
|
|
244
|
+
}
|
|
245
|
+
return info;
|
|
246
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XPath in a stylesheet: the static context of each stylesheet element
|
|
3
|
+
* (in-scope namespaces, xpath-default-namespace, base URI, backwards
|
|
4
|
+
* compatibility, decimal formats, the function library with the
|
|
5
|
+
* stylesheet functions), and the compilation of expressions, sequence
|
|
6
|
+
* types and attribute value templates against the variables in scope.
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/xslt/compiler/expressions
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { compileNode, withinLimits } from "../../xpath/eval/compiler.js";
|
|
12
|
+
import { compileSequenceType } from "../../xpath/eval/sequenceType.js";
|
|
13
|
+
import { createStaticContext } from "../../xpath/eval/staticContext.js";
|
|
14
|
+
import { parseXPath } from "../../xpath/syntax/index.js";
|
|
15
|
+
import { TokenStream } from "../../xpath/syntax/tokenStream.js";
|
|
16
|
+
import { parseSequenceType } from "../../xpath/syntax/types.js";
|
|
17
|
+
import { XPathError } from "../../errors.js";
|
|
18
|
+
import { resolveQName } from "../names.js";
|
|
19
|
+
import { parseAvt } from "./avt.js";
|
|
20
|
+
import { infoOf } from "./elementInfo.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A compiled XPath expression of the stylesheet.
|
|
24
|
+
* @typedef {object} Expr
|
|
25
|
+
* @property {(ctx: object) => Array} run - The evaluator
|
|
26
|
+
* @property {string} text - Source text
|
|
27
|
+
* @property {object} sc - Static context
|
|
28
|
+
* @property {object} ast - Syntax tree
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** The namespace of the standard functions. */
|
|
32
|
+
const FN_NS = "http://www.w3.org/2005/xpath-functions";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* In backwards-compatible mode a call of an unknown extension function
|
|
36
|
+
* is an error only when evaluated (XSLT 3.0 section 24.1.2, XTDE1425).
|
|
37
|
+
* @param {Error} error - Raised by the XPath compiler
|
|
38
|
+
* @param {object} sc - Static context of the expression
|
|
39
|
+
* @returns {(ctx: object) => Array} an evaluator raising XTDE1425
|
|
40
|
+
* @throws {Error} the error otherwise
|
|
41
|
+
*/
|
|
42
|
+
function unavailableFunction(error, sc) {
|
|
43
|
+
const uri = /^XPST0017: Unknown function Q\{([^}]*)\}/.exec(
|
|
44
|
+
error.message,
|
|
45
|
+
)?.[1];
|
|
46
|
+
if (!sc.backwardsCompatible || uri === undefined || uri === FN_NS) {
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
return () => {
|
|
50
|
+
throw new XPathError("XTDE1425", error.message.slice(10));
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Compiles the XPath expressions of a stylesheet. */
|
|
55
|
+
export class ExpressionCompiler {
|
|
56
|
+
/**
|
|
57
|
+
* @param {object} options
|
|
58
|
+
* @param {import("../../functions/registry.js").FunctionLibrary} options.library
|
|
59
|
+
* @param {Array<object>} [options.decimalFormats] - Definitions
|
|
60
|
+
* @param {object} [options.owner] - Package compiler of the expressions
|
|
61
|
+
*/
|
|
62
|
+
constructor({ library, decimalFormats = [], owner = null }) {
|
|
63
|
+
this.library = library;
|
|
64
|
+
this.decimalFormats = decimalFormats;
|
|
65
|
+
/** The package compiler whose keys key() reads (null: the stylesheet's) */
|
|
66
|
+
this.owner = owner;
|
|
67
|
+
/** @type {WeakMap<Map, Map<string, object>>} */
|
|
68
|
+
this.cache = new WeakMap();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The static context of the expressions of a stylesheet element.
|
|
73
|
+
* @param {Element} element
|
|
74
|
+
* @returns {object} an XPath static context
|
|
75
|
+
*/
|
|
76
|
+
staticContext(element) {
|
|
77
|
+
const info = infoOf(element);
|
|
78
|
+
let byKey = this.cache.get(info.namespaces);
|
|
79
|
+
if (!byKey) {
|
|
80
|
+
byKey = new Map();
|
|
81
|
+
this.cache.set(info.namespaces, byKey);
|
|
82
|
+
}
|
|
83
|
+
const compatible = info.version < 2;
|
|
84
|
+
const key = `${info.xpathDefaultNs}|${info.baseUri}|${compatible}`;
|
|
85
|
+
let sc = byKey.get(key);
|
|
86
|
+
if (!sc) {
|
|
87
|
+
const namespaces = new Map(
|
|
88
|
+
[...info.namespaces].filter(([p]) => p !== ""),
|
|
89
|
+
);
|
|
90
|
+
sc = createStaticContext(
|
|
91
|
+
{
|
|
92
|
+
namespaces,
|
|
93
|
+
defaultElementNamespace: info.xpathDefaultNs,
|
|
94
|
+
baseUri: info.baseUri,
|
|
95
|
+
backwardsCompatible: compatible,
|
|
96
|
+
decimalFormats: this.decimalFormats,
|
|
97
|
+
},
|
|
98
|
+
this.library,
|
|
99
|
+
);
|
|
100
|
+
sc.owner = this.owner;
|
|
101
|
+
// for element-available(), whose unprefixed names use it
|
|
102
|
+
sc.defaultNamespace = info.namespaces.get("") ?? "";
|
|
103
|
+
byKey.set(key, sc);
|
|
104
|
+
}
|
|
105
|
+
return sc;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Compiles an XPath expression written on a stylesheet element.
|
|
110
|
+
* @param {string} text
|
|
111
|
+
* @param {Element} element
|
|
112
|
+
* @param {object|null} vars - Variables in scope (see eval/scope.js)
|
|
113
|
+
* @returns {Expr}
|
|
114
|
+
*/
|
|
115
|
+
xpath(text, element, vars) {
|
|
116
|
+
const sc = this.staticContext(element);
|
|
117
|
+
const ast = parseXPath(text);
|
|
118
|
+
const run = withinLimits(() => {
|
|
119
|
+
try {
|
|
120
|
+
return compileNode(ast, { sc, vars });
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return unavailableFunction(error, sc);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
return { run, text, sc, ast };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Compiles an XPath AST (patterns compile their parts this way).
|
|
130
|
+
* @param {object} ast
|
|
131
|
+
* @param {object} sc
|
|
132
|
+
* @param {object|null} vars
|
|
133
|
+
* @returns {(ctx: object) => Array}
|
|
134
|
+
*/
|
|
135
|
+
compileAst(ast, sc, vars) {
|
|
136
|
+
return withinLimits(() => compileNode(ast, { sc, vars }));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Compiles a sequence type (an `as` attribute).
|
|
141
|
+
* @param {string} text
|
|
142
|
+
* @param {Element} element
|
|
143
|
+
* @returns {import("../../xpath/eval/sequenceType.js").SequenceType}
|
|
144
|
+
*/
|
|
145
|
+
sequenceType(text, element) {
|
|
146
|
+
const tokens = new TokenStream(text);
|
|
147
|
+
const node = parseSequenceType(tokens);
|
|
148
|
+
if (tokens.peek().type !== "eof") tokens.fail("Unexpected token");
|
|
149
|
+
return compileSequenceType(node, this.staticContext(element));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Compiles an attribute value template.
|
|
154
|
+
* @param {string} text
|
|
155
|
+
* @param {Element} element
|
|
156
|
+
* @param {object|null} vars
|
|
157
|
+
* @returns {Array<string|Expr>} literal parts and expressions
|
|
158
|
+
*/
|
|
159
|
+
avt(text, element, vars) {
|
|
160
|
+
return parseAvt(text).map((part) =>
|
|
161
|
+
typeof part === "string" ? part : this.xpath(part.expr, element, vars),
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Resolves a QName attribute value of a stylesheet element.
|
|
167
|
+
* @param {string} text
|
|
168
|
+
* @param {Element} element
|
|
169
|
+
* @param {object} [options] - See names.resolveQName
|
|
170
|
+
* @returns {import("../names.js").ExpandedName}
|
|
171
|
+
*/
|
|
172
|
+
qname(text, element, options) {
|
|
173
|
+
return resolveQName(text, infoOf(element).namespaces, options);
|
|
174
|
+
}
|
|
175
|
+
}
|