• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FontoXML / fontoxpath / 13790201722

11 Mar 2025 02:12PM UTC coverage: 91.576% (+0.001%) from 91.575%
13790201722

push

github

DrRataplan
Fix contextItemAsFirstArgument to check type of contextItem

This makes errors for some queries like `1!path()` a lot more readable

Fixes #670

5000 of 5809 branches covered (86.07%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 3 files covered. (100.0%)

1 existing line in 1 file now uncovered.

10795 of 11439 relevant lines covered (94.37%)

96502.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.22
/src/expressions/functions/builtInFunctions_node.ts
1
import {
2
        AttributeNodePointer,
3
        ChildNodePointer,
4
        CommentNodePointer,
5
        ElementNodePointer,
6
        NodePointer,
7
        ParentNodePointer,
8
        ProcessingInstructionNodePointer,
9
        TextNodePointer,
10
} from '../../domClone/Pointer';
11
import { NODE_TYPES } from '../../domFacade/ConcreteNode';
12
import DomFacade from '../../domFacade/DomFacade';
13
import atomize from '../dataTypes/atomize';
15✔
14
import createAtomicValue from '../dataTypes/createAtomicValue';
15✔
15
import createPointerValue from '../dataTypes/createPointerValue';
15✔
16
import { sortNodeValues } from '../dataTypes/documentOrderUtils';
15✔
17
import ISequence from '../dataTypes/ISequence';
18
import isSubtypeOf from '../dataTypes/isSubtypeOf';
15✔
19
import sequenceFactory from '../dataTypes/sequenceFactory';
15✔
20
import Value, { SequenceMultiplicity, ValueType } from '../dataTypes/Value';
21
import QName from '../dataTypes/valueTypes/QName';
15✔
22
import arePointersEqual from '../operators/compares/arePointersEqual';
15✔
23
import { BUILT_IN_NAMESPACE_URIS } from '../staticallyKnownNamespaces';
24
import { IterationHint } from '../util/iterators';
15✔
25
import zipSingleton from '../util/zipSingleton';
15✔
26
import { errXPDY0002 } from '../XPathErrors';
15✔
27
import { contextItemAsFirstArgument } from './argumentHelper';
15✔
28
import { BuiltinDeclarationType } from './builtInFunctions';
29
import builtinStringFunctions from './builtInFunctions_string';
15✔
30
import FunctionDefinitionType from './FunctionDefinitionType';
31
import generateId from './generateId';
15✔
32
const fnString = builtinStringFunctions.functions.string;
15✔
33

34
const fnNodeName: FunctionDefinitionType = (
15✔
35
        _dynamicContext,
36
        executionParameters,
37
        _staticContext,
38
        sequence,
39
) => {
40
        return zipSingleton([sequence], ([pointerValue]) => {
238,254✔
41
                if (pointerValue === null) {
238,254✔
42
                        return sequenceFactory.empty();
3✔
43
                }
44
                const domFacade = executionParameters.domFacade;
238,251✔
45
                const pointer: NodePointer = pointerValue.value;
238,251✔
46
                switch (domFacade.getNodeType(pointer)) {
238,251✔
47
                        case NODE_TYPES.ELEMENT_NODE:
48
                        case NODE_TYPES.ATTRIBUTE_NODE:
49
                                // element or attribute
50
                                const attrOrElPointer = pointer as AttributeNodePointer | ElementNodePointer;
238,224✔
51
                                return sequenceFactory.singleton(
238,224✔
52
                                        createAtomicValue(
53
                                                new QName(
54
                                                        domFacade.getPrefix(attrOrElPointer),
55
                                                        domFacade.getNamespaceURI(attrOrElPointer),
56
                                                        domFacade.getLocalName(attrOrElPointer),
57
                                                ),
58
                                                ValueType.XSQNAME,
59
                                        ),
60
                                );
61
                        case NODE_TYPES.PROCESSING_INSTRUCTION_NODE:
62
                                // A processing instruction's target is its nodename (https://www.w3.org/TR/xpath-functions-31/#func-node-name)
63
                                const processingInstruction = pointer as ProcessingInstructionNodePointer;
15✔
64
                                return sequenceFactory.singleton(
15✔
65
                                        createAtomicValue(
66
                                                new QName('', '', domFacade.getTarget(processingInstruction)),
67
                                                ValueType.XSQNAME,
68
                                        ),
69
                                );
70
                        default:
71
                                // All other nodes have no name
72
                                return sequenceFactory.empty();
12✔
73
                }
74
        });
75
};
76

77
const fnName: FunctionDefinitionType = (
15✔
78
        dynamicContext,
79
        executionParameters,
80
        staticContext,
81
        sequence,
82
) => {
83
        return sequence.switchCases({
375✔
84
                default: () =>
85
                        fnString(
372✔
86
                                dynamicContext,
87
                                executionParameters,
88
                                staticContext,
89
                                fnNodeName(dynamicContext, executionParameters, staticContext, sequence),
90
                        ),
91
                empty: () => sequenceFactory.singleton(createAtomicValue('', ValueType.XSSTRING)),
3✔
92
        });
93
};
94

95
const fnData: FunctionDefinitionType = (
15✔
96
        _dynamicContext,
97
        executionParameters,
98
        _staticContext,
99
        sequence,
100
) => {
101
        return atomize(sequence, executionParameters);
24✔
102
};
103

104
const fnGenerateId: FunctionDefinitionType = (
15✔
105
        dynamicContext,
106
        executionParameters,
107
        _staticContext,
108
        nodeValue,
109
) => {
110
        if (nodeValue.isEmpty()) {
15✔
111
                return sequenceFactory.singleton(createAtomicValue('', ValueType.XSSTRING));
3✔
112
        }
113
        if (!isSubtypeOf(nodeValue.first().type, ValueType.NODE)) {
12!
UNCOV
114
                throw new Error('XPTY0004: The context item must be a node.');
×
115
        }
116
        const node = nodeValue.first().value as NodePointer;
12✔
117

118
        return sequenceFactory.singleton(createAtomicValue(generateId(node), ValueType.XSSTRING));
12✔
119
};
120

121
const fnHasChildren: FunctionDefinitionType = (
15✔
122
        _dynamicContext,
123
        executionParameters,
124
        _staticContext,
125
        nodeSequence: ISequence,
126
) => {
127
        return zipSingleton([nodeSequence], ([pointerValue]: (Value | null)[]) => {
12✔
128
                const pointer: ParentNodePointer = pointerValue ? pointerValue.value : null;
12✔
129

130
                if (pointer !== null && executionParameters.domFacade.getFirstChildPointer(pointer, null)) {
12✔
131
                        return sequenceFactory.singletonTrueSequence();
6✔
132
                }
133
                return sequenceFactory.singletonFalseSequence();
6✔
134
        });
135
};
136

137
function areSameNode(
138
        nodeA: ChildNodePointer,
139
        nodeB: ChildNodePointer,
140
        domFacade: DomFacade,
141
): boolean {
142
        if (domFacade.getNodeType(nodeA) !== domFacade.getNodeType(nodeB)) {
117✔
143
                return false;
30✔
144
        }
145
        if (domFacade.getNodeType(nodeB) === NODE_TYPES.ELEMENT_NODE) {
87✔
146
                return (
63✔
147
                        domFacade.getLocalName(nodeB as ElementNodePointer) ===
120✔
148
                                domFacade.getLocalName(nodeA as ElementNodePointer) &&
149
                        domFacade.getNamespaceURI(nodeB as ElementNodePointer) ===
150
                                domFacade.getNamespaceURI(nodeA as ElementNodePointer)
151
                );
152
        }
153
        if (domFacade.getNodeType(nodeB) === NODE_TYPES.PROCESSING_INSTRUCTION_NODE) {
24✔
154
                return (
18✔
155
                        domFacade.getTarget(nodeB as ProcessingInstructionNodePointer) ===
156
                        domFacade.getTarget(nodeA as ProcessingInstructionNodePointer)
157
                );
158
        }
159

160
        return true;
6✔
161
}
162

163
/**
164
 * Test if a string should match the xml:lang attribute string of a node.
165
 */
166
function langMatchString(truth: string, test: string): boolean {
167
        truth = truth.toLowerCase();
30✔
168
        test = test.toLowerCase();
30✔
169
        if (truth === test) {
30✔
170
                return true;
18✔
171
        } else {
172
                return truth.length < 5 || !truth.startsWith(test)
12✔
173
                        ? false
174
                        : /* Strip the least specific part and test again */
175
                          langMatchString(truth.replace(/-[a-z0-9]+$/, ''), test);
176
        }
177
}
178

179
/**
180
 * Starting at a given node, test the xml:lang attribute to see if it
181
   matches a test. Move up the tree until the test passes or fails.
182
 */
183
function langMatchNode(node: NodePointer, domFacade: DomFacade, test: string): ISequence {
184
        let toTest = node;
27✔
185
        while (toTest) {
27✔
186
                if (domFacade.getNodeType(toTest) !== NODE_TYPES.ELEMENT_NODE) {
30!
187
                        toTest = domFacade.getParentNodePointer(toTest as AttributeNodePointer);
×
188
                } else if (domFacade.getNodeType(toTest) === NODE_TYPES.ELEMENT_NODE) {
30!
189
                        const attrValue = domFacade.getAttribute(toTest as ElementNodePointer, 'xml:lang');
30✔
190
                        if (attrValue) {
30✔
191
                                return langMatchString(attrValue, test)
27✔
192
                                        ? sequenceFactory.singletonTrueSequence()
193
                                        : sequenceFactory.singletonFalseSequence();
194
                        } else {
195
                                toTest = domFacade.getParentNodePointer(toTest as ElementNodePointer);
3✔
196
                        }
197
                }
198
        }
199
        return sequenceFactory.singletonFalseSequence();
×
200
}
201

202
const fnLang: FunctionDefinitionType = (
15✔
203
        dynamicContext,
204
        executionParameters,
205
        _staticContext,
206
        langTestValue,
207
        nodeValue,
208
) => {
209
        const domFacade = executionParameters.domFacade;
27✔
210
        let langTest;
211
        if (langTestValue.isEmpty()) {
27!
212
                langTest = '';
×
213
        } else if (!isSubtypeOf(langTestValue.first().type, ValueType.XSSTRING)) {
27!
214
                throw new Error('XPTY0004: The first argument of lang must be a string.');
×
215
        } else {
216
                langTest = langTestValue.first().value;
27✔
217
        }
218
        let node;
219
        if (!nodeValue) {
27✔
220
                if (!dynamicContext || !dynamicContext.contextItem) {
12!
221
                        throw errXPDY0002(
×
222
                                `The function lang depends on dynamic context if a node is not passed as the second argument.`,
223
                        );
224
                }
225
                if (!isSubtypeOf(dynamicContext.contextItem.type, ValueType.NODE)) {
12!
226
                        throw new Error('XPTY0004: The context item must be a node.');
×
227
                }
228
                node = dynamicContext.contextItem.value;
12✔
229
        } else {
230
                node = nodeValue.first().value;
15✔
231
        }
232
        return langMatchNode(node, domFacade, langTest);
27✔
233
};
234

235
const fnPath: FunctionDefinitionType = (
15✔
236
        _dynamicContext,
237
        executionParameters,
238
        _staticContext,
239
        nodeSequence: ISequence,
240
) => {
241
        return zipSingleton([nodeSequence], ([pointerValue]: (Value | null)[]) => {
45✔
242
                if (pointerValue === null) {
45✔
243
                        return sequenceFactory.empty();
3✔
244
                }
245

246
                const pointer: NodePointer = pointerValue.value;
42✔
247
                const domFacade: DomFacade = executionParameters.domFacade;
42✔
248

249
                let result = '';
42✔
250

251
                function getChildIndex(child: ChildNodePointer): number {
252
                        let i = 0;
51✔
253
                        let otherChild = child;
51✔
254
                        while (otherChild !== null) {
51✔
255
                                if (areSameNode(child, otherChild, domFacade)) {
117✔
256
                                        i++;
72✔
257
                                }
258
                                otherChild = domFacade.getPreviousSiblingPointer(otherChild, null);
117✔
259
                        }
260
                        return i;
51✔
261
                }
262
                let ancestor;
263
                for (
42✔
264
                        ancestor = pointer;
265
                        executionParameters.domFacade.getParentNodePointer(
266
                                ancestor as ChildNodePointer,
267
                                null,
268
                        ) !== null;
269
                        ancestor = executionParameters.domFacade.getParentNodePointer(
270
                                ancestor as ChildNodePointer,
271
                                null,
272
                        )
273
                ) {
274
                        switch (domFacade.getNodeType(ancestor)) {
60!
275
                                case NODE_TYPES.ELEMENT_NODE: {
276
                                        const ancestorElement = ancestor as ElementNodePointer;
42✔
277
                                        result = `/Q{${
42✔
278
                                                domFacade.getNamespaceURI(ancestorElement) || ''
60✔
279
                                        }}${domFacade.getLocalName(ancestorElement)}[${getChildIndex(
280
                                                ancestorElement,
281
                                        )}]${result}`;
282
                                        break;
42✔
283
                                }
284
                                case NODE_TYPES.ATTRIBUTE_NODE: {
285
                                        const ancestorAttributeNode = ancestor as AttributeNodePointer;
9✔
286
                                        const attributeNameSpace = domFacade.getNamespaceURI(ancestorAttributeNode)
9✔
287
                                                ? `Q{${domFacade.getNamespaceURI(ancestorAttributeNode)}}`
288
                                                : '';
289
                                        result = `/@${attributeNameSpace}${domFacade.getLocalName(
9✔
290
                                                ancestorAttributeNode,
291
                                        )}${result}`;
292
                                        break;
9✔
293
                                }
294
                                case NODE_TYPES.TEXT_NODE: {
295
                                        const ancestorTextNode = ancestor as TextNodePointer;
3✔
296
                                        result = `/text()[${getChildIndex(ancestorTextNode)}]${result}`;
3✔
297
                                        break;
3✔
298
                                }
299
                                case NODE_TYPES.PROCESSING_INSTRUCTION_NODE: {
300
                                        const ancestorPI = ancestor as ProcessingInstructionNodePointer;
6✔
301
                                        result = `/processing-instruction(${domFacade.getTarget(
6✔
302
                                                ancestorPI,
303
                                        )})[${getChildIndex(ancestorPI)}]${result}`;
304
                                        break;
6✔
305
                                }
306
                                case NODE_TYPES.COMMENT_NODE: {
307
                                        const ancestorComment = ancestor as CommentNodePointer;
×
308
                                        result = `/comment()[${getChildIndex(ancestorComment)}]${result}`;
×
309
                                        break;
×
310
                                }
311
                        }
312
                }
313
                if (domFacade.getNodeType(ancestor) === NODE_TYPES.DOCUMENT_NODE) {
42✔
314
                        return sequenceFactory.create(createAtomicValue(result || '/', ValueType.XSSTRING));
27✔
315
                }
316
                result = 'Q{http://www.w3.org/2005/xpath-functions}root()' + result;
15✔
317
                return sequenceFactory.create(createAtomicValue(result, ValueType.XSSTRING));
15✔
318
        });
319
};
320

321
const fnNamespaceURI: FunctionDefinitionType = (
15✔
322
        _dynamicContext,
323
        executionParameters,
324
        _staticContext,
325
        sequence,
326
) => {
327
        return sequence.map((node) =>
78✔
328
                createAtomicValue(
78✔
329
                        executionParameters.domFacade.getNamespaceURI(node.value) || '',
90✔
330
                        ValueType.XSANYURI,
331
                ),
332
        );
333
};
334

335
const fnLocalName: FunctionDefinitionType = (
15✔
336
        _dynamicContext,
337
        executionParameters,
338
        _staticContext,
339
        sequence,
340
) => {
341
        const domFacade = executionParameters.domFacade;
426✔
342
        return sequence.switchCases({
426✔
343
                default: () => {
344
                        return sequence.map((node) => {
423✔
345
                                if (domFacade.getNodeType(node.value) === 7) {
423✔
346
                                        const pi: ProcessingInstructionNodePointer = node.value;
3✔
347
                                        return createAtomicValue(domFacade.getTarget(pi), ValueType.XSSTRING);
3✔
348
                                }
349

350
                                return createAtomicValue(
420✔
351
                                        domFacade.getLocalName(node.value) || '',
420!
352
                                        ValueType.XSSTRING,
353
                                );
354
                        });
355
                },
356
                empty: () => sequenceFactory.singleton(createAtomicValue('', ValueType.XSSTRING)),
3✔
357
        });
358
};
359

360
function contains(domFacade: DomFacade, ancestor: NodePointer, descendant: NodePointer): boolean {
361
        if (domFacade.getNodeType(ancestor) === NODE_TYPES.ATTRIBUTE_NODE) {
99✔
362
                return arePointersEqual(ancestor, descendant);
6✔
363
        }
364
        while (descendant) {
93✔
365
                if (arePointersEqual(ancestor, descendant)) {
237✔
366
                        return true;
39✔
367
                }
368
                if (domFacade.getNodeType(descendant) === NODE_TYPES.DOCUMENT_NODE) {
198✔
369
                        return false;
42✔
370
                }
371
                descendant = domFacade.getParentNodePointer(descendant as ChildNodePointer, null);
156✔
372
        }
373
        return false;
12✔
374
}
375

376
const fnOutermost: FunctionDefinitionType = (
15✔
377
        _dynamicContext,
378
        executionParameters,
379
        _staticContext,
380
        nodeSequence,
381
) => {
382
        return nodeSequence.mapAll((allNodeValues) => {
72✔
383
                if (!allNodeValues.length) {
72✔
384
                        return sequenceFactory.empty();
3✔
385
                }
386

387
                const resultNodes = sortNodeValues(executionParameters.domFacade, allNodeValues).reduce(
69✔
388
                        (previousNodes, node, i) => {
389
                                if (i === 0) {
114✔
390
                                        previousNodes.push(node);
69✔
391
                                        return previousNodes;
69✔
392
                                }
393
                                // Because the nodes are sorted, the previous node is either a 'previous node', or an ancestor of this node
394
                                if (
45✔
395
                                        contains(
396
                                                executionParameters.domFacade,
397
                                                previousNodes[previousNodes.length - 1].value,
398
                                                node.value,
399
                                        )
400
                                ) {
401
                                        // The previous node is an ancestor
402
                                        return previousNodes;
12✔
403
                                }
404

405
                                previousNodes.push(node);
33✔
406
                                return previousNodes;
33✔
407
                        },
408
                        [],
409
                );
410

411
                return sequenceFactory.create(resultNodes);
69✔
412
        }, IterationHint.SKIP_DESCENDANTS);
413
};
414

415
const fnInnermost: FunctionDefinitionType = (
15✔
416
        _dynamicContext,
417
        executionParameters,
418
        _staticContext,
419
        nodeSequence,
420
) => {
421
        return nodeSequence.mapAll((allNodeValues) => {
24✔
422
                if (!allNodeValues.length) {
24✔
423
                        return sequenceFactory.empty();
3✔
424
                }
425

426
                const resultNodes = sortNodeValues(
21✔
427
                        executionParameters.domFacade,
428
                        allNodeValues,
429
                ).reduceRight((followingNodes, node, i, allNodes) => {
430
                        if (i === allNodes.length - 1) {
75✔
431
                                followingNodes.push(node);
21✔
432
                                return followingNodes;
21✔
433
                        }
434
                        // Because the nodes are sorted, the following node is either a 'following node', or a descendant of this node
435
                        if (contains(executionParameters.domFacade, node.value, followingNodes[0].value)) {
54✔
436
                                // The previous node is an ancestor
437
                                return followingNodes;
27✔
438
                        }
439

440
                        followingNodes.unshift(node);
27✔
441
                        return followingNodes;
27✔
442
                }, []);
443

444
                return sequenceFactory.create(resultNodes);
21✔
445
        });
446
};
447

448
const fnRoot: FunctionDefinitionType = (
15✔
449
        _dynamicContext,
450
        executionParameters,
451
        _staticContext,
452
        nodeSequence,
453
) => {
454
        return nodeSequence.map((node) => {
15✔
455
                if (!isSubtypeOf(node.type, ValueType.NODE)) {
15!
456
                        throw new Error('XPTY0004 Argument passed to fn:root() should be of the type node()');
×
457
                }
458

459
                let ancestor;
460
                let parent = node.value;
15✔
461
                while (parent) {
15✔
462
                        ancestor = parent;
33✔
463
                        parent = executionParameters.domFacade.getParentNodePointer(ancestor, null);
33✔
464
                }
465
                return createPointerValue(ancestor, executionParameters.domFacade);
15✔
466
        });
467
};
468

469
const declarations: BuiltinDeclarationType[] = [
15✔
470
        {
471
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
472
                callFunction: fnName,
473
                localName: 'name',
474
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
475
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
476
        },
477

478
        {
479
                argumentTypes: [],
480
                callFunction: contextItemAsFirstArgument('name', ValueType.NODE, fnName),
481
                localName: 'name',
482
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
483
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
484
        },
485

486
        {
487
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.EXACTLY_ONE }],
488
                callFunction: fnNamespaceURI,
489
                localName: 'namespace-uri',
490
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
491
                returnType: { type: ValueType.XSANYURI, mult: SequenceMultiplicity.EXACTLY_ONE },
492
        },
