xslt-processor 5.0.8 → 5.0.10
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/dist/index.d.mts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +134 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +134 -22
- package/dist/index.mjs.map +1 -1
- package/dist/umd/xslt-processor.global.js +6 -6
- package/dist/umd/xslt-processor.global.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -285,7 +285,7 @@ declare class ExprContext {
|
|
|
285
285
|
ignoreAttributesWithoutValue: any;
|
|
286
286
|
returnOnFirstMatch: any;
|
|
287
287
|
ignoreNonElementNodesForNTA: any;
|
|
288
|
-
parent: ExprContext;
|
|
288
|
+
parent: ExprContext | null;
|
|
289
289
|
root: XNode;
|
|
290
290
|
decimalFormatSettings: XsltDecimalFormatSettings;
|
|
291
291
|
inApplyTemplates: boolean;
|
|
@@ -348,8 +348,8 @@ declare class ExprContext {
|
|
|
348
348
|
* @returns A new ExprContext instance with the specified node list and position, and the current context as its parent.
|
|
349
349
|
*/
|
|
350
350
|
clone(opt_nodeList?: XNode[], opt_position?: number): ExprContext;
|
|
351
|
-
setVariable(name
|
|
352
|
-
getVariable(name: string): NodeValue;
|
|
351
|
+
setVariable(name: string, value?: NodeValue | string): void;
|
|
352
|
+
getVariable(name: string): NodeValue | null;
|
|
353
353
|
/**
|
|
354
354
|
* Gets a regex group from xsl:analyze-string context.
|
|
355
355
|
* Searches up the parent chain for regexGroups.
|
|
@@ -612,6 +612,13 @@ declare class NodeConverter {
|
|
|
612
612
|
* followed by the evaluated function arguments.
|
|
613
613
|
*/
|
|
614
614
|
private createCustomFunctions;
|
|
615
|
+
/**
|
|
616
|
+
* Minimal XSLT/XPath format-number() picture formatter.
|
|
617
|
+
* Supports grouping, decimal precision, percent/per-mille scaling and positive/negative subpictures.
|
|
618
|
+
*/
|
|
619
|
+
private formatXsltNumberPicture;
|
|
620
|
+
private applyGrouping;
|
|
621
|
+
private leftPad;
|
|
615
622
|
/**
|
|
616
623
|
* Convert an XPathNode interface tree to actual XNode objects.
|
|
617
624
|
* This is needed to convert json-to-xml() output to XSLT-compatible nodes.
|
package/dist/index.d.ts
CHANGED
|
@@ -285,7 +285,7 @@ declare class ExprContext {
|
|
|
285
285
|
ignoreAttributesWithoutValue: any;
|
|
286
286
|
returnOnFirstMatch: any;
|
|
287
287
|
ignoreNonElementNodesForNTA: any;
|
|
288
|
-
parent: ExprContext;
|
|
288
|
+
parent: ExprContext | null;
|
|
289
289
|
root: XNode;
|
|
290
290
|
decimalFormatSettings: XsltDecimalFormatSettings;
|
|
291
291
|
inApplyTemplates: boolean;
|
|
@@ -348,8 +348,8 @@ declare class ExprContext {
|
|
|
348
348
|
* @returns A new ExprContext instance with the specified node list and position, and the current context as its parent.
|
|
349
349
|
*/
|
|
350
350
|
clone(opt_nodeList?: XNode[], opt_position?: number): ExprContext;
|
|
351
|
-
setVariable(name
|
|
352
|
-
getVariable(name: string): NodeValue;
|
|
351
|
+
setVariable(name: string, value?: NodeValue | string): void;
|
|
352
|
+
getVariable(name: string): NodeValue | null;
|
|
353
353
|
/**
|
|
354
354
|
* Gets a regex group from xsl:analyze-string context.
|
|
355
355
|
* Searches up the parent chain for regexGroups.
|
|
@@ -612,6 +612,13 @@ declare class NodeConverter {
|
|
|
612
612
|
* followed by the evaluated function arguments.
|
|
613
613
|
*/
|
|
614
614
|
private createCustomFunctions;
|
|
615
|
+
/**
|
|
616
|
+
* Minimal XSLT/XPath format-number() picture formatter.
|
|
617
|
+
* Supports grouping, decimal precision, percent/per-mille scaling and positive/negative subpictures.
|
|
618
|
+
*/
|
|
619
|
+
private formatXsltNumberPicture;
|
|
620
|
+
private applyGrouping;
|
|
621
|
+
private leftPad;
|
|
615
622
|
/**
|
|
616
623
|
* Convert an XPathNode interface tree to actual XNode objects.
|
|
617
624
|
* This is needed to convert json-to-xml() output to XSLT-compatible nodes.
|
package/dist/index.js
CHANGED
|
@@ -9084,13 +9084,9 @@ var XPathBaseParser = class {
|
|
|
9084
9084
|
return expr;
|
|
9085
9085
|
}
|
|
9086
9086
|
parsePrimaryExpr() {
|
|
9087
|
-
var _a, _b
|
|
9087
|
+
var _a, _b;
|
|
9088
9088
|
if (this.match("DOLLAR")) {
|
|
9089
|
-
const
|
|
9090
|
-
if (!next || !this.isNcNameToken(next.type)) {
|
|
9091
|
-
throw grammarViolation(`Expected variable name after $. Got: ${(_a = next == null ? void 0 : next.lexeme) != null ? _a : "EOF"}`);
|
|
9092
|
-
}
|
|
9093
|
-
const name = this.advance().lexeme;
|
|
9089
|
+
const name = this.parseVariableReferenceName();
|
|
9094
9090
|
return new XPathVariableReference(name);
|
|
9095
9091
|
}
|
|
9096
9092
|
if (this.match("OPEN_PAREN")) {
|
|
@@ -9114,7 +9110,7 @@ var XPathBaseParser = class {
|
|
|
9114
9110
|
return this.parseFunctionCall();
|
|
9115
9111
|
}
|
|
9116
9112
|
throw grammarViolation(
|
|
9117
|
-
`Unexpected token in primary expression: ${(
|
|
9113
|
+
`Unexpected token in primary expression: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`
|
|
9118
9114
|
);
|
|
9119
9115
|
}
|
|
9120
9116
|
parseFunctionCall() {
|
|
@@ -9186,6 +9182,27 @@ var XPathBaseParser = class {
|
|
|
9186
9182
|
isFunctionNameToken(type) {
|
|
9187
9183
|
return type === "IDENTIFIER" || type === "FUNCTION" || type === "OPERATOR" || type === "LOCATION" || type === "EQNAME";
|
|
9188
9184
|
}
|
|
9185
|
+
parseVariableReferenceName() {
|
|
9186
|
+
var _a, _b;
|
|
9187
|
+
if (this.check("EQNAME")) {
|
|
9188
|
+
return this.advance().lexeme;
|
|
9189
|
+
}
|
|
9190
|
+
const next = this.peek();
|
|
9191
|
+
if (!next || !this.isNcNameToken(next.type)) {
|
|
9192
|
+
throw grammarViolation(`Expected variable name after $. Got: ${(_a = next == null ? void 0 : next.lexeme) != null ? _a : "EOF"}`);
|
|
9193
|
+
}
|
|
9194
|
+
let name = this.advance().lexeme;
|
|
9195
|
+
if (this.match("COLON")) {
|
|
9196
|
+
const local = this.peek();
|
|
9197
|
+
if (!local || !this.isNcNameToken(local.type)) {
|
|
9198
|
+
throw grammarViolation(
|
|
9199
|
+
`Expected local name after namespace prefix in variable reference. Got: ${(_b = local == null ? void 0 : local.lexeme) != null ? _b : "EOF"}`
|
|
9200
|
+
);
|
|
9201
|
+
}
|
|
9202
|
+
name = `${name}:${this.advance().lexeme}`;
|
|
9203
|
+
}
|
|
9204
|
+
return name;
|
|
9205
|
+
}
|
|
9189
9206
|
isNcNameToken(type) {
|
|
9190
9207
|
return type === "IDENTIFIER" || type === "FUNCTION" || type === "OPERATOR" || type === "LOCATION" || type === "NODE_TYPE";
|
|
9191
9208
|
}
|
|
@@ -9298,16 +9315,12 @@ var XPath20Parser = class extends XPathBaseParser {
|
|
|
9298
9315
|
return left;
|
|
9299
9316
|
}
|
|
9300
9317
|
parsePrimaryExpr() {
|
|
9301
|
-
var _a, _b;
|
|
9302
9318
|
if (this.check("RESERVED_WORD") && this.peek().lexeme === "if") {
|
|
9303
9319
|
return this.parseIfExpr();
|
|
9304
9320
|
}
|
|
9305
9321
|
if (this.check("DOLLAR")) {
|
|
9306
9322
|
this.advance();
|
|
9307
|
-
|
|
9308
|
-
throw new Error(`Expected variable name after $. Got: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`);
|
|
9309
|
-
}
|
|
9310
|
-
const name = this.advance().lexeme;
|
|
9323
|
+
const name = this.parseVariableReferenceName();
|
|
9311
9324
|
return new XPathVariableReference(name);
|
|
9312
9325
|
}
|
|
9313
9326
|
return super.parsePrimaryExpr();
|
|
@@ -9684,7 +9697,7 @@ var XPath30Parser = class extends XPath20Parser {
|
|
|
9684
9697
|
let args = [];
|
|
9685
9698
|
if (this.check("DOLLAR")) {
|
|
9686
9699
|
this.advance();
|
|
9687
|
-
const varName = this.
|
|
9700
|
+
const varName = this.parseVariableReferenceName();
|
|
9688
9701
|
funcExpr = new XPathVariableReference(varName);
|
|
9689
9702
|
this.consume(
|
|
9690
9703
|
"OPEN_PAREN",
|
|
@@ -9752,8 +9765,7 @@ var XPath30Parser = class extends XPath20Parser {
|
|
|
9752
9765
|
return this.parseStringTemplateFromLexeme(template);
|
|
9753
9766
|
}
|
|
9754
9767
|
if (this.match("DOLLAR")) {
|
|
9755
|
-
|
|
9756
|
-
return new XPathVariableReference(nameToken.lexeme);
|
|
9768
|
+
return new XPathVariableReference(this.parseVariableReferenceName());
|
|
9757
9769
|
}
|
|
9758
9770
|
if (this.checkReservedWordInternal("function")) {
|
|
9759
9771
|
return this.parseInlineFunction();
|
|
@@ -11846,7 +11858,9 @@ var NodeConverter = class {
|
|
|
11846
11858
|
* We add missing properties but keep the original XNode reference.
|
|
11847
11859
|
*/
|
|
11848
11860
|
adaptXNode(node) {
|
|
11849
|
-
if (!node)
|
|
11861
|
+
if (!node) {
|
|
11862
|
+
throw new Error("Cannot adapt undefined XPath node.");
|
|
11863
|
+
}
|
|
11850
11864
|
const adapted = node;
|
|
11851
11865
|
if (!("textContent" in adapted)) {
|
|
11852
11866
|
Object.defineProperty(adapted, "textContent", {
|
|
@@ -11932,7 +11946,12 @@ var NodeConverter = class {
|
|
|
11932
11946
|
}
|
|
11933
11947
|
for (let i = contexts.length - 1; i >= 0; i--) {
|
|
11934
11948
|
const current = contexts[i];
|
|
11935
|
-
|
|
11949
|
+
const currentVariables = current.variables || {};
|
|
11950
|
+
for (const name in currentVariables) {
|
|
11951
|
+
if (!Object.prototype.hasOwnProperty.call(currentVariables, name)) {
|
|
11952
|
+
continue;
|
|
11953
|
+
}
|
|
11954
|
+
const value = currentVariables[name];
|
|
11936
11955
|
if (value && typeof value === "object" && "stringValue" in value) {
|
|
11937
11956
|
const nodeValue = value;
|
|
11938
11957
|
if (nodeValue.type === "node-set") {
|
|
@@ -11981,7 +12000,7 @@ var NodeConverter = class {
|
|
|
11981
12000
|
};
|
|
11982
12001
|
functions["format-number"] = (_context, number, format, decimalFormatName) => {
|
|
11983
12002
|
const settings = exprContext.decimalFormatSettings;
|
|
11984
|
-
return
|
|
12003
|
+
return this.formatXsltNumberPicture(Number(number), String(format), settings);
|
|
11985
12004
|
};
|
|
11986
12005
|
functions["xml-to-json"] = (_context, nodes) => {
|
|
11987
12006
|
if (exprContext.xsltVersion !== "3.0") {
|
|
@@ -12062,7 +12081,7 @@ var NodeConverter = class {
|
|
|
12062
12081
|
"xsl:with-param"
|
|
12063
12082
|
];
|
|
12064
12083
|
const normalizedName = name.startsWith("xsl:") ? name : `xsl:${name}`;
|
|
12065
|
-
return xsltElements.
|
|
12084
|
+
return xsltElements.indexOf(normalizedName) >= 0 || xsltElements.indexOf(name) >= 0;
|
|
12066
12085
|
};
|
|
12067
12086
|
functions["function-available"] = (_context, functionName2) => {
|
|
12068
12087
|
const name = String(functionName2);
|
|
@@ -12113,7 +12132,7 @@ var NodeConverter = class {
|
|
|
12113
12132
|
"json-to-xml"
|
|
12114
12133
|
];
|
|
12115
12134
|
const allFunctions = [...xpathCoreFunctions, ...xsltFunctions, ...additionalFunctions];
|
|
12116
|
-
return allFunctions.
|
|
12135
|
+
return allFunctions.indexOf(name) >= 0;
|
|
12117
12136
|
};
|
|
12118
12137
|
functions["document"] = (_context, uriOrNodeSet, _baseNode) => {
|
|
12119
12138
|
var _a, _b;
|
|
@@ -12157,6 +12176,95 @@ var NodeConverter = class {
|
|
|
12157
12176
|
}
|
|
12158
12177
|
return functions;
|
|
12159
12178
|
}
|
|
12179
|
+
/**
|
|
12180
|
+
* Minimal XSLT/XPath format-number() picture formatter.
|
|
12181
|
+
* Supports grouping, decimal precision, percent/per-mille scaling and positive/negative subpictures.
|
|
12182
|
+
*/
|
|
12183
|
+
formatXsltNumberPicture(value, picture, settings) {
|
|
12184
|
+
if (Number.isNaN(value)) {
|
|
12185
|
+
return settings.naN;
|
|
12186
|
+
}
|
|
12187
|
+
if (!Number.isFinite(value)) {
|
|
12188
|
+
return value < 0 ? `${settings.minusSign}${settings.infinity}` : settings.infinity;
|
|
12189
|
+
}
|
|
12190
|
+
const subPictures = picture.split(settings.patternSeparator);
|
|
12191
|
+
const isNegative = value < 0;
|
|
12192
|
+
const activePicture = (isNegative && subPictures.length > 1 ? subPictures[1] : subPictures[0]) || "";
|
|
12193
|
+
const absValue = Math.abs(value);
|
|
12194
|
+
const placeholders = /* @__PURE__ */ new Set([settings.digit, settings.zeroDigit, settings.groupingSeparator, settings.decimalSeparator]);
|
|
12195
|
+
let firstPatternIndex = -1;
|
|
12196
|
+
let lastPatternIndex = -1;
|
|
12197
|
+
for (let i = 0; i < activePicture.length; i++) {
|
|
12198
|
+
if (placeholders.has(activePicture[i])) {
|
|
12199
|
+
if (firstPatternIndex === -1) {
|
|
12200
|
+
firstPatternIndex = i;
|
|
12201
|
+
}
|
|
12202
|
+
lastPatternIndex = i;
|
|
12203
|
+
}
|
|
12204
|
+
}
|
|
12205
|
+
if (firstPatternIndex === -1) {
|
|
12206
|
+
return activePicture;
|
|
12207
|
+
}
|
|
12208
|
+
const prefix = activePicture.slice(0, firstPatternIndex);
|
|
12209
|
+
const suffix = activePicture.slice(lastPatternIndex + 1);
|
|
12210
|
+
const numericPicture = activePicture.slice(firstPatternIndex, lastPatternIndex + 1);
|
|
12211
|
+
let scaledValue = absValue;
|
|
12212
|
+
if (activePicture.includes(settings.percent)) {
|
|
12213
|
+
scaledValue *= 100;
|
|
12214
|
+
}
|
|
12215
|
+
if (activePicture.includes(settings.perMille)) {
|
|
12216
|
+
scaledValue *= 1e3;
|
|
12217
|
+
}
|
|
12218
|
+
const decimalIndex = numericPicture.indexOf(settings.decimalSeparator);
|
|
12219
|
+
const integerPattern = decimalIndex >= 0 ? numericPicture.slice(0, decimalIndex) : numericPicture;
|
|
12220
|
+
const fractionPattern = decimalIndex >= 0 ? numericPicture.slice(decimalIndex + 1) : "";
|
|
12221
|
+
const minIntegerDigits = integerPattern.split("").filter((c) => c === settings.zeroDigit).length;
|
|
12222
|
+
const minFractionDigits = fractionPattern.split("").filter((c) => c === settings.zeroDigit).length;
|
|
12223
|
+
const maxFractionDigits = fractionPattern.split("").filter((c) => c === settings.zeroDigit || c === settings.digit).length;
|
|
12224
|
+
const rounded = maxFractionDigits > 0 ? scaledValue.toFixed(maxFractionDigits) : Math.round(scaledValue).toString();
|
|
12225
|
+
let [integerPart, fractionPart = ""] = rounded.split(".");
|
|
12226
|
+
if (integerPart.length < minIntegerDigits) {
|
|
12227
|
+
integerPart = this.leftPad(integerPart, minIntegerDigits, settings.zeroDigit);
|
|
12228
|
+
}
|
|
12229
|
+
while (fractionPart.length > minFractionDigits && fractionPart.endsWith(settings.zeroDigit)) {
|
|
12230
|
+
fractionPart = fractionPart.slice(0, -1);
|
|
12231
|
+
}
|
|
12232
|
+
const lastGroupingPos = integerPattern.lastIndexOf(settings.groupingSeparator);
|
|
12233
|
+
if (lastGroupingPos >= 0) {
|
|
12234
|
+
const groupSize = integerPattern.slice(lastGroupingPos + 1).split("").filter((c) => c === settings.zeroDigit || c === settings.digit).length;
|
|
12235
|
+
if (groupSize > 0) {
|
|
12236
|
+
integerPart = this.applyGrouping(integerPart, settings.groupingSeparator, groupSize);
|
|
12237
|
+
}
|
|
12238
|
+
}
|
|
12239
|
+
const numberText = fractionPart.length > 0 ? `${integerPart}${settings.decimalSeparator}${fractionPart}` : integerPart;
|
|
12240
|
+
if (isNegative && subPictures.length < 2) {
|
|
12241
|
+
return `${settings.minusSign}${prefix}${numberText}${suffix}`;
|
|
12242
|
+
}
|
|
12243
|
+
return `${prefix}${numberText}${suffix}`;
|
|
12244
|
+
}
|
|
12245
|
+
applyGrouping(numberText, separator, groupSize) {
|
|
12246
|
+
if (groupSize <= 0 || numberText.length <= groupSize) {
|
|
12247
|
+
return numberText;
|
|
12248
|
+
}
|
|
12249
|
+
const chunks = [];
|
|
12250
|
+
for (let i = numberText.length; i > 0; i -= groupSize) {
|
|
12251
|
+
const start = Math.max(0, i - groupSize);
|
|
12252
|
+
chunks.unshift(numberText.slice(start, i));
|
|
12253
|
+
}
|
|
12254
|
+
return chunks.join(separator);
|
|
12255
|
+
}
|
|
12256
|
+
leftPad(value, width, fillChar) {
|
|
12257
|
+
if (value.length >= width) {
|
|
12258
|
+
return value;
|
|
12259
|
+
}
|
|
12260
|
+
const padChar = fillChar && fillChar.length > 0 ? fillChar.charAt(0) : "0";
|
|
12261
|
+
const missing = width - value.length;
|
|
12262
|
+
let padding = "";
|
|
12263
|
+
for (let i = 0; i < missing; i++) {
|
|
12264
|
+
padding += padChar;
|
|
12265
|
+
}
|
|
12266
|
+
return padding + value;
|
|
12267
|
+
}
|
|
12160
12268
|
/**
|
|
12161
12269
|
* Convert an XPathNode interface tree to actual XNode objects.
|
|
12162
12270
|
* This is needed to convert json-to-xml() output to XSLT-compatible nodes.
|
|
@@ -12169,7 +12277,11 @@ var NodeConverter = class {
|
|
|
12169
12277
|
if (xpathNode.nodeType === DOM_DOCUMENT_NODE) {
|
|
12170
12278
|
if (xpathNode.childNodes && xpathNode.childNodes.length > 0) {
|
|
12171
12279
|
const rootChild = xpathNode.childNodes[0];
|
|
12172
|
-
|
|
12280
|
+
const convertedNode = this.convertXPathNodeToXNode(rootChild, ownerDoc);
|
|
12281
|
+
if (!convertedNode) {
|
|
12282
|
+
return null;
|
|
12283
|
+
}
|
|
12284
|
+
node = convertedNode;
|
|
12173
12285
|
return node;
|
|
12174
12286
|
}
|
|
12175
12287
|
return null;
|
|
@@ -15402,7 +15514,7 @@ var Xslt = class {
|
|
|
15402
15514
|
);
|
|
15403
15515
|
if (onCompletionElements.length > 0) {
|
|
15404
15516
|
const onCompletion = onCompletionElements[0];
|
|
15405
|
-
const completionContext = context.clone(
|
|
15517
|
+
const completionContext = context.clone();
|
|
15406
15518
|
for (const accName in accumulators) {
|
|
15407
15519
|
completionContext.variables[accName] = accumulators[accName];
|
|
15408
15520
|
}
|