@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,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fn:xml-to-json (F&O 3.1 section 17.5.4): the XML representation of JSON
|
|
3
|
+
* (elements map, array, string, number, boolean and null in the fn
|
|
4
|
+
* namespace) to a JSON text. The input is checked against the rules of
|
|
5
|
+
* the schema for that representation (FOJS0006); comments, processing
|
|
6
|
+
* instructions and whitespace between elements are ignored.
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/functions/json/xmlToJson
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { formatDouble, parseDouble } from "../../xdm/numeric.js";
|
|
12
|
+
import { normalizeWhitespace, parseBoolean } from "../../xdm/strings.js";
|
|
13
|
+
import { readOptions } from "../options.js";
|
|
14
|
+
import { define, FN_NAMESPACE, stringItem } from "../support.js";
|
|
15
|
+
import { unescapeJsonChars } from "./jsonChars.js";
|
|
16
|
+
import { escapeChar, escapeJsonString, needsEscape } from "./jsonStrings.js";
|
|
17
|
+
import {
|
|
18
|
+
checkAttributes,
|
|
19
|
+
flag,
|
|
20
|
+
invalid,
|
|
21
|
+
members,
|
|
22
|
+
textOf,
|
|
23
|
+
} from "./xmlRepresentation.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A JSON string literal of a string or key.
|
|
27
|
+
* @param {string} text
|
|
28
|
+
* @param {boolean} escaped - The text holds JSON escape sequences, kept
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
function quote(text, escaped) {
|
|
32
|
+
if (!escaped) return `"${escapeJsonString(text)}"`;
|
|
33
|
+
let result = "";
|
|
34
|
+
for (const { cp, escape } of unescapeJsonChars(text)) {
|
|
35
|
+
result +=
|
|
36
|
+
escape ?? (needsEscape(cp) ? escapeChar(cp) : String.fromCodePoint(cp));
|
|
37
|
+
}
|
|
38
|
+
return `"${result}"`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Writes one element of the representation.
|
|
43
|
+
* @param {Element} element
|
|
44
|
+
* @param {boolean} inMap - The element is an entry of a map (needs a key)
|
|
45
|
+
* @param {string} indent - Line break and indentation, "" when not indenting
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
function write(element, inMap, indent) {
|
|
49
|
+
if (element.namespaceURI !== FN_NAMESPACE) {
|
|
50
|
+
invalid(`element {${element.namespaceURI ?? ""}}${element.localName}`);
|
|
51
|
+
}
|
|
52
|
+
const name = element.localName;
|
|
53
|
+
checkAttributes(element);
|
|
54
|
+
if (inMap && !element.hasAttribute("key")) invalid("an entry without key");
|
|
55
|
+
flag(element, "escaped-key");
|
|
56
|
+
const inner = indent && `${indent} `;
|
|
57
|
+
const list = (open, close, items) =>
|
|
58
|
+
items.length
|
|
59
|
+
? `${open}${items.map((item) => inner + item).join(",")}${indent}${close}`
|
|
60
|
+
: `${open}${close}`;
|
|
61
|
+
switch (name) {
|
|
62
|
+
case "map": {
|
|
63
|
+
const keys = new Set();
|
|
64
|
+
const entries = members(element).map((child) => {
|
|
65
|
+
const escaped = flag(child, "escaped-key");
|
|
66
|
+
const raw = child.getAttribute("key") ?? "";
|
|
67
|
+
const key = escaped ? unescapeKey(raw) : raw;
|
|
68
|
+
if (keys.has(key)) invalid(`duplicate key "${key}"`);
|
|
69
|
+
keys.add(key);
|
|
70
|
+
const separator = indent ? ": " : ":";
|
|
71
|
+
return `${quote(raw, escaped)}${separator}${write(child, true, inner)}`;
|
|
72
|
+
});
|
|
73
|
+
return list("{", "}", entries);
|
|
74
|
+
}
|
|
75
|
+
case "array":
|
|
76
|
+
return list(
|
|
77
|
+
"[",
|
|
78
|
+
"]",
|
|
79
|
+
members(element).map((child) => write(child, false, inner)),
|
|
80
|
+
);
|
|
81
|
+
case "string":
|
|
82
|
+
return quote(textOf(element), flag(element, "escaped"));
|
|
83
|
+
case "number": {
|
|
84
|
+
const value = parseDouble(
|
|
85
|
+
normalizeWhitespace(textOf(element), "collapse"),
|
|
86
|
+
);
|
|
87
|
+
if (value === null || !Number.isFinite(value)) invalid("number");
|
|
88
|
+
return formatDouble(value);
|
|
89
|
+
}
|
|
90
|
+
case "boolean": {
|
|
91
|
+
const value = parseBoolean(
|
|
92
|
+
normalizeWhitespace(textOf(element), "collapse"),
|
|
93
|
+
);
|
|
94
|
+
if (value === null) invalid("boolean");
|
|
95
|
+
return String(value);
|
|
96
|
+
}
|
|
97
|
+
case "null":
|
|
98
|
+
if (/\S/.test(textOf(element))) invalid("content in <null>");
|
|
99
|
+
return "null";
|
|
100
|
+
default:
|
|
101
|
+
return invalid(`element <${name}>`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The unescaped form of an escaped key, for duplicate detection.
|
|
107
|
+
* @param {string} key
|
|
108
|
+
* @returns {string}
|
|
109
|
+
*/
|
|
110
|
+
const unescapeKey = (key) =>
|
|
111
|
+
unescapeJsonChars(key)
|
|
112
|
+
.map(({ cp }) => String.fromCodePoint(cp))
|
|
113
|
+
.join("");
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* fn:xml-to-json of a node.
|
|
117
|
+
* @param {Node} node - Document or element node
|
|
118
|
+
* @param {Array} [optionsArg]
|
|
119
|
+
* @returns {Array} an xs:string
|
|
120
|
+
*/
|
|
121
|
+
function xmlToJson(node, optionsArg) {
|
|
122
|
+
const { indent } = readOptions(
|
|
123
|
+
optionsArg?.[0],
|
|
124
|
+
{ indent: { type: "xs:boolean", default: false } },
|
|
125
|
+
"FOJS0005",
|
|
126
|
+
);
|
|
127
|
+
let element = node;
|
|
128
|
+
// 11: a temporary tree (xsl:variable without "as") is a document node
|
|
129
|
+
if (node.nodeType === 9 || node.nodeType === 11) {
|
|
130
|
+
const children = members(node);
|
|
131
|
+
if (children.length !== 1) invalid("a document needs one element");
|
|
132
|
+
element = children[0];
|
|
133
|
+
} else if (node.nodeType !== 1) {
|
|
134
|
+
invalid("not an element or document node");
|
|
135
|
+
}
|
|
136
|
+
return [stringItem(write(element, false, indent ? "\n" : ""))];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Function definitions. */
|
|
140
|
+
export const xmlToJsonFunctions = [
|
|
141
|
+
define("xml-to-json", ["node()?"], "xs:string?", ([input]) =>
|
|
142
|
+
input.length ? xmlToJson(input[0]) : [],
|
|
143
|
+
),
|
|
144
|
+
define("xml-to-json", ["node()?", "map(*)"], "xs:string?", ([input, o]) =>
|
|
145
|
+
input.length ? xmlToJson(input[0], o) : [],
|
|
146
|
+
),
|
|
147
|
+
];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The function modules of F&O 3.1 that need no evaluator, collected for
|
|
3
|
+
* the function registry. fn:concat, fn:string-join and fn:string-length
|
|
4
|
+
* are exported separately (`coreStringFunctions`) because the core library
|
|
5
|
+
* may define them.
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/functions/library
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { aggregateFunctions } from "./aggregates.js";
|
|
11
|
+
import { dateTimeFunctions } from "./datetime.js";
|
|
12
|
+
import { formatDateTimeFunctions } from "./format/formatDateTime.js";
|
|
13
|
+
import { formatIntegerFunctions } from "./format/formatInteger.js";
|
|
14
|
+
import { formatNumberFunctions } from "./format/formatNumber.js";
|
|
15
|
+
import { mathFunctions } from "./math.js";
|
|
16
|
+
import { numericFunctions } from "./numeric.js";
|
|
17
|
+
import { parseIetfDateFunctions } from "./parseIetfDate.js";
|
|
18
|
+
import { qnameFunctions } from "./qnames.js";
|
|
19
|
+
import { analyzeStringFunctions } from "./regex/analyzeString.js";
|
|
20
|
+
import { regexFunctions } from "./regex/regexFunctions.js";
|
|
21
|
+
import { sequenceFunctions } from "./sequences.js";
|
|
22
|
+
import { serializeFunctions } from "./serializeFunction.js";
|
|
23
|
+
import { stringFunctions } from "./strings.js";
|
|
24
|
+
import { stringMatchFunctions } from "./stringMatch.js";
|
|
25
|
+
import { uriFunctions } from "./uri.js";
|
|
26
|
+
|
|
27
|
+
export { coreStringFunctions } from "./stringsCore.js";
|
|
28
|
+
|
|
29
|
+
/** @type {import("./support.js").FunctionDefinition[]} */
|
|
30
|
+
export const libraryFunctions = [
|
|
31
|
+
...stringFunctions,
|
|
32
|
+
...stringMatchFunctions,
|
|
33
|
+
...uriFunctions,
|
|
34
|
+
...regexFunctions,
|
|
35
|
+
...analyzeStringFunctions,
|
|
36
|
+
...numericFunctions,
|
|
37
|
+
...formatIntegerFunctions,
|
|
38
|
+
...formatNumberFunctions,
|
|
39
|
+
...mathFunctions,
|
|
40
|
+
...dateTimeFunctions,
|
|
41
|
+
...formatDateTimeFunctions,
|
|
42
|
+
...parseIetfDateFunctions,
|
|
43
|
+
...qnameFunctions,
|
|
44
|
+
...sequenceFunctions,
|
|
45
|
+
...aggregateFunctions,
|
|
46
|
+
...serializeFunctions,
|
|
47
|
+
];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fn:deep-equal for maps and arrays (F&O 3.1 section 14.2.1), the
|
|
3
|
+
* `deepEqualItem` hook that deepEqual.js calls for items that are neither
|
|
4
|
+
* atomic values nor nodes: maps are equal when they have the same keys
|
|
5
|
+
* (op:same-key) with deep-equal values, arrays when their members are
|
|
6
|
+
* deep-equal one by one. Other function items raise FOTY0015.
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/functions/mapArrayEqual
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { XPathError } from "../errors.js";
|
|
12
|
+
import { itemKind } from "../xdm/atomic.js";
|
|
13
|
+
import { deepEqualSequences } from "./deepEqual.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Whether two items that are not both atomic values or nodes are
|
|
17
|
+
* deep-equal.
|
|
18
|
+
* @param {*} a
|
|
19
|
+
* @param {*} b
|
|
20
|
+
* @param {import("./deepEqual.js").DeepEqualOptions} options - Options of
|
|
21
|
+
* deepEqualSequences, with this function as `deepEqualItem`
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
* @throws {XPathError} FOTY0015 for function items other than maps and
|
|
24
|
+
* arrays
|
|
25
|
+
*/
|
|
26
|
+
export function deepEqualItem(a, b, options) {
|
|
27
|
+
const kind = itemKind(a);
|
|
28
|
+
if (kind === "function" || itemKind(b) === "function") {
|
|
29
|
+
throw new XPathError("FOTY0015", "deep-equal cannot compare functions");
|
|
30
|
+
}
|
|
31
|
+
if (kind !== itemKind(b) || a.size !== b.size) return false;
|
|
32
|
+
if (kind === "array") {
|
|
33
|
+
return a.members.every((member, i) =>
|
|
34
|
+
deepEqualSequences(member, b.members[i], options),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return [...a.entries.values()].every(({ key, value }) => {
|
|
38
|
+
const other = b.get(key);
|
|
39
|
+
return other !== undefined && deepEqualSequences(value, other, options);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functions on maps (F&O 3.1 section 17.1), in the namespace
|
|
3
|
+
* http://www.w3.org/2005/xpath-functions/map.
|
|
4
|
+
*
|
|
5
|
+
* @module @tradik/xslt3/functions/maps
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { XPathError } from "../errors.js";
|
|
9
|
+
import { XdmArray } from "../items/array.js";
|
|
10
|
+
import { XdmMap } from "../items/map.js";
|
|
11
|
+
import { isArray, isMap } from "../xdm/atomic.js";
|
|
12
|
+
import { booleanItem, integerItem, stringItem } from "../xpath/eval/atomics.js";
|
|
13
|
+
import { NS } from "./signatures.js";
|
|
14
|
+
|
|
15
|
+
const DUPLICATES = new Set([
|
|
16
|
+
"use-first",
|
|
17
|
+
"use-last",
|
|
18
|
+
"use-any",
|
|
19
|
+
"combine",
|
|
20
|
+
"reject",
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* map:merge.
|
|
25
|
+
* @param {XdmMap[]} maps
|
|
26
|
+
* @param {XdmMap} [options]
|
|
27
|
+
* @returns {XdmMap}
|
|
28
|
+
*/
|
|
29
|
+
function merge(maps, options) {
|
|
30
|
+
const duplicates = options?.get(stringItem("duplicates"));
|
|
31
|
+
let policy = "use-first";
|
|
32
|
+
if (duplicates !== undefined) {
|
|
33
|
+
const value = duplicates[0]?.value;
|
|
34
|
+
if (duplicates.length !== 1 || typeof value !== "string") {
|
|
35
|
+
throw new XPathError("XPTY0004", "duplicates must be an xs:string");
|
|
36
|
+
}
|
|
37
|
+
if (!DUPLICATES.has(value)) {
|
|
38
|
+
throw new XPathError("FOJS0005", `Invalid duplicates option ${value}`);
|
|
39
|
+
}
|
|
40
|
+
policy = value;
|
|
41
|
+
}
|
|
42
|
+
const entries = new Map();
|
|
43
|
+
for (const map of maps) {
|
|
44
|
+
for (const [k, entry] of map.entries) {
|
|
45
|
+
const existing = entries.get(k);
|
|
46
|
+
if (!existing || policy === "use-last") entries.set(k, entry);
|
|
47
|
+
else if (policy === "reject") {
|
|
48
|
+
throw new XPathError("FOJS0003", "Duplicate key in map:merge");
|
|
49
|
+
} else if (policy === "combine") {
|
|
50
|
+
entries.set(k, {
|
|
51
|
+
key: existing.key,
|
|
52
|
+
value: [...existing.value, ...entry.value],
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return new XdmMap(entries);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* map:find: values of a key in maps nested in a sequence.
|
|
62
|
+
* @param {Array} sequence
|
|
63
|
+
* @param {*} key
|
|
64
|
+
* @param {Array[]} found - Values are appended
|
|
65
|
+
*/
|
|
66
|
+
function find(sequence, key, found) {
|
|
67
|
+
for (const item of sequence) {
|
|
68
|
+
if (isMap(item)) {
|
|
69
|
+
const value = item.get(key);
|
|
70
|
+
if (value !== undefined) found.push(value);
|
|
71
|
+
for (const entry of item.entries.values()) find(entry.value, key, found);
|
|
72
|
+
} else if (isArray(item)) {
|
|
73
|
+
for (const member of item.members) find(member, key, found);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {string} local
|
|
80
|
+
* @param {string[]} params
|
|
81
|
+
* @param {string} returns
|
|
82
|
+
* @param {Function} impl
|
|
83
|
+
* @returns {object} a definition in the map namespace
|
|
84
|
+
*/
|
|
85
|
+
const mapFunction = (local, params, returns, impl) => ({
|
|
86
|
+
namespace: NS.map,
|
|
87
|
+
local,
|
|
88
|
+
params,
|
|
89
|
+
returns,
|
|
90
|
+
impl,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/** Function definitions. */
|
|
94
|
+
export const mapFunctions = [
|
|
95
|
+
mapFunction("size", ["map(*)"], "xs:integer", ([[map]]) => [
|
|
96
|
+
integerItem(map.size),
|
|
97
|
+
]),
|
|
98
|
+
mapFunction("keys", ["map(*)"], "xs:anyAtomicType*", ([[map]]) => map.keys()),
|
|
99
|
+
mapFunction(
|
|
100
|
+
"contains",
|
|
101
|
+
["map(*)", "xs:anyAtomicType"],
|
|
102
|
+
"xs:boolean",
|
|
103
|
+
([[map], [key]]) => [booleanItem(map.has(key))],
|
|
104
|
+
),
|
|
105
|
+
mapFunction(
|
|
106
|
+
"get",
|
|
107
|
+
["map(*)", "xs:anyAtomicType"],
|
|
108
|
+
"item()*",
|
|
109
|
+
([[map], [key]]) => map.get(key) ?? [],
|
|
110
|
+
),
|
|
111
|
+
mapFunction(
|
|
112
|
+
"put",
|
|
113
|
+
["map(*)", "xs:anyAtomicType", "item()*"],
|
|
114
|
+
"map(*)",
|
|
115
|
+
([[map], [key], value]) => [map.put(key, value)],
|
|
116
|
+
),
|
|
117
|
+
mapFunction(
|
|
118
|
+
"remove",
|
|
119
|
+
["map(*)", "xs:anyAtomicType*"],
|
|
120
|
+
"map(*)",
|
|
121
|
+
([[map], keys]) => [map.remove(keys)],
|
|
122
|
+
),
|
|
123
|
+
mapFunction(
|
|
124
|
+
"entry",
|
|
125
|
+
["xs:anyAtomicType", "item()*"],
|
|
126
|
+
"map(*)",
|
|
127
|
+
([[key], value]) => [XdmMap.from([[key, value]])],
|
|
128
|
+
),
|
|
129
|
+
mapFunction("merge", ["map(*)*"], "map(*)", ([maps]) => [merge(maps)]),
|
|
130
|
+
mapFunction("merge", ["map(*)*", "map(*)"], "map(*)", ([maps, [options]]) => [
|
|
131
|
+
merge(maps, options),
|
|
132
|
+
]),
|
|
133
|
+
mapFunction(
|
|
134
|
+
"for-each",
|
|
135
|
+
["map(*)", "function(xs:anyAtomicType, item()*) as item()*"],
|
|
136
|
+
"item()*",
|
|
137
|
+
([[map], [f]]) =>
|
|
138
|
+
[...map.entries.values()].flatMap(({ key, value }) =>
|
|
139
|
+
f.invoke([[key], value]),
|
|
140
|
+
),
|
|
141
|
+
),
|
|
142
|
+
mapFunction(
|
|
143
|
+
"find",
|
|
144
|
+
["item()*", "xs:anyAtomicType"],
|
|
145
|
+
"array(*)",
|
|
146
|
+
([sequence, [key]]) => {
|
|
147
|
+
const found = [];
|
|
148
|
+
find(sequence, key, found);
|
|
149
|
+
return [new XdmArray(found)];
|
|
150
|
+
},
|
|
151
|
+
),
|
|
152
|
+
];
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigonometric and exponential functions (F&O 3.1 section 4.8), in the
|
|
3
|
+
* namespace http://www.w3.org/2005/xpath-functions/math. They follow IEEE
|
|
4
|
+
* 754 (JS Math) except where F&O differs: math:pow(1, y) and
|
|
5
|
+
* math:pow(-1, ±INF) are 1.
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/functions/math
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { define, doubleItem, MATH_NAMESPACE, toDouble } from "./support.js";
|
|
11
|
+
|
|
12
|
+
const D = "xs:double?";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* math:pow on JS numbers.
|
|
16
|
+
* @param {number} x
|
|
17
|
+
* @param {number} y
|
|
18
|
+
* @returns {number}
|
|
19
|
+
*/
|
|
20
|
+
export function pow(x, y) {
|
|
21
|
+
if (x === 1 || (x === -1 && !Number.isFinite(y) && !Number.isNaN(y))) {
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
return x ** y;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Declares a math function of one optional xs:double.
|
|
29
|
+
* @param {string} local
|
|
30
|
+
* @param {(x: number) => number} apply
|
|
31
|
+
* @returns {import("./support.js").FunctionDefinition}
|
|
32
|
+
*/
|
|
33
|
+
const unary = (local, apply) =>
|
|
34
|
+
define(
|
|
35
|
+
local,
|
|
36
|
+
[D],
|
|
37
|
+
D,
|
|
38
|
+
([arg]) => (arg.length === 0 ? [] : [doubleItem(apply(arg[0].value))]),
|
|
39
|
+
{ namespace: MATH_NAMESPACE },
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
/** @type {import("./support.js").FunctionDefinition[]} */
|
|
43
|
+
export const mathFunctions = [
|
|
44
|
+
define("pi", [], "xs:double", () => [doubleItem(Math.PI)], {
|
|
45
|
+
namespace: MATH_NAMESPACE,
|
|
46
|
+
}),
|
|
47
|
+
unary("exp", Math.exp),
|
|
48
|
+
unary("exp10", (x) => 10 ** x),
|
|
49
|
+
unary("log", Math.log),
|
|
50
|
+
unary("log10", Math.log10),
|
|
51
|
+
unary("sqrt", Math.sqrt),
|
|
52
|
+
unary("sin", Math.sin),
|
|
53
|
+
unary("cos", Math.cos),
|
|
54
|
+
unary("tan", Math.tan),
|
|
55
|
+
unary("asin", Math.asin),
|
|
56
|
+
unary("acos", Math.acos),
|
|
57
|
+
unary("atan", Math.atan),
|
|
58
|
+
define(
|
|
59
|
+
"pow",
|
|
60
|
+
[D, "xs:numeric"],
|
|
61
|
+
D,
|
|
62
|
+
([x, [y]]) =>
|
|
63
|
+
x.length === 0 ? [] : [doubleItem(pow(x[0].value, toDouble(y)))],
|
|
64
|
+
{ namespace: MATH_NAMESPACE },
|
|
65
|
+
),
|
|
66
|
+
define(
|
|
67
|
+
"atan2",
|
|
68
|
+
["xs:double", "xs:double"],
|
|
69
|
+
"xs:double",
|
|
70
|
+
([[y], [x]]) => [doubleItem(Math.atan2(y.value, x.value))],
|
|
71
|
+
{ namespace: MATH_NAMESPACE },
|
|
72
|
+
),
|
|
73
|
+
];
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functions locating nodes and their namespaces (F&O 3.1 sections 13 and
|
|
3
|
+
* 10.2): fn:path, fn:base-uri, fn:document-uri, fn:resolve-QName,
|
|
4
|
+
* fn:in-scope-prefixes and fn:namespace-uri-for-prefix.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/functions/nodePaths
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { XPathError } from "../errors.js";
|
|
10
|
+
import { AtomicValue } from "../xdm/atomic.js";
|
|
11
|
+
import { parseQName } from "../xdm/qname.js";
|
|
12
|
+
import { types } from "../xdm/types.js";
|
|
13
|
+
import { stringItem } from "../xpath/eval/atomics.js";
|
|
14
|
+
import {
|
|
15
|
+
childrenOf,
|
|
16
|
+
nodeLocalName,
|
|
17
|
+
nodeNamespace,
|
|
18
|
+
parentOf,
|
|
19
|
+
} from "../xpath/eval/domNodes.js";
|
|
20
|
+
import { inScopeNamespaces } from "../xpath/eval/namespaceNodes.js";
|
|
21
|
+
import { documentUriOf, nodeBaseUri } from "./baseUris.js";
|
|
22
|
+
import { focusNode } from "./focus.js";
|
|
23
|
+
|
|
24
|
+
export { nodeBaseUri };
|
|
25
|
+
|
|
26
|
+
/** @param {Node} node @returns {boolean} */
|
|
27
|
+
const isDocument = (node) => node.nodeType === 9 || node.nodeType === 11;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {Node} node
|
|
31
|
+
* @param {(n: Node) => boolean} same - Siblings counted for the position
|
|
32
|
+
* @returns {number} 1-based position among the matching siblings
|
|
33
|
+
*/
|
|
34
|
+
function positionAmong(node, same) {
|
|
35
|
+
const parent = parentOf(node);
|
|
36
|
+
if (!parent) return 1;
|
|
37
|
+
return childrenOf(parent).filter(same).indexOf(node) + 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* One step of fn:path.
|
|
42
|
+
* @param {Node} node
|
|
43
|
+
* @returns {string}
|
|
44
|
+
*/
|
|
45
|
+
function pathStep(node) {
|
|
46
|
+
const name = `Q{${nodeNamespace(node)}}${nodeLocalName(node)}`;
|
|
47
|
+
switch (node.nodeType) {
|
|
48
|
+
case 1:
|
|
49
|
+
return `${name}[${positionAmong(
|
|
50
|
+
node,
|
|
51
|
+
(n) =>
|
|
52
|
+
n.nodeType === 1 &&
|
|
53
|
+
`Q{${nodeNamespace(n)}}${nodeLocalName(n)}` === name,
|
|
54
|
+
)}]`;
|
|
55
|
+
case 2:
|
|
56
|
+
return node.namespaceURI ? `@${name}` : `@${nodeLocalName(node)}`;
|
|
57
|
+
case 7:
|
|
58
|
+
return `processing-instruction(${nodeLocalName(node)})[${positionAmong(
|
|
59
|
+
node,
|
|
60
|
+
(n) => n.nodeType === 7 && nodeLocalName(n) === nodeLocalName(node),
|
|
61
|
+
)}]`;
|
|
62
|
+
case 8:
|
|
63
|
+
return `comment()[${positionAmong(node, (n) => n.nodeType === 8)}]`;
|
|
64
|
+
case 13:
|
|
65
|
+
return node.localName
|
|
66
|
+
? `namespace::${node.localName}`
|
|
67
|
+
: 'namespace::*[Q{http://www.w3.org/2005/xpath-functions}local-name()=""]';
|
|
68
|
+
default:
|
|
69
|
+
return `text()[${positionAmong(node, (n) => n.nodeType === 3 || n.nodeType === 4)}]`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* fn:path of a node.
|
|
75
|
+
* @param {Node} node
|
|
76
|
+
* @returns {string}
|
|
77
|
+
*/
|
|
78
|
+
function pathOf(node) {
|
|
79
|
+
const steps = [];
|
|
80
|
+
let current = node;
|
|
81
|
+
for (; parentOf(current); current = parentOf(current)) {
|
|
82
|
+
steps.unshift(pathStep(current));
|
|
83
|
+
}
|
|
84
|
+
if (isDocument(current)) return `/${steps.join("/")}`;
|
|
85
|
+
const root = "Q{http://www.w3.org/2005/xpath-functions}root()";
|
|
86
|
+
return steps.length ? `${root}/${steps.join("/")}` : root;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** @param {string|undefined} uri @returns {Array} an optional xs:anyURI */
|
|
90
|
+
const anyUri = (uri) =>
|
|
91
|
+
uri === undefined ? [] : [new AtomicValue(types.anyURI, uri)];
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* fn:resolve-QName: a lexical QName resolved with the in-scope namespaces
|
|
95
|
+
* of an element.
|
|
96
|
+
* @param {Array<Array>} args
|
|
97
|
+
* @returns {Array} an optional xs:QName
|
|
98
|
+
* @throws {XPathError} FOCA0002 for an invalid lexical QName, FONS0004
|
|
99
|
+
* for an undeclared prefix
|
|
100
|
+
*/
|
|
101
|
+
function resolveQName([name, [element]]) {
|
|
102
|
+
if (!name.length) return [];
|
|
103
|
+
const namespaces = inScopeNamespaces(element);
|
|
104
|
+
const resolve = (prefix) => namespaces.get(prefix) ?? (prefix ? null : "");
|
|
105
|
+
const qname = parseQName(name[0].value, resolve);
|
|
106
|
+
if (qname === null) {
|
|
107
|
+
throw new XPathError("FOCA0002", `"${name[0].value}" is not a QName`);
|
|
108
|
+
}
|
|
109
|
+
return [new AtomicValue(types.QName, qname)];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Function definitions. */
|
|
113
|
+
export const nodePathFunctions = [
|
|
114
|
+
{
|
|
115
|
+
local: "path",
|
|
116
|
+
params: [],
|
|
117
|
+
returns: "xs:string?",
|
|
118
|
+
focus: true,
|
|
119
|
+
impl: (_, context) => [stringItem(pathOf(focusNode(context)))],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
local: "path",
|
|
123
|
+
params: ["node()?"],
|
|
124
|
+
returns: "xs:string?",
|
|
125
|
+
impl: ([arg]) => (arg.length ? [stringItem(pathOf(arg[0]))] : []),
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
local: "base-uri",
|
|
129
|
+
params: [],
|
|
130
|
+
returns: "xs:anyURI?",
|
|
131
|
+
focus: true,
|
|
132
|
+
impl: (_, context) => anyUri(nodeBaseUri(focusNode(context))),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
local: "base-uri",
|
|
136
|
+
params: ["node()?"],
|
|
137
|
+
returns: "xs:anyURI?",
|
|
138
|
+
impl: ([arg]) => (arg.length ? anyUri(nodeBaseUri(arg[0])) : []),
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
local: "document-uri",
|
|
142
|
+
params: [],
|
|
143
|
+
returns: "xs:anyURI?",
|
|
144
|
+
focus: true,
|
|
145
|
+
impl: (_, context) => {
|
|
146
|
+
const node = focusNode(context);
|
|
147
|
+
return isDocument(node) ? anyUri(documentUriOf(node)) : [];
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
local: "document-uri",
|
|
152
|
+
params: ["node()?"],
|
|
153
|
+
returns: "xs:anyURI?",
|
|
154
|
+
impl: ([arg]) =>
|
|
155
|
+
arg.length && isDocument(arg[0]) ? anyUri(documentUriOf(arg[0])) : [],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
local: "resolve-QName",
|
|
159
|
+
params: ["xs:string?", "element()"],
|
|
160
|
+
returns: "xs:QName?",
|
|
161
|
+
impl: resolveQName,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
local: "in-scope-prefixes",
|
|
165
|
+
params: ["element()"],
|
|
166
|
+
returns: "xs:string*",
|
|
167
|
+
impl: ([[element]]) =>
|
|
168
|
+
[...inScopeNamespaces(element)]
|
|
169
|
+
.filter(([, uri]) => uri !== "")
|
|
170
|
+
.map(([prefix]) => stringItem(prefix)),
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
local: "namespace-uri-for-prefix",
|
|
174
|
+
params: ["xs:string?", "element()"],
|
|
175
|
+
returns: "xs:anyURI?",
|
|
176
|
+
impl: ([prefix, [element]]) => {
|
|
177
|
+
const uri = inScopeNamespaces(element).get(prefix[0]?.value ?? "");
|
|
178
|
+
return uri ? anyUri(uri) : [];
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
];
|