493

494
        {
495
                argumentTypes: [],
496
                callFunction: contextItemAsFirstArgument('namespace-uri', ValueType.NODE, fnNamespaceURI),
497
                localName: 'namespace-uri',
498
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
499
                returnType: { type: ValueType.XSANYURI, mult: SequenceMultiplicity.EXACTLY_ONE },
500
        },
501

502
        {
503
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_MORE }],
504
                callFunction: fnInnermost,
505
                localName: 'innermost',
506
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
507
                returnType: { type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_MORE },
508
        },
509

510
        {
511
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_MORE }],
512
                callFunction: fnOutermost,
513
                localName: 'outermost',
514
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
515
                returnType: { type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_MORE },
516
        },
517

518
        {
519
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
520
                callFunction: fnHasChildren,
521
                localName: 'has-children',
522
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
523
                returnType: {
524
                        type: ValueType.XSBOOLEAN,
525
                        mult: SequenceMultiplicity.EXACTLY_ONE,
526
                },
527
        },
528

529
        {
530
                argumentTypes: [],
531
                callFunction: contextItemAsFirstArgument('has-children', ValueType.NODE, fnHasChildren),
532
                localName: 'has-children',
533
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
534
                returnType: { type: ValueType.XSBOOLEAN, mult: SequenceMultiplicity.EXACTLY_ONE },
535
        },
