xslt-processor 4.3.0 → 4.3.1

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
@@ -22,6 +22,7 @@ declare class XNode {
22
22
  parentNode: XNode;
23
23
  visited: boolean;
24
24
  escape: boolean;
25
+ fromXslText: boolean;
25
26
  static _unusedXNodes: any[];
26
27
  constructor(type: number, name: string, opt_value: any, opt_owner: any, opt_namespace?: any);
27
28
  /**
@@ -138,7 +139,7 @@ interface XPathNode {
138
139
  nodeType: number;
139
140
  nodeName: string;
140
141
  localName?: string;
141
- namespaceURI?: string | null;
142
+ namespaceUri?: string | null;
142
143
  textContent?: string | null;
143
144
  parentNode?: XPathNode | null;
144
145
  childNodes?: ArrayLike<XPathNode>;
@@ -532,7 +533,7 @@ type XsltOptions = {
532
533
  cData: boolean;
533
534
  escape: boolean;
534
535
  selfClosingTags: boolean;
535
- outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json';
536
+ outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json' | 'adaptive';
536
537
  parameters?: XsltParameter[];
537
538
  };
538
539
 
@@ -567,7 +568,7 @@ declare class Xslt {
567
568
  options: XsltOptions;
568
569
  decimalFormatSettings: XsltDecimalFormatSettings;
569
570
  outputDocument: XDocument;
570
- outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json';
571
+ outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json' | 'adaptive';
571
572
  outputOmitXmlDeclaration: string;
572
573
  version: string;
573
574
  firstTemplateRan: boolean;
@@ -592,7 +593,7 @@ declare class Xslt {
592
593
  * The exported entry point of the XSL-T processor.
593
594
  * @param xmlDoc The input document root, as DOM node.
594
595
  * @param stylesheet The stylesheet document root, as DOM node.
595
- * @returns the processed document, as XML text in a string, or JSON string if outputMethod is 'json'.
596
+ * @returns the processed document, as XML text in a string, JSON string if outputMethod is 'json', or text if outputMethod is 'text' or 'adaptive' (with text content).
596
597
  */
597
598
  xsltProcess(xmlDoc: XDocument, stylesheet: XDocument): Promise<string>;
598
599
  /**
@@ -843,6 +844,17 @@ declare class Xslt {
843
844
  */
844
845
  protected xsltTemplate(context: ExprContext, template: XNode, output?: XNode): Promise<void>;
845
846
  protected xsltText(context: ExprContext, template: XNode, output?: XNode): void;
847
+ /**
848
+ * Validates XSLT stylesheet/transform attributes.
849
+ * According to XSLT specification, validates:
850
+ * - Required version attribute
851
+ * - Valid version values (1.0, 2.0, 3.0)
852
+ * - Valid namespace declarations
853
+ * - Valid values for optional attributes (extension-element-prefixes, exclude-result-prefixes)
854
+ * @param stylesheetElement The `<xsl:stylesheet>` or `<xsl:transform>` element to validate.
855
+ * @param context The Expression Context for namespace access.
856
+ */
857
+ protected validateStylesheetAttributes(stylesheetElement: XNode, context: ExprContext): void;
846
858
  /**
847
859
  * Implements `<xsl:stylesheet>` and `<xsl:transform>`, and its corresponding
848
860
  * validations.
package/index.d.ts CHANGED
@@ -22,6 +22,7 @@ declare class XNode {
22
22
  parentNode: XNode;
23
23
  visited: boolean;
24
24
  escape: boolean;
25
+ fromXslText: boolean;
25
26
  static _unusedXNodes: any[];
26
27
  constructor(type: number, name: string, opt_value: any, opt_owner: any, opt_namespace?: any);
27
28
  /**
@@ -138,7 +139,7 @@ interface XPathNode {
138
139
  nodeType: number;
139
140
  nodeName: string;
140
141
  localName?: string;
141
- namespaceURI?: string | null;
142
+ namespaceUri?: string | null;
142
143
  textContent?: string | null;
143
144
  parentNode?: XPathNode | null;
144
145
  childNodes?: ArrayLike<XPathNode>;
@@ -532,7 +533,7 @@ type XsltOptions = {
532
533
  cData: boolean;
533
534
  escape: boolean;
534
535
  selfClosingTags: boolean;
535
- outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json';
536
+ outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json' | 'adaptive';
536
537
  parameters?: XsltParameter[];
537
538
  };
538
539
 
@@ -567,7 +568,7 @@ declare class Xslt {
567
568
  options: XsltOptions;
568
569
  decimalFormatSettings: XsltDecimalFormatSettings;
569
570
  outputDocument: XDocument;
570
- outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json';
571
+ outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json' | 'adaptive';
571
572
  outputOmitXmlDeclaration: string;
572
573
  version: string;
573
574
  firstTemplateRan: boolean;
@@ -592,7 +593,7 @@ declare class Xslt {
592
593
  * The exported entry point of the XSL-T processor.
593
594
  * @param xmlDoc The input document root, as DOM node.
594
595
  * @param stylesheet The stylesheet document root, as DOM node.
595
- * @returns the processed document, as XML text in a string, or JSON string if outputMethod is 'json'.
596
+ * @returns the processed document, as XML text in a string, JSON string if outputMethod is 'json', or text if outputMethod is 'text' or 'adaptive' (with text content).
596
597
  */
597
598
  xsltProcess(xmlDoc: XDocument, stylesheet: XDocument): Promise<string>;
598
599
  /**
@@ -843,6 +844,17 @@ declare class Xslt {
843
844
  */
844
845
  protected xsltTemplate(context: ExprContext, template: XNode, output?: XNode): Promise<void>;
845
846
  protected xsltText(context: ExprContext, template: XNode, output?: XNode): void;
847
+ /**
848
+ * Validates XSLT stylesheet/transform attributes.
849
+ * According to XSLT specification, validates:
850
+ * - Required version attribute
851
+ * - Valid version values (1.0, 2.0, 3.0)
852
+ * - Valid namespace declarations
853
+ * - Valid values for optional attributes (extension-element-prefixes, exclude-result-prefixes)
854
+ * @param stylesheetElement The `<xsl:stylesheet>` or `<xsl:transform>` element to validate.
855
+ * @param context The Expression Context for namespace access.
856
+ */
857
+ protected validateStylesheetAttributes(stylesheetElement: XNode, context: ExprContext): void;
846
858
  /**
847
859
  * Implements `<xsl:stylesheet>` and `<xsl:transform>`, and its corresponding
848
860
  * validations.
package/index.js CHANGED
@@ -742,12 +742,12 @@ var XPathStep = class extends XPathExpression {
742
742
  if (!nsUri) {
743
743
  return false;
744
744
  }
745
- const nodeLocalName = node.localName || node.nodeName;
745
+ const nodeLocalName2 = node.localName || node.nodeName && this.extractLocalName(node.nodeName);
746
746
  const nodeNsUri = node.namespaceURI || node.namespaceUri || "";
747
- return nodeLocalName === localName && nodeNsUri === nsUri;
747
+ return nodeLocalName2 === localName && nodeNsUri === nsUri;
748
748
  }
749
- const nodeName = node.localName || node.nodeName;
750
- return nodeName === testName;
749
+ const nodeLocalName = node.localName || this.extractLocalName(node.nodeName);
750
+ return nodeLocalName === testName;
751
751
  case "node-type":
752
752
  switch (this.nodeTest.nodeType) {
753
753
  case "node":
@@ -806,6 +806,17 @@ var XPathStep = class extends XPathExpression {
806
806
  if (Array.isArray(value)) return value.length > 0;
807
807
  return !!value;
808
808
  }
809
+ /**
810
+ * Extract the local name from a qualified name (e.g., "ns:name" -> "name", "name" -> "name")
811
+ */
812
+ extractLocalName(qname) {
813
+ if (!qname) return "";
814
+ const colonIndex = qname.indexOf(":");
815
+ if (colonIndex > 0) {
816
+ return qname.substring(colonIndex + 1);
817
+ }
818
+ return qname;
819
+ }
809
820
  };
810
821
 
811
822
  // src/xpath/lib/src/expressions/predicate-expression.ts
@@ -1090,7 +1101,7 @@ var XPathFunctionCall = class extends XPathExpression {
1090
1101
  namespaceUri(args, context) {
1091
1102
  var _a;
1092
1103
  const node = this.getNodeArg(args, context);
1093
- return (_a = node == null ? void 0 : node.namespaceURI) != null ? _a : "";
1104
+ return (_a = node == null ? void 0 : node.namespaceUri) != null ? _a : "";
1094
1105
  }
1095
1106
  nodeName(args, context) {
1096
1107
  var _a;
@@ -1560,6 +1571,7 @@ var _XNode = class _XNode {
1560
1571
  this.childNodes = [];
1561
1572
  this.visited = false;
1562
1573
  this.escape = true;
1574
+ this.fromXslText = false;
1563
1575
  this.siblingPosition = -1;
1564
1576
  this.init(type, name, opt_value, opt_owner, opt_namespace);
1565
1577
  }
@@ -2086,23 +2098,32 @@ function xmlTransformedTextRecursive(node, buffer, options) {
2086
2098
  const nodeType = node.nodeType;
2087
2099
  const nodeValue = node.nodeValue;
2088
2100
  if (nodeType === DOM_TEXT_NODE) {
2089
- if (node.nodeValue && node.nodeValue.trim() !== "") {
2101
+ const isFromXslText = node.fromXslText === true;
2102
+ if (node.nodeValue && (isFromXslText || node.nodeValue.trim() !== "")) {
2090
2103
  const finalText = node.escape && options.escape ? xmlEscapeText(node.nodeValue) : xmlUnescapeText(node.nodeValue);
2091
2104
  buffer.push(finalText);
2092
2105
  }
2093
2106
  } else if (nodeType === DOM_CDATA_SECTION_NODE) {
2094
- if (options.cData) {
2107
+ if (options.outputMethod === "text") {
2108
+ buffer.push(nodeValue);
2109
+ } else if (options.cData) {
2095
2110
  buffer.push(xmlEscapeText(nodeValue));
2096
2111
  } else {
2097
2112
  buffer.push(`<![CDATA[${nodeValue}]]>`);
2098
2113
  }
2099
2114
  } else if (nodeType == DOM_COMMENT_NODE) {
2100
- buffer.push(`<!-- ${nodeValue} -->`);
2115
+ if (options.outputMethod !== "text") {
2116
+ buffer.push(`<!-- ${nodeValue} -->`);
2117
+ }
2101
2118
  } else if (nodeType == DOM_ELEMENT_NODE) {
2102
- if (node.nodeName !== null && node.nodeName !== void 0) {
2103
- xmlElementLogicTrivial(node, buffer, options);
2119
+ if (options.outputMethod === "text") {
2120
+ xmlElementLogicTextOnly(node, buffer, options);
2104
2121
  } else {
2105
- xmlElementLogicMuted(node, buffer, options);
2122
+ if (node.nodeName !== null && node.nodeName !== void 0) {
2123
+ xmlElementLogicTrivial(node, buffer, options);
2124
+ } else {
2125
+ xmlElementLogicMuted(node, buffer, options);
2126
+ }
2106
2127
  }
2107
2128
  } else if (nodeType === DOM_DOCUMENT_NODE || nodeType === DOM_DOCUMENT_FRAGMENT_NODE) {
2108
2129
  let childNodes = node.firstChild ? [] : node.childNodes;
@@ -2190,6 +2211,22 @@ function xmlElementLogicMuted(node, buffer, options) {
2190
2211
  xmlTransformedTextRecursive(childNodes[i], buffer, options);
2191
2212
  }
2192
2213
  }
2214
+ function xmlElementLogicTextOnly(node, buffer, options) {
2215
+ let childNodes = [];
2216
+ if (node.firstChild) {
2217
+ let child = node.firstChild;
2218
+ while (child) {
2219
+ childNodes.push(child);
2220
+ child = child.nextSibling;
2221
+ }
2222
+ } else {
2223
+ childNodes = node.childNodes;
2224
+ }
2225
+ childNodes = childNodes.sort((a, b) => a.siblingPosition - b.siblingPosition);
2226
+ for (let i = 0; i < childNodes.length; ++i) {
2227
+ xmlTransformedTextRecursive(childNodes[i], buffer, options);
2228
+ }
2229
+ }
2193
2230
  function xmlFullNodeName(node) {
2194
2231
  const nodeName = node.nodeName;
2195
2232
  if (node.prefix && nodeName.indexOf(`${node.prefix}:`) != 0) {
@@ -2297,6 +2334,41 @@ function nodeToJsonObject(node) {
2297
2334
  }
2298
2335
  return null;
2299
2336
  }
2337
+ function detectAdaptiveOutputFormat(node) {
2338
+ if (!node) {
2339
+ return "xml";
2340
+ }
2341
+ const nodeType = node.nodeType;
2342
+ if (nodeType === DOM_DOCUMENT_NODE || nodeType === DOM_DOCUMENT_FRAGMENT_NODE) {
2343
+ const children = node.childNodes || [];
2344
+ let elementCount = 0;
2345
+ let textCount = 0;
2346
+ let hasSignificantText = false;
2347
+ for (let i = 0; i < children.length; i++) {
2348
+ const child = children[i];
2349
+ if (child.nodeType === DOM_ELEMENT_NODE) {
2350
+ elementCount++;
2351
+ } else if (child.nodeType === DOM_TEXT_NODE) {
2352
+ const text = child.nodeValue ? child.nodeValue.trim() : "";
2353
+ if (text.length > 0) {
2354
+ textCount++;
2355
+ hasSignificantText = true;
2356
+ }
2357
+ }
2358
+ }
2359
+ if (elementCount === 0 && hasSignificantText) {
2360
+ return "text";
2361
+ }
2362
+ return "xml";
2363
+ }
2364
+ if (nodeType === DOM_TEXT_NODE || nodeType === DOM_CDATA_SECTION_NODE) {
2365
+ const text = node.nodeValue ? node.nodeValue.trim() : "";
2366
+ if (text.length > 0) {
2367
+ return "text";
2368
+ }
2369
+ }
2370
+ return "xml";
2371
+ }
2300
2372
  function xmlToJson(node) {
2301
2373
  if (!node) {
2302
2374
  return "{}";
@@ -2573,7 +2645,7 @@ var XmlParser = class {
2573
2645
  } else if (!tag && char === "<") {
2574
2646
  let text = xml.slice(start, i);
2575
2647
  if (text && parent !== root) {
2576
- domAppendChild(parent, domCreateTextNode(xmlDocument, text));
2648
+ domAppendChild(parent, domCreateTextNode(xmlDocument, import_he2.default.decode(text)));
2577
2649
  }
2578
2650
  if (xml.slice(i + 1, i + 4) === "!--") {
2579
2651
  let endTagIndex = xml.slice(i + 4).indexOf("-->");
@@ -2717,15 +2789,6 @@ var NodeConverter = class {
2717
2789
  adaptXNode(node) {
2718
2790
  if (!node) return null;
2719
2791
  const adapted = node;
2720
- if (!("namespaceURI" in adapted)) {
2721
- Object.defineProperty(adapted, "namespaceURI", {
2722
- get() {
2723
- return this.namespaceUri;
2724
- },
2725
- enumerable: true,
2726
- configurable: true
2727
- });
2728
- }
2729
2792
  if (!("textContent" in adapted)) {
2730
2793
  Object.defineProperty(adapted, "textContent", {
2731
2794
  get() {
@@ -3693,7 +3756,7 @@ var Xslt = class {
3693
3756
  * The exported entry point of the XSL-T processor.
3694
3757
  * @param xmlDoc The input document root, as DOM node.
3695
3758
  * @param stylesheet The stylesheet document root, as DOM node.
3696
- * @returns the processed document, as XML text in a string, or JSON string if outputMethod is 'json'.
3759
+ * @returns the processed document, as XML text in a string, JSON string if outputMethod is 'json', or text if outputMethod is 'text' or 'adaptive' (with text content).
3697
3760
  */
3698
3761
  xsltProcess(xmlDoc, stylesheet) {
3699
3762
  return __async(this, null, function* () {
@@ -3709,11 +3772,15 @@ var Xslt = class {
3709
3772
  if (this.outputMethod === "json") {
3710
3773
  return xmlToJson(outputDocument);
3711
3774
  }
3775
+ let outputMethod = this.outputMethod;
3776
+ if (this.outputMethod === "adaptive") {
3777
+ outputMethod = detectAdaptiveOutputFormat(outputDocument);
3778
+ }
3712
3779
  const transformedOutputXml = xmlTransformedText(outputDocument, {
3713
3780
  cData: this.options.cData,
3714
3781
  escape: this.options.escape,
3715
3782
  selfClosingTags: this.options.selfClosingTags,
3716
- outputMethod: this.outputMethod
3783
+ outputMethod
3717
3784
  });
3718
3785
  return transformedOutputXml;
3719
3786
  });
@@ -3874,6 +3941,9 @@ var Xslt = class {
3874
3941
  for (let j = 0; j < modifiedContext.contextSize(); ++j) {
3875
3942
  const currentNode = modifiedContext.nodeList[j];
3876
3943
  if (currentNode.nodeType === DOM_TEXT_NODE) {
3944
+ if (!this.xsltPassText(currentNode)) {
3945
+ continue;
3946
+ }
3877
3947
  const textNodeContext = context.clone(
3878
3948
  [currentNode],
3879
3949
  0
@@ -4642,6 +4712,7 @@ var Xslt = class {
4642
4712
  xsltText(context, template, output) {
4643
4713
  const text = xmlValue(template);
4644
4714
  const node = domCreateTextNode(this.outputDocument, text);
4715
+ node.fromXslText = true;
4645
4716
  const disableOutputEscaping = template.childNodes.filter(
4646
4717
  (a) => a.nodeType === DOM_ATTRIBUTE_NODE && a.nodeName === "disable-output-escaping"
4647
4718
  );
@@ -4649,8 +4720,80 @@ var Xslt = class {
4649
4720
  node.escape = false;
4650
4721
  }
4651
4722
  const destinationTextNode = output || this.outputDocument;
4723
+ node.siblingPosition = destinationTextNode.childNodes.length;
4652
4724
  destinationTextNode.appendChild(node);
4653
4725
  }
4726
+ /**
4727
+ * Validates XSLT stylesheet/transform attributes.
4728
+ * According to XSLT specification, validates:
4729
+ * - Required version attribute
4730
+ * - Valid version values (1.0, 2.0, 3.0)
4731
+ * - Valid namespace declarations
4732
+ * - Valid values for optional attributes (extension-element-prefixes, exclude-result-prefixes)
4733
+ * @param stylesheetElement The `<xsl:stylesheet>` or `<xsl:transform>` element to validate.
4734
+ * @param context The Expression Context for namespace access.
4735
+ */
4736
+ validateStylesheetAttributes(stylesheetElement, context) {
4737
+ const attributes = stylesheetElement.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE);
4738
+ const validAttributes = ["version", "id", "extension-element-prefixes", "exclude-result-prefixes", "default-collation"];
4739
+ const validNamespaceAttributes = ["xmlns"];
4740
+ let versionFound = false;
4741
+ for (let attribute of attributes) {
4742
+ const nodeName = attribute.nodeName;
4743
+ const nodeValue = attribute.nodeValue;
4744
+ if (attribute.prefix === "xmlns") {
4745
+ context.knownNamespaces[attribute.localName] = nodeValue;
4746
+ continue;
4747
+ }
4748
+ if (nodeName === "xmlns") {
4749
+ context.knownNamespaces[""] = nodeValue;
4750
+ continue;
4751
+ }
4752
+ if (nodeName === "version") {
4753
+ versionFound = true;
4754
+ if (!["1.0", "2.0", "3.0"].includes(nodeValue)) {
4755
+ throw new Error(
4756
+ `XSLT version not defined or invalid. Actual resolved version: ${nodeValue || "(none)"}.`
4757
+ );
4758
+ }
4759
+ this.version = nodeValue;
4760
+ context.xsltVersion = nodeValue;
4761
+ continue;
4762
+ }
4763
+ if (nodeName === "extension-element-prefixes") {
4764
+ const prefixes = nodeValue.split(/\s+/);
4765
+ for (const prefix of prefixes) {
4766
+ if (prefix && !/^[a-zA-Z_:][\w:.-]*$/.test(prefix)) {
4767
+ throw new Error(`Invalid prefix in extension-element-prefixes: "${prefix}". Prefixes must be valid QNames.`);
4768
+ }
4769
+ }
4770
+ continue;
4771
+ }
4772
+ if (nodeName === "exclude-result-prefixes") {
4773
+ if (nodeValue !== "#all") {
4774
+ const prefixes = nodeValue.split(/\s+/);
4775
+ for (const prefix of prefixes) {
4776
+ if (prefix && !/^[a-zA-Z_:][\w:.-]*$/.test(prefix)) {
4777
+ throw new Error(`Invalid prefix in exclude-result-prefixes: "${prefix}". Prefixes must be valid QNames or "#all".`);
4778
+ }
4779
+ }
4780
+ }
4781
+ continue;
4782
+ }
4783
+ if (nodeName === "default-collation") {
4784
+ if (!nodeValue || nodeValue.trim().length === 0) {
4785
+ throw new Error("The default-collation attribute must contain a URI.");
4786
+ }
4787
+ continue;
4788
+ }
4789
+ if (nodeName === "id") {
4790
+ if (!/^[a-zA-Z_:][\w:.-]*$/.test(nodeValue)) {
4791
+ throw new Error(`Invalid id attribute value: "${nodeValue}". IDs must be valid NCNames.`);
4792
+ }
4793
+ continue;
4794
+ }
4795
+ }
4796
+ }
4654
4797
  /**
4655
4798
  * Implements `<xsl:stylesheet>` and `<xsl:transform>`, and its corresponding
4656
4799
  * validations.
@@ -4661,24 +4804,7 @@ var Xslt = class {
4661
4804
  */
4662
4805
  xsltTransformOrStylesheet(context, template, output) {
4663
4806
  return __async(this, null, function* () {
4664
- for (let stylesheetAttribute of template.childNodes.filter((n) => n.nodeType === DOM_ATTRIBUTE_NODE)) {
4665
- switch (stylesheetAttribute.nodeName) {
4666
- case "version":
4667
- this.version = stylesheetAttribute.nodeValue;
4668
- if (!["1.0", "2.0", "3.0"].includes(this.version)) {
4669
- throw new Error(
4670
- `XSLT version not defined or invalid. Actual resolved version: ${this.version || "(none)"}.`
4671
- );
4672
- }
4673
- context.xsltVersion = this.version;
4674
- break;
4675
- default:
4676
- if (stylesheetAttribute.prefix === "xmlns") {
4677
- context.knownNamespaces[stylesheetAttribute.localName] = stylesheetAttribute.nodeValue;
4678
- }
4679
- break;
4680
- }
4681
- }
4807
+ this.validateStylesheetAttributes(template, context);
4682
4808
  let importsDone = false;
4683
4809
  for (const child of template.childNodes) {
4684
4810
  if (child.nodeType === DOM_ELEMENT_NODE) {
@@ -4718,16 +4844,22 @@ var Xslt = class {
4718
4844
  }
4719
4845
  }
4720
4846
  if (matchCandidates.length > 0) {
4721
- matchCandidates.sort((a, b) => {
4722
- if (a.priority.importPrecedence !== b.priority.importPrecedence) {
4723
- return b.priority.importPrecedence - a.priority.importPrecedence;
4724
- }
4725
- if (a.priority.effectivePriority !== b.priority.effectivePriority) {
4726
- return b.priority.effectivePriority - a.priority.effectivePriority;
4727
- }
4728
- return b.priority.documentOrder - a.priority.documentOrder;
4729
- });
4730
- const winner = matchCandidates[0];
4847
+ const rootPatternMatch = matchCandidates.find((c) => c.priority.matchPattern === "/");
4848
+ let winner;
4849
+ if (rootPatternMatch) {
4850
+ winner = rootPatternMatch;
4851
+ } else {
4852
+ matchCandidates.sort((a, b) => {
4853
+ if (a.priority.importPrecedence !== b.priority.importPrecedence) {
4854
+ return b.priority.importPrecedence - a.priority.importPrecedence;
4855
+ }
4856
+ if (a.priority.effectivePriority !== b.priority.effectivePriority) {
4857
+ return b.priority.effectivePriority - a.priority.effectivePriority;
4858
+ }
4859
+ return b.priority.documentOrder - a.priority.documentOrder;
4860
+ });
4861
+ winner = matchCandidates[0];
4862
+ }
4731
4863
  const conflicts = matchCandidates.filter(
4732
4864
  (t) => t.priority.importPrecedence === winner.priority.importPrecedence && t.priority.effectivePriority === winner.priority.effectivePriority
4733
4865
  );
@@ -4865,7 +4997,11 @@ var Xslt = class {
4865
4997
  return __async(this, null, function* () {
4866
4998
  const contextClone = context.clone();
4867
4999
  for (let i = 0; i < template.childNodes.length; ++i) {
4868
- yield this.xsltProcessContext(contextClone, template.childNodes[i], output);
5000
+ const child = template.childNodes[i];
5001
+ if (child.nodeType === DOM_ATTRIBUTE_NODE) {
5002
+ continue;
5003
+ }
5004
+ yield this.xsltProcessContext(contextClone, child, output);
4869
5005
  }
4870
5006
  });
4871
5007
  }