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.mjs
CHANGED
|
@@ -9069,13 +9069,9 @@ var XPathBaseParser = class {
|
|
|
9069
9069
|
return expr;
|
|
9070
9070
|
}
|
|
9071
9071
|
parsePrimaryExpr() {
|
|
9072
|
-
var _a, _b
|
|
9072
|
+
var _a, _b;
|
|
9073
9073
|
if (this.match("DOLLAR")) {
|
|
9074
|
-
const
|
|
9075
|
-
if (!next || !this.isNcNameToken(next.type)) {
|
|
9076
|
-
throw grammarViolation(`Expected variable name after $. Got: ${(_a = next == null ? void 0 : next.lexeme) != null ? _a : "EOF"}`);
|
|
9077
|
-
}
|
|
9078
|
-
const name = this.advance().lexeme;
|
|
9074
|
+
const name = this.parseVariableReferenceName();
|
|
9079
9075
|
return new XPathVariableReference(name);
|
|
9080
9076
|
}
|
|
9081
9077
|
if (this.match("OPEN_PAREN")) {
|
|
@@ -9099,7 +9095,7 @@ var XPathBaseParser = class {
|
|
|
9099
9095
|
return this.parseFunctionCall();
|
|
9100
9096
|
}
|
|
9101
9097
|
throw grammarViolation(
|
|
9102
|
-
`Unexpected token in primary expression: ${(
|
|
9098
|
+
`Unexpected token in primary expression: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`
|
|
9103
9099
|
);
|
|
9104
9100
|
}
|
|
9105
9101
|
parseFunctionCall() {
|
|
@@ -9171,6 +9167,27 @@ var XPathBaseParser = class {
|
|
|
9171
9167
|
isFunctionNameToken(type) {
|
|
9172
9168
|
return type === "IDENTIFIER" || type === "FUNCTION" || type === "OPERATOR" || type === "LOCATION" || type === "EQNAME";
|
|
9173
9169
|
}
|
|
9170
|
+
parseVariableReferenceName() {
|
|
9171
|
+
var _a, _b;
|
|
9172
|
+
if (this.check("EQNAME")) {
|
|
9173
|
+
return this.advance().lexeme;
|
|
9174
|
+
}
|
|
9175
|
+
const next = this.peek();
|
|
9176
|
+
if (!next || !this.isNcNameToken(next.type)) {
|
|
9177
|
+
throw grammarViolation(`Expected variable name after $. Got: ${(_a = next == null ? void 0 : next.lexeme) != null ? _a : "EOF"}`);
|
|
9178
|
+
}
|
|
9179
|
+
let name = this.advance().lexeme;
|
|
9180
|
+
if (this.match("COLON")) {
|
|
9181
|
+
const local = this.peek();
|
|
9182
|
+
if (!local || !this.isNcNameToken(local.type)) {
|
|
9183
|
+
throw grammarViolation(
|
|
9184
|
+
`Expected local name after namespace prefix in variable reference. Got: ${(_b = local == null ? void 0 : local.lexeme) != null ? _b : "EOF"}`
|
|
9185
|
+
);
|
|
9186
|
+
}
|
|
9187
|
+
name = `${name}:${this.advance().lexeme}`;
|
|
9188
|
+
}
|
|
9189
|
+
return name;
|
|
9190
|
+
}
|
|
9174
9191
|
isNcNameToken(type) {
|
|
9175
9192
|
return type === "IDENTIFIER" || type === "FUNCTION" || type === "OPERATOR" || type === "LOCATION" || type === "NODE_TYPE";
|
|
9176
9193
|
}
|
|
@@ -9283,16 +9300,12 @@ var XPath20Parser = class extends XPathBaseParser {
|
|
|
9283
9300
|
return left;
|
|
9284
9301
|
}
|
|
9285
9302
|
parsePrimaryExpr() {
|
|
9286
|
-
var _a, _b;
|
|
9287
9303
|
if (this.check("RESERVED_WORD") && this.peek().lexeme === "if") {
|
|
9288
9304
|
return this.parseIfExpr();
|
|
9289
9305
|
}
|
|
9290
9306
|
if (this.check("DOLLAR")) {
|
|
9291
9307
|
this.advance();
|
|
9292
|
-
|
|
9293
|
-
throw new Error(`Expected variable name after $. Got: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`);
|
|
9294
|
-
}
|
|
9295
|
-
const name = this.advance().lexeme;
|
|
9308
|
+
const name = this.parseVariableReferenceName();
|
|
9296
9309
|
return new XPathVariableReference(name);
|
|
9297
9310
|
}
|
|
9298
9311
|
return super.parsePrimaryExpr();
|
|
@@ -9669,7 +9682,7 @@ var XPath30Parser = class extends XPath20Parser {
|
|
|
9669
9682
|
let args = [];
|
|
9670
9683
|
if (this.check("DOLLAR")) {
|
|
9671
9684
|
this.advance();
|
|
9672
|
-
const varName = this.
|
|
9685
|
+
const varName = this.parseVariableReferenceName();
|
|
9673
9686
|
funcExpr = new XPathVariableReference(varName);
|
|
9674
9687
|
this.consume(
|
|
9675
9688
|
"OPEN_PAREN",
|
|
@@ -9737,8 +9750,7 @@ var XPath30Parser = class extends XPath20Parser {
|
|
|
9737
9750
|
return this.parseStringTemplateFromLexeme(template);
|
|
9738
9751
|
}
|
|
9739
9752
|
if (this.match("DOLLAR")) {
|
|
9740
|
-
|
|
9741
|
-
return new XPathVariableReference(nameToken.lexeme);
|
|
9753
|
+
return new XPathVariableReference(this.parseVariableReferenceName());
|
|
9742
9754
|
}
|
|
9743
9755
|
if (this.checkReservedWordInternal("function")) {
|
|
9744
9756
|
return this.parseInlineFunction();
|
|
@@ -11831,7 +11843,9 @@ var NodeConverter = class {
|
|
|
11831
11843
|
* We add missing properties but keep the original XNode reference.
|
|
11832
11844
|
*/
|
|
11833
11845
|
adaptXNode(node) {
|
|
11834
|
-
if (!node)
|
|
11846
|
+
if (!node) {
|
|
11847
|
+
throw new Error("Cannot adapt undefined XPath node.");
|
|
11848
|
+
}
|
|
11835
11849
|
const adapted = node;
|
|
11836
11850
|
if (!("textContent" in adapted)) {
|
|
11837
11851
|
Object.defineProperty(adapted, "textContent", {
|
|
@@ -11917,7 +11931,12 @@ var NodeConverter = class {
|
|
|
11917
11931
|
}
|
|
11918
11932
|
for (let i = contexts.length - 1; i >= 0; i--) {
|
|
11919
11933
|
const current = contexts[i];
|
|
11920
|
-
|
|
11934
|
+
const currentVariables = current.variables || {};
|
|
11935
|
+
for (const name in currentVariables) {
|
|
11936
|
+
if (!Object.prototype.hasOwnProperty.call(currentVariables, name)) {
|
|
11937
|
+
continue;
|
|
11938
|
+
}
|
|
11939
|
+
const value = currentVariables[name];
|
|
11921
11940
|
if (value && typeof value === "object" && "stringValue" in value) {
|
|
11922
11941
|
const nodeValue = value;
|
|
11923
11942
|
if (nodeValue.type === "node-set") {
|
|
@@ -11966,7 +11985,7 @@ var NodeConverter = class {
|
|
|
11966
11985
|
};
|
|
11967
11986
|
functions["format-number"] = (_context, number, format, decimalFormatName) => {
|
|
11968
11987
|
const settings = exprContext.decimalFormatSettings;
|
|
11969
|
-
return
|
|
11988
|
+
return this.formatXsltNumberPicture(Number(number), String(format), settings);
|
|
11970
11989
|
};
|
|
11971
11990
|
functions["xml-to-json"] = (_context, nodes) => {
|
|
11972
11991
|
if (exprContext.xsltVersion !== "3.0") {
|
|
@@ -12047,7 +12066,7 @@ var NodeConverter = class {
|
|
|
12047
12066
|
"xsl:with-param"
|
|
12048
12067
|
];
|
|
12049
12068
|
const normalizedName = name.startsWith("xsl:") ? name : `xsl:${name}`;
|
|
12050
|
-
return xsltElements.
|
|
12069
|
+
return xsltElements.indexOf(normalizedName) >= 0 || xsltElements.indexOf(name) >= 0;
|
|
12051
12070
|
};
|
|
12052
12071
|
functions["function-available"] = (_context, functionName2) => {
|
|
12053
12072
|
const name = String(functionName2);
|
|
@@ -12098,7 +12117,7 @@ var NodeConverter = class {
|
|
|
12098
12117
|
"json-to-xml"
|
|
12099
12118
|
];
|
|
12100
12119
|
const allFunctions = [...xpathCoreFunctions, ...xsltFunctions, ...additionalFunctions];
|
|
12101
|
-
return allFunctions.
|
|
12120
|
+
return allFunctions.indexOf(name) >= 0;
|
|
12102
12121
|
};
|
|
12103
12122
|
functions["document"] = (_context, uriOrNodeSet, _baseNode) => {
|
|
12104
12123
|
var _a, _b;
|
|
@@ -12142,6 +12161,95 @@ var NodeConverter = class {
|
|
|
12142
12161
|
}
|
|
12143
12162
|
return functions;
|
|
12144
12163
|
}
|
|
12164
|
+
/**
|
|
12165
|
+
* Minimal XSLT/XPath format-number() picture formatter.
|
|
12166
|
+
* Supports grouping, decimal precision, percent/per-mille scaling and positive/negative subpictures.
|
|
12167
|
+
*/
|
|
12168
|
+
formatXsltNumberPicture(value, picture, settings) {
|
|
12169
|
+
if (Number.isNaN(value)) {
|
|
12170
|
+
return settings.naN;
|
|
12171
|
+
}
|
|
12172
|
+
if (!Number.isFinite(value)) {
|
|
12173
|
+
return value < 0 ? `${settings.minusSign}${settings.infinity}` : settings.infinity;
|
|
12174
|
+
}
|
|
12175
|
+
const subPictures = picture.split(settings.patternSeparator);
|
|
12176
|
+
const isNegative = value < 0;
|
|
12177
|
+
const activePicture = (isNegative && subPictures.length > 1 ? subPictures[1] : subPictures[0]) || "";
|
|
12178
|
+
const absValue = Math.abs(value);
|
|
12179
|
+
const placeholders = /* @__PURE__ */ new Set([settings.digit, settings.zeroDigit, settings.groupingSeparator, settings.decimalSeparator]);
|
|
12180
|
+
let firstPatternIndex = -1;
|
|
12181
|
+
let lastPatternIndex = -1;
|
|
12182
|
+
for (let i = 0; i < activePicture.length; i++) {
|
|
12183
|
+
if (placeholders.has(activePicture[i])) {
|
|
12184
|
+
if (firstPatternIndex === -1) {
|
|
12185
|
+
firstPatternIndex = i;
|
|
12186
|
+
}
|
|
12187
|
+
lastPatternIndex = i;
|
|
12188
|
+
}
|
|
12189
|
+
}
|
|
12190
|
+
if (firstPatternIndex === -1) {
|
|
12191
|
+
return activePicture;
|
|
12192
|
+
}
|
|
12193
|
+
const prefix = activePicture.slice(0, firstPatternIndex);
|
|
12194
|
+
const suffix = activePicture.slice(lastPatternIndex + 1);
|
|
12195
|
+
const numericPicture = activePicture.slice(firstPatternIndex, lastPatternIndex + 1);
|
|
12196
|
+
let scaledValue = absValue;
|
|
12197
|
+
if (activePicture.includes(settings.percent)) {
|
|
12198
|
+
scaledValue *= 100;
|
|
12199
|
+
}
|
|
12200
|
+
if (activePicture.includes(settings.perMille)) {
|
|
12201
|
+
scaledValue *= 1e3;
|
|
12202
|
+
}
|
|
12203
|
+
const decimalIndex = numericPicture.indexOf(settings.decimalSeparator);
|
|
12204
|
+
const integerPattern = decimalIndex >= 0 ? numericPicture.slice(0, decimalIndex) : numericPicture;
|
|
12205
|
+
const fractionPattern = decimalIndex >= 0 ? numericPicture.slice(decimalIndex + 1) : "";
|
|
12206
|
+
const minIntegerDigits = integerPattern.split("").filter((c) => c === settings.zeroDigit).length;
|
|
12207
|
+
const minFractionDigits = fractionPattern.split("").filter((c) => c === settings.zeroDigit).length;
|
|
12208
|
+
const maxFractionDigits = fractionPattern.split("").filter((c) => c === settings.zeroDigit || c === settings.digit).length;
|
|
12209
|
+
const rounded = maxFractionDigits > 0 ? scaledValue.toFixed(maxFractionDigits) : Math.round(scaledValue).toString();
|
|
12210
|
+
let [integerPart, fractionPart = ""] = rounded.split(".");
|
|
12211
|
+
if (integerPart.length < minIntegerDigits) {
|
|
12212
|
+
integerPart = this.leftPad(integerPart, minIntegerDigits, settings.zeroDigit);
|
|
12213
|
+
}
|
|
12214
|
+
while (fractionPart.length > minFractionDigits && fractionPart.endsWith(settings.zeroDigit)) {
|
|
12215
|
+
fractionPart = fractionPart.slice(0, -1);
|
|
12216
|
+
}
|
|
12217
|
+
const lastGroupingPos = integerPattern.lastIndexOf(settings.groupingSeparator);
|
|
12218
|
+
if (lastGroupingPos >= 0) {
|
|
12219
|
+
const groupSize = integerPattern.slice(lastGroupingPos + 1).split("").filter((c) => c === settings.zeroDigit || c === settings.digit).length;
|
|
12220
|
+
if (groupSize > 0) {
|
|
12221
|
+
integerPart = this.applyGrouping(integerPart, settings.groupingSeparator, groupSize);
|
|
12222
|
+
}
|
|
12223
|
+
}
|
|
12224
|
+
const numberText = fractionPart.length > 0 ? `${integerPart}${settings.decimalSeparator}${fractionPart}` : integerPart;
|
|
12225
|
+
if (isNegative && subPictures.length < 2) {
|
|
12226
|
+
return `${settings.minusSign}${prefix}${numberText}${suffix}`;
|
|
12227
|
+
}
|
|
12228
|
+
return `${prefix}${numberText}${suffix}`;
|
|
12229
|
+
}
|
|
12230
|
+
applyGrouping(numberText, separator, groupSize) {
|
|
12231
|
+
if (groupSize <= 0 || numberText.length <= groupSize) {
|
|
12232
|
+
return numberText;
|
|
12233
|
+
}
|
|
12234
|
+
const chunks = [];
|
|
12235
|
+
for (let i = numberText.length; i > 0; i -= groupSize) {
|
|
12236
|
+
const start = Math.max(0, i - groupSize);
|
|
12237
|
+
chunks.unshift(numberText.slice(start, i));
|
|
12238
|
+
}
|
|
12239
|
+
return chunks.join(separator);
|
|
12240
|
+
}
|
|
12241
|
+
leftPad(value, width, fillChar) {
|
|
12242
|
+
if (value.length >= width) {
|
|
12243
|
+
return value;
|
|
12244
|
+
}
|
|
12245
|
+
const padChar = fillChar && fillChar.length > 0 ? fillChar.charAt(0) : "0";
|
|
12246
|
+
const missing = width - value.length;
|
|
12247
|
+
let padding = "";
|
|
12248
|
+
for (let i = 0; i < missing; i++) {
|
|
12249
|
+
padding += padChar;
|
|
12250
|
+
}
|
|
12251
|
+
return padding + value;
|
|
12252
|
+
}
|
|
12145
12253
|
/**
|
|
12146
12254
|
* Convert an XPathNode interface tree to actual XNode objects.
|
|
12147
12255
|
* This is needed to convert json-to-xml() output to XSLT-compatible nodes.
|
|
@@ -12154,7 +12262,11 @@ var NodeConverter = class {
|
|
|
12154
12262
|
if (xpathNode.nodeType === DOM_DOCUMENT_NODE) {
|
|
12155
12263
|
if (xpathNode.childNodes && xpathNode.childNodes.length > 0) {
|
|
12156
12264
|
const rootChild = xpathNode.childNodes[0];
|
|
12157
|
-
|
|
12265
|
+
const convertedNode = this.convertXPathNodeToXNode(rootChild, ownerDoc);
|
|
12266
|
+
if (!convertedNode) {
|
|
12267
|
+
return null;
|
|
12268
|
+
}
|
|
12269
|
+
node = convertedNode;
|
|
12158
12270
|
return node;
|
|
12159
12271
|
}
|
|
12160
12272
|
return null;
|
|
@@ -15387,7 +15499,7 @@ var Xslt = class {
|
|
|
15387
15499
|
);
|
|
15388
15500
|
if (onCompletionElements.length > 0) {
|
|
15389
15501
|
const onCompletion = onCompletionElements[0];
|
|
15390
|
-
const completionContext = context.clone(
|
|
15502
|
+
const completionContext = context.clone();
|
|
15391
15503
|
for (const accName in accumulators) {
|
|
15392
15504
|
completionContext.variables[accName] = accumulators[accName];
|
|
15393
15505
|
}
|