536

537
        {
538
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
539
                callFunction: fnPath,
540
                localName: 'path',
541
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
542
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.ZERO_OR_ONE },
543
        },
544

545
        {
546
                argumentTypes: [],
547
                callFunction: contextItemAsFirstArgument('path', ValueType.NODE, fnPath),
548
                localName: 'path',
549
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
550
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.ZERO_OR_ONE },
551
        },
552

553
        {
554
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
555
                callFunction: fnNodeName,
556
                localName: 'node-name',
557
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
558
                returnType: { type: ValueType.XSQNAME, mult: SequenceMultiplicity.ZERO_OR_ONE },
559
        },
560

561
        {
562
                argumentTypes: [],
563
                callFunction: contextItemAsFirstArgument('node-name', ValueType.NODE, fnNodeName),
564
                localName: 'node-name',
565
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
566
                returnType: { type: ValueType.XSQNAME, mult: SequenceMultiplicity.ZERO_OR_ONE },
567
        },
568

569
        {
570
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
571
                callFunction: fnLocalName,
572
                localName: 'local-name',
573
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
574
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
575
        },
576

577
        {
578
                argumentTypes: [],
579
                callFunction: contextItemAsFirstArgument('local-name', ValueType.NODE, fnLocalName),
580
                localName: 'local-name',
581
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
582
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
583
        },
584

585
        {
586
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
587
                callFunction: fnRoot,
588
                localName: 'root',
589
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
590
                returnType: { type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE },
591
        },
592

593
        {
594
                argumentTypes: [],
595
                callFunction: contextItemAsFirstArgument('root', ValueType.NODE, fnRoot),
596
                localName: 'root',
597
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
598
                returnType: { type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE },
599
        },
600

601
        {
602
                argumentTypes: [],
603
                callFunction: contextItemAsFirstArgument('data', ValueType.ITEM, fnData),
604
                localName: 'data',
605
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
606
                returnType: { type: ValueType.XSANYATOMICTYPE, mult: SequenceMultiplicity.ZERO_OR_MORE },
607
        },
608
        {
609
                argumentTypes: [{ type: ValueType.ITEM, mult: SequenceMultiplicity.ZERO_OR_MORE }],
610
                callFunction: fnData,
611
                localName: 'data',
612
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
613
                returnType: { type: ValueType.XSANYATOMICTYPE, mult: SequenceMultiplicity.ZERO_OR_MORE },
614
        },
615

616
        {
617
                argumentTypes: [{ type: ValueType.XSSTRING, mult: SequenceMultiplicity.ZERO_OR_ONE }],
618
                callFunction: fnLang,
619
                localName: 'lang',
620
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
621
                returnType: { type: ValueType.XSBOOLEAN, mult: SequenceMultiplicity.EXACTLY_ONE },
622
        },
623
        {
624
                argumentTypes: [
625
                        { type: ValueType.XSSTRING, mult: SequenceMultiplicity.ZERO_OR_ONE },
626
                        { type: ValueType.NODE, mult: SequenceMultiplicity.EXACTLY_ONE },
627
                ],
628
                callFunction: fnLang,
629
                localName: 'lang',
630
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
631
                returnType: { type: ValueType.XSBOOLEAN, mult: SequenceMultiplicity.EXACTLY_ONE },
632
        },
633
        {
634
                argumentTypes: [],
635
                callFunction: contextItemAsFirstArgument('generate-id', ValueType.NODE, fnGenerateId),
636
                localName: 'generate-id',
637
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
638
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
639
        },
640
        {
641
                argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
642
                callFunction: fnGenerateId,
643
                localName: 'generate-id',
644
                namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
645
                returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
646
        },
647
];
648

649
export default {
15✔
650
        declarations,
651
        functions: {
652
                name: fnName,
653
                nodeName: fnNodeName,
654
        },
655
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc