XSLTProcessor

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

XSLTProcessor 会将 XSLT 样式表转换应用于 XML 文档,并生成一个新的 XML 文档作为输出。它提供了加载 XSLT 样式表、操作 <xsl:param> 参数值以及将转换应用于文档的方法。

构造函数

XSLTProcessor()

创建一个新的 XSLTProcessor

实例方法

XSLTProcessor.importStylesheet()

导入 XSLT 样式表。如果提供的节点是文档节点,您可以传入一个完整的 XSL 转换或一个 字面量结果元素转换;否则,它必须是 <xsl:stylesheet><xsl:transform> 元素。

XSLTProcessor.transformToFragment()

通过应用使用 XSLTProcessor.importStylesheet() 函数导入的 XSLT 样式表来转换源节点。生成的文档片段的所有者文档是源节点。

XSLTProcessor.transformToDocument()

通过应用使用 XSLTProcessor.importStylesheet() 函数导入的 XSLT 样式表来转换源节点。

XSLTProcessor.setParameter()

设置已导入的 XSLT 样式表中的参数(<xsl:param>)值。

XSLTProcessor.getParameter()

从 XSLT 样式表中获取参数的值。

XSLTProcessor.removeParameter()

如果参数之前已设置,则移除该参数。这将使 XSLTProcessor 使用 XSLT 样式表中指定的参数的默认值。

XSLTProcessor.clearParameters()

XSLTProcessor 中移除所有已设置的参数。XSLTProcessor 随后将使用 XSLT 样式表中指定的默认值。

XSLTProcessor.reset()

XSLTProcessor 中移除所有参数和样式表。

实例属性

此接口没有属性。

示例

实例化 XSLTProcessor

js
async function init() {
  const parser = new DOMParser();
  const xsltProcessor = new XSLTProcessor();

  // Load the XSLT file, example1.xsl
  const xslResponse = await fetch("example1.xsl");
  const xslText = await xslResponse.text();
  const xslStylesheet = parser.parseFromString(xslText, "application/xml");
  xsltProcessor.importStylesheet(xslStylesheet);

  // process the file
  // …
}

基于文档 DOM 的一部分创建 XML 文档

对于实际转换,XSLTProcessor 需要一个 XML 文档,该文档与导入的 XSL 文件结合使用以生成最终结果。XML 文档可以是使用 fetch() 加载的独立 XML 文件,也可以是现有页面的一部分。

要处理页面 DOM 的一部分,必须首先在内存中创建一个 XML 文档。假设要处理的 DOM 包含在一个 ID 为 example 的元素中,可以使用内存中 XML 文档的 Document.importNode() 方法来“克隆”该 DOM。 Document.importNode() 允许在文档之间传输 DOM 片段,在本例中是从 HTML 文档传输到 XML 文档。第一个参数引用要克隆的 DOM 节点。将第二个参数设置为“true”将克隆所有后代节点(深层克隆)。然后,可以使用 Node.appendChild() 将克隆的 DOM 插入到 XML 文档中,如下所示。

js
// Create a new XML document in memory
const xmlRef = document.implementation.createDocument("", "", null);

// We want to move a part of the DOM from an HTML document to an XML document.
// importNode is used to clone the nodes we want to process via XSLT - true makes it do a deep clone
const myNode = document.getElementById("example");
const clonedNode = xmlRef.importNode(myNode, true);

// Add the cloned DOM into the XML document
xmlRef.appendChild(clonedNode);

导入样式表后,XSLTProcessor 必须执行两个方法才能进行实际转换,即 XSLTProcessor.transformToDocument()XSLTProcessor.transformToFragment()XSLTProcessor.transformToDocument() 返回一个完整的 XML 文档,而 XSLTProcessor.transformToFragment() 返回一个文档片段,该片段可以轻松地添加到现有文档中。两者都将要转换的 XML 文档作为第一个参数。 XSLTProcessor.transformToFragment() 需要第二个参数,即生成片段的所有者文档对象。如果生成的片段将插入到当前 HTML 文档中,则传递 document 就足够了。

从字符串“XML Soup”创建 XML 文档

您可以使用 DOMParser 从 XML 字符串创建 XML 文档。

js
const parser = new DOMParser();
const doc = parser.parseFromString(str, "text/xml");

执行转换

js
const fragment = xsltProcessor.transformToFragment(xmlRef, document);

基本示例

基本示例将加载一个 XML 文件并对其应用 XSL 转换。这些是与 生成 HTML 示例中使用的相同文件。XML 文件描述了一篇文章,XSL 文件格式化信息以便显示。

XML

xml
<?xml version="1.0"?>
<myNS:Article xmlns:myNS="http://devedge.netscape.com/2002/de">
  <myNS:Title>My Article</myNS:Title>
  <myNS:Authors>
    <myNS:Author company="Foopy Corp.">Mr. Foo</myNS:Author>
    <myNS:Author>Mr. Bar</myNS:Author>
  </myNS:Authors>
  <myNS:Body>
    The <b>rain</b> in <u>Spain</u> stays mainly in the plains.
  </myNS:Body>
</myNS:Article>

XSLT

xml
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:myNS="http://devedge.netscape.com/2002/de">

  <xsl:output method="html" />

  <xsl:template match="/">
    <html>

      <head>

        <title>
          <xsl:value-of select="/myNS:Article/myNS:Title"/>
        </title>

        <style>
          .myBox {margin:10px 155px 0 50px; border: 1px dotted #639ACE; padding:0 5px 0 5px;}
        </style>

      </head>

      <body>
        <p class="myBox">
          <span class="title">
            <xsl:value-of select="/myNS:Article/myNS:Title"/>
          </span> <br />

          Authors:   <br />
            <xsl:apply-templates select="/myNS:Article/myNS:Authors/myNS:Author"/>
          </p>

        <p class="myBox">
          <xsl:apply-templates select="//myNS:Body"/>
        </p>

      </body>

    </html>
  </xsl:template>

  <xsl:template match="myNS:Author">
     --   <xsl:value-of select="." />

    <xsl:if test="@company">
     ::   <b>  <xsl:value-of select="@company" />  </b>
    </xsl:if>

    <br />
  </xsl:template>

  <xsl:template match="myNS:Body">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

该示例将 .xsl (xslStylesheet) 和 .xml (xmlDoc) 文件加载到内存中。然后导入 .xsl 文件 (xsltProcessor.importStylesheet(xslStylesheet)) 并运行转换 (xsltProcessor.transformToFragment(xmlDoc, document))。这允许在页面加载后获取数据,而无需重新加载页面。

JavaScript

js
async function init() {
  const parser = new DOMParser();
  const xsltProcessor = new XSLTProcessor();

  // Load the XSLT file, example1.xsl
  const xslResponse = await fetch("example1.xsl");
  const xslText = await xslResponse.text();
  const xslStylesheet = parser.parseFromString(xslText, "application/xml");
  xsltProcessor.importStylesheet(xslStylesheet);

  // Load the XML file, example1.xml
  const xmlResponse = await fetch("example1.xml");
  const xmlText = await xmlResponse.text();
  const xmlDoc = parser.parseFromString(xmlText, "application/xml");

  const fragment = xsltProcessor.transformToFragment(xmlDoc, document);

  document.getElementById("example").textContent = "";
  document.getElementById("example").appendChild(fragment);
}

init();

高级示例

这个高级示例根据内容对多个 div 进行排序。该示例允许多次排序内容,并在升序和降序之间交替。JavaScript 仅在第一次排序时加载 .xsl 文件,并在文件加载完成后将 xslLoaded 变量设置为 true。使用 XSLTProcessor.getParameter() 方法,代码可以确定是升序还是降序排序。如果参数为空(首次排序时,因为 XSLT 文件中没有该参数的值),则默认为升序。排序值使用 XSLTProcessor.setParameter() 设置。

XSLT 文件中有一个名为 myOrder 的参数,JavaScript 会设置它来更改排序方法。xsl:sort 元素的 order 属性可以使用 $myOrder 访问参数的值。但是,该值需要是 XPath 表达式而不是字符串,因此使用 {$myOrder}。使用 {} 会将内容评估为 XPath 表达式。

转换完成后,结果会追加到文档中,如本示例所示。

XHTML

html
<div id="example">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
</div>

JavaScript

js
let xslRef;
let xslLoaded = false;
const parser = new DOMParser();
const xsltProcessor = new XSLTProcessor();
let myDOM;

let xmlRef = document.implementation.createDocument("", "", null);

async function sort() {
  if (!xslLoaded) {
    const response = await fetch("example2.xsl");
    const xslText = await response.text();
    xslRef = parser.parseFromString(xslText, "application/xml");
    xsltProcessor.importStylesheet(xslRef);
    xslLoaded = true;
  }

  // Create a new XML document in memory
  xmlRef = document.implementation.createDocument("", "", null);

  // We want to move a part of the DOM from an HTML document to an XML document.
  // importNode is used to clone the nodes we want to process via XSLT - true makes it do a deep clone
  const myNode = document.getElementById("example");
  const clonedNode = xmlRef.importNode(myNode, true);

  // After cloning, we append
  xmlRef.appendChild(clonedNode);

  // Set the sorting parameter in the XSL file
  const sortVal = xsltProcessor.getParameter(null, "myOrder");

  if (sortVal === "" || sortVal === "descending") {
    xsltProcessor.setParameter(null, "myOrder", "ascending");
  } else {
    xsltProcessor.setParameter(null, "myOrder", "descending");
  }

  // Initiate the transformation
  const fragment = xsltProcessor.transformToFragment(xmlRef, document);

  // Clear the contents
  document.getElementById("example").textContent = "";

  myDOM = fragment;

  // Add the new content from the transformation
  document.getElementById("example").appendChild(fragment);
}

XSLT

xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

  <xsl:param name="myOrder" />

  <xsl:template match="/">

    <xsl:apply-templates select="/div//div">
      <xsl:sort select="." data-type="number" order="{$myOrder}" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="div">
    <xsl:copy-of select="." />
  </xsl:template>
</xsl:stylesheet>

规范

规范
DOM
# interface-xsltprocessor

浏览器兼容性

另见