xslt-processor 4.8.4 → 4.8.5

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/index.d.mts CHANGED
@@ -719,6 +719,11 @@ declare class MatchResolver {
719
719
  private relativeXsltMatch;
720
720
  }
721
721
 
722
+ interface WhitespacePattern {
723
+ namespaceUri: string | null;
724
+ localName: string;
725
+ isWildcard: boolean;
726
+ }
722
727
  /**
723
728
  * The main class for XSL-T processing.
724
729
  *
@@ -775,13 +780,13 @@ declare class Xslt {
775
780
  * List of element name patterns from xsl:strip-space declarations.
776
781
  * Whitespace-only text nodes inside matching elements will be stripped.
777
782
  */
778
- stripSpacePatterns: string[];
783
+ stripSpacePatterns: WhitespacePattern[];
779
784
  /**
780
785
  * List of element name patterns from xsl:preserve-space declarations.
781
786
  * Whitespace-only text nodes inside matching elements will be preserved.
782
787
  * preserve-space takes precedence over strip-space for conflicting patterns.
783
788
  */
784
- preserveSpacePatterns: string[];
789
+ preserveSpacePatterns: WhitespacePattern[];
785
790
  /**
786
791
  * Namespace aliases from xsl:namespace-alias declarations.
787
792
  * Maps stylesheet namespace prefixes to result namespace prefixes.
@@ -1346,6 +1351,9 @@ declare class Xslt {
1346
1351
  * @todo case-order is not implemented.
1347
1352
  */
1348
1353
  protected xsltSort(context: ExprContext, template: XNode): void;
1354
+ private resolveNamespaceUriForPrefix;
1355
+ private isNamespaceDeclaredOnAncestor;
1356
+ private parseWhitespacePattern;
1349
1357
  /**
1350
1358
  * Implements `xsl:strip-space`.
1351
1359
  * Collects element name patterns for which whitespace-only text nodes should be stripped.
@@ -1378,7 +1386,7 @@ declare class Xslt {
1378
1386
  * @param element The element node (for namespace checking).
1379
1387
  * @returns True if the element matches the pattern.
1380
1388
  */
1381
- protected matchesNamePattern(elementName: string, pattern: string, element: XNode): boolean;
1389
+ protected matchesNamePattern(elementName: string, pattern: WhitespacePattern, element: XNode): boolean;
1382
1390
  /**
1383
1391
  * Implements `xsl:template`.
1384
1392
  * @param context The Expression Context.
package/index.d.ts CHANGED
@@ -719,6 +719,11 @@ declare class MatchResolver {
719
719
  private relativeXsltMatch;
720
720
  }
721
721
 
722
+ interface WhitespacePattern {
723
+ namespaceUri: string | null;
724
+ localName: string;
725
+ isWildcard: boolean;
726
+ }
722
727
  /**
723
728
  * The main class for XSL-T processing.
724
729
  *
@@ -775,13 +780,13 @@ declare class Xslt {
775
780
  * List of element name patterns from xsl:strip-space declarations.
776
781
  * Whitespace-only text nodes inside matching elements will be stripped.
777
782
  */
778
- stripSpacePatterns: string[];
783
+ stripSpacePatterns: WhitespacePattern[];
779
784
  /**
780
785
  * List of element name patterns from xsl:preserve-space declarations.
781
786
  * Whitespace-only text nodes inside matching elements will be preserved.
782
787
  * preserve-space takes precedence over strip-space for conflicting patterns.
783
788
  */
784
- preserveSpacePatterns: string[];
789
+ preserveSpacePatterns: WhitespacePattern[];
785
790
  /**
786
791
  * Namespace aliases from xsl:namespace-alias declarations.
787
792
  * Maps stylesheet namespace prefixes to result namespace prefixes.
@@ -1346,6 +1351,9 @@ declare class Xslt {
1346
1351
  * @todo case-order is not implemented.
1347
1352
  */
1348
1353
  protected xsltSort(context: ExprContext, template: XNode): void;
1354
+ private resolveNamespaceUriForPrefix;
1355
+ private isNamespaceDeclaredOnAncestor;
1356
+ private parseWhitespacePattern;
1349
1357
  /**
1350
1358
  * Implements `xsl:strip-space`.
1351
1359
  * Collects element name patterns for which whitespace-only text nodes should be stripped.
@@ -1378,7 +1386,7 @@ declare class Xslt {
1378
1386
  * @param element The element node (for namespace checking).
1379
1387
  * @returns True if the element matches the pattern.
1380
1388
  */
1381
- protected matchesNamePattern(elementName: string, pattern: string, element: XNode): boolean;
1389
+ protected matchesNamePattern(elementName: string, pattern: WhitespacePattern, element: XNode): boolean;
1382
1390
  /**
1383
1391
  * Implements `xsl:template`.
1384
1392
  * @param context The Expression Context.
package/index.js CHANGED
@@ -10973,6 +10973,9 @@ function xmlElementLogicTrivial(node, buffer, options) {
10973
10973
  if (!attribute) {
10974
10974
  continue;
10975
10975
  }
10976
+ if (options.outputMethod === "html" && (attribute.nodeName === "xmlns" || attribute.nodeName.startsWith("xmlns:"))) {
10977
+ continue;
10978
+ }
10976
10979
  if (attribute.nodeName && attribute.nodeValue !== null && attribute.nodeValue !== void 0) {
10977
10980
  buffer.push(` ${xmlFullNodeName(attribute)}="${xmlEscapeAttr(attribute.nodeValue)}"`);
10978
10981
  }
@@ -14475,7 +14478,40 @@ var Xslt = class {
14475
14478
  } = currentTemplateContext;
14476
14479
  const currentNode = context.nodeList[context.position];
14477
14480
  const top = template.ownerDocument.documentElement;
14478
- const allTemplates = collectAndExpandTemplates(top, currentMode, this.xPath, this.templateSourceMap);
14481
+ const stylesheetRoots = [];
14482
+ if (top) {
14483
+ stylesheetRoots.push(top);
14484
+ }
14485
+ this.importedStylesheets.forEach((doc) => {
14486
+ if (!doc) {
14487
+ return;
14488
+ }
14489
+ if (doc.nodeType === DOM_DOCUMENT_NODE) {
14490
+ const rootElement = doc.childNodes.find(
14491
+ (child) => child.nodeType === DOM_ELEMENT_NODE
14492
+ );
14493
+ if (rootElement) {
14494
+ stylesheetRoots.push(rootElement);
14495
+ }
14496
+ } else if (doc.nodeType === DOM_ELEMENT_NODE) {
14497
+ stylesheetRoots.push(doc);
14498
+ }
14499
+ });
14500
+ let allTemplates = [];
14501
+ let docOrderOffset = 0;
14502
+ for (const root2 of stylesheetRoots) {
14503
+ const templates = collectAndExpandTemplates(
14504
+ root2,
14505
+ currentMode,
14506
+ this.xPath,
14507
+ this.templateSourceMap
14508
+ );
14509
+ for (const templateEntry of templates) {
14510
+ templateEntry.documentOrder += docOrderOffset;
14511
+ }
14512
+ docOrderOffset += templates.length;
14513
+ allTemplates = allTemplates.concat(templates);
14514
+ }
14479
14515
  const importedTemplates = allTemplates.filter((t) => {
14480
14516
  const metadata2 = this.templateSourceMap.get(t.template);
14481
14517
  return metadata2 && metadata2.importDepth > currentDepth;
@@ -14611,7 +14647,11 @@ var Xslt = class {
14611
14647
  if (source.nodeType == DOM_ELEMENT_NODE) {
14612
14648
  let node = domCreateElement(this.outputDocument, source.nodeName);
14613
14649
  if (source.namespaceUri !== null && source.namespaceUri !== void 0) {
14614
- domSetAttribute(node, "xmlns", source.namespaceUri);
14650
+ const prefix = source.prefix || (source.nodeName.includes(":") ? source.nodeName.split(":")[0] : null);
14651
+ const nsAttr = prefix ? `xmlns:${prefix}` : "xmlns";
14652
+ if (!this.isNamespaceDeclaredOnAncestor(destination, nsAttr, source.namespaceUri)) {
14653
+ domSetAttribute(node, nsAttr, source.namespaceUri);
14654
+ }
14615
14655
  }
14616
14656
  node.siblingPosition = destination.childNodes.length;
14617
14657
  domAppendChild(destination, node);
@@ -16354,6 +16394,17 @@ var Xslt = class {
16354
16394
  * @returns The formatted number string.
16355
16395
  */
16356
16396
  xsltFormatNumber(number, format, groupingSeparator, groupingSize) {
16397
+ if (format.match(/^0+1$/)) {
16398
+ const width = format.length;
16399
+ let result2 = number.toString().padStart(width, "0");
16400
+ if (groupingSeparator && groupingSize) {
16401
+ const size = parseInt(groupingSize, 10);
16402
+ if (size > 0 && !isNaN(size)) {
16403
+ result2 = this.applyGrouping(result2, groupingSeparator, size);
16404
+ }
16405
+ }
16406
+ return result2;
16407
+ }
16357
16408
  const formatChar = format.charAt(0);
16358
16409
  let result;
16359
16410
  switch (formatChar) {
@@ -16482,6 +16533,54 @@ var Xslt = class {
16482
16533
  }
16483
16534
  this.xPath.xPathSort(context, sort2);
16484
16535
  }
16536
+ resolveNamespaceUriForPrefix(node, prefix) {
16537
+ const attrName = prefix ? `xmlns:${prefix}` : "xmlns";
16538
+ let current = node;
16539
+ while (current) {
16540
+ const attributes = current.childNodes.filter(
16541
+ (child) => child.nodeType === DOM_ATTRIBUTE_NODE
16542
+ );
16543
+ for (const attribute of attributes) {
16544
+ if (attribute.nodeName === attrName) {
16545
+ return attribute.nodeValue;
16546
+ }
16547
+ if (prefix && attribute.prefix === "xmlns" && attribute.localName === prefix) {
16548
+ return attribute.nodeValue;
16549
+ }
16550
+ if (!prefix && attribute.nodeName === "xmlns") {
16551
+ return attribute.nodeValue;
16552
+ }
16553
+ }
16554
+ current = current.parentNode;
16555
+ }
16556
+ return null;
16557
+ }
16558
+ isNamespaceDeclaredOnAncestor(node, nsAttr, nsUri) {
16559
+ let current = node;
16560
+ while (current) {
16561
+ const value = domGetAttributeValue(current, nsAttr);
16562
+ if (value === nsUri) {
16563
+ return true;
16564
+ }
16565
+ current = current.parentNode;
16566
+ }
16567
+ return false;
16568
+ }
16569
+ parseWhitespacePattern(pattern, template) {
16570
+ if (pattern === "*") {
16571
+ return { namespaceUri: null, localName: "*", isWildcard: true };
16572
+ }
16573
+ if (pattern.includes(":")) {
16574
+ const [prefix, localPart] = pattern.split(":");
16575
+ const namespaceUri = this.resolveNamespaceUriForPrefix(template, prefix);
16576
+ return {
16577
+ namespaceUri: namespaceUri != null ? namespaceUri : null,
16578
+ localName: localPart || "*",
16579
+ isWildcard: localPart === "*"
16580
+ };
16581
+ }
16582
+ return { namespaceUri: null, localName: pattern, isWildcard: false };
16583
+ }
16485
16584
  /**
16486
16585
  * Implements `xsl:strip-space`.
16487
16586
  * Collects element name patterns for which whitespace-only text nodes should be stripped.
@@ -16491,7 +16590,9 @@ var Xslt = class {
16491
16590
  const elements = xmlGetAttribute(template, "elements");
16492
16591
  if (elements) {
16493
16592
  const patterns = elements.trim().split(/\s+/);
16494
- this.stripSpacePatterns.push(...patterns);
16593
+ for (const pattern of patterns) {
16594
+ this.stripSpacePatterns.push(this.parseWhitespacePattern(pattern, template));
16595
+ }
16495
16596
  }
16496
16597
  }
16497
16598
  /**
@@ -16504,7 +16605,9 @@ var Xslt = class {
16504
16605
  const elements = xmlGetAttribute(template, "elements");
16505
16606
  if (elements) {
16506
16607
  const patterns = elements.trim().split(/\s+/);
16507
- this.preserveSpacePatterns.push(...patterns);
16608
+ for (const pattern of patterns) {
16609
+ this.preserveSpacePatterns.push(this.parseWhitespacePattern(pattern, template));
16610
+ }
16508
16611
  }
16509
16612
  }
16510
16613
  /**
@@ -16561,19 +16664,19 @@ var Xslt = class {
16561
16664
  * @returns True if the element matches the pattern.
16562
16665
  */
16563
16666
  matchesNamePattern(elementName, pattern, element) {
16564
- if (pattern === "*") {
16565
- return true;
16566
- }
16567
- if (pattern.includes(":")) {
16568
- const [prefix, localPart] = pattern.split(":");
16569
- const elementPrefix = element.prefix || "";
16570
- if (localPart === "*") {
16571
- return elementPrefix === prefix;
16572
- } else {
16573
- return elementPrefix === prefix && elementName === localPart;
16667
+ var _a;
16668
+ const elementNamespace = (_a = element.namespaceUri) != null ? _a : this.resolveNamespaceUriForPrefix(element, element.prefix || null);
16669
+ if (pattern.namespaceUri !== null) {
16670
+ if (elementNamespace !== pattern.namespaceUri) {
16671
+ return false;
16574
16672
  }
16673
+ } else if (!pattern.isWildcard && elementNamespace) {
16674
+ return false;
16675
+ }
16676
+ if (pattern.isWildcard) {
16677
+ return true;
16575
16678
  }
16576
- return elementName === pattern;
16679
+ return elementName === pattern.localName;
16577
16680
  }
16578
16681
  /**
16579
16682
  * Implements `xsl:template`.
@@ -17459,9 +17562,38 @@ var Xslt = class {
17459
17562
  let elementContext = context;
17460
17563
  node = context.nodeList[context.position];
17461
17564
  let newNode;
17462
- newNode = domCreateElement(this.outputDocument, template.nodeName);
17565
+ let qualifiedName = template.nodeName;
17566
+ let namespaceUri = template.namespaceUri;
17567
+ const templatePrefix = template.prefix || "";
17568
+ const aliasPrefix = this.namespaceAliases.get(templatePrefix);
17569
+ if (aliasPrefix) {
17570
+ const localName = template.localName || template.nodeName;
17571
+ if (aliasPrefix === "#default") {
17572
+ qualifiedName = localName;
17573
+ namespaceUri = this.resolveNamespaceUriForPrefix(template, null);
17574
+ } else {
17575
+ qualifiedName = `${aliasPrefix}:${localName}`;
17576
+ namespaceUri = this.resolveNamespaceUriForPrefix(template, aliasPrefix);
17577
+ }
17578
+ }
17579
+ newNode = domCreateElement(this.outputDocument, qualifiedName);
17463
17580
  newNode.siblingPosition = (output || this.outputDocument).childNodes.length;
17464
17581
  domAppendChild(output || this.outputDocument, newNode);
17582
+ if (aliasPrefix) {
17583
+ if (aliasPrefix === "#default") {
17584
+ if (namespaceUri) {
17585
+ domSetAttribute(newNode, "xmlns", namespaceUri);
17586
+ }
17587
+ } else if (namespaceUri) {
17588
+ domSetAttribute(newNode, `xmlns:${aliasPrefix}`, namespaceUri);
17589
+ }
17590
+ } else if (namespaceUri) {
17591
+ const prefix = templatePrefix || (qualifiedName.includes(":") ? qualifiedName.split(":")[0] : null);
17592
+ const nsAttr = prefix ? `xmlns:${prefix}` : "xmlns";
17593
+ if (!this.isNamespaceDeclaredOnAncestor(output, nsAttr, namespaceUri)) {
17594
+ domSetAttribute(newNode, nsAttr, namespaceUri);
17595
+ }
17596
+ }
17465
17597
  const useAttributeSetsAttr = template.childNodes.find(
17466
17598
  (a) => (a == null ? void 0 : a.nodeType) === DOM_ATTRIBUTE_NODE && a.nodeName === "use-attribute-sets"
17467
17599
  );