【问题标题】:Load XML and XSL from variables and transform in the browser从变量加载 XML 和 XSL 并在浏览器中转换
【发布时间】:2018-05-15 12:59:15
【问题描述】:

下面的代码 sn-p 是对我遇到的问题的最小重现。目的是通过 XSL 转换 XML 并将结果转换为变量。

注释行发生错误。我做错了什么?

更大的图景是,我希望能够在浏览器中拥有 XML 文件的 URL 和 XSL 文件的 URL,并使用 XSL 转换 XML。我已经从服务器管道中加载了所有文件,但是我收到了这个错误,并且在 Google 中找不到可以理解的答案。自 2014 年左右以来,客户端的 XML 转换似乎很少受到关注,所以我想知道是否有更现代的技术或插件。

我很乐意接受纯 JS 或 jquery 答案或插件。

我知道这个最小的示例不是跨浏览器(没有针对 IE 风格的解决方案),但我应该说我确实需要一个跨浏览器解决方案作为最终答案。

最后,我知道你可以在服务器上进行转换,这不在规范中。

这是来自控制台的错误和问题。

err=TypeError: 无法执行“importStylesheet” “XSLTProcessor”:参数 1 不是“节点”类型。

错误:{“消息”: “未捕获的类型错误:无法执行‘transformToFragment’ 'XSLTProcessor': 参数 1 不是'Node' 类型。", "filename": "https://stacksnippets.net/js", "lineno": 26, "colno": 32 }

这是导致错误的代码。

var xsltProcessor, resultDocument, xml, xsl;

var xml = '<?xml version="1.0" encoding="UTF-8"?><catalog><cd><title>Empire Burlesque</title></cd></catalog>';
var xsl = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/">  <h2>My CD Collection</h2>  <table border="1">    <tr bgcolor="#9acd32">      <th style="text-align:left">Title</th>      <th style="text-align:left">Artist</th>    </tr>    <xsl:for-each select="catalog/cd">    <tr>      <td><xsl:value-of select="title" /></td>    </tr>    </xsl:for-each>  </table></xsl:template></xsl:stylesheet>'


xsltProcessor = new XSLTProcessor();
try {
  xsltProcessor.importStylesheet(xsl);  // < error here !
} catch (error) {
  console.log('err=' + error);
}
resultDocument = xsltProcessor.transformToFragment(xml, document);

console.log(resultDocument);

【问题讨论】:

  • 如果你说你有“更大的图景是我希望能够在浏览器中拥有 XML 文件的 URL 和 XSL 文件的 URL,并转换XML with the XSL" 那么我不明白你为什么要使用带有 XML 或 XSLT 的 sn-p 作为 Javascript 字符串。如果您有 URL 并使用 XMLHttpRequest 加载它们,那么它有一个 XML DOM 文档类型的 responseXML,然后您可以将 importStylesheet 分别用作 transformToFragment 的第一个参数。
  • 如果您想从同一服务器加载 XSLT 和 XML,因为 Javascript 来自同一服务器,请参阅 github.com/martin-honnen/martin-honnen.github.io/blob/master/… 以获取直接使用 XMLHttpRequest 的 responseXML 的示例。
  • 很好的例子@MartinHonnen - 就像 xml 和 xsl 文件的 promise.all / 加载过程。我敦促读者看看这种风格。我可能会借一些。我已经有负载工作了,但是谢谢。关于您之前的评论-是的,我可以将它们加载为 application/xml 类型,但这是一种解决方法,而不是修复方法-假设某些 xml 是在本地计算的,例如,作为字符串。

标签: xml xslt client


【解决方案1】:

回答这部分问题:

客户端的 XML 转换似乎没有什么重点 从 2014 年左右开始,所以我想知道是否有更现代的 技术或插件。

我想说,自 2004 年左右以来,浏览器供应商就很少关注它。

但是,如果您想要更现代的东西,可以使用 Saxon-JS,它是 XSLT 3.0 的纯 Javascript 实现。它不仅支持 3.0 标准,还具有使其具有交互性的扩展,因此您可以直接在 XSLT 代码中处理用户输入事件。详情在http://www.saxonica.com/saxon-js/index.xml

免责声明:Saxon-JS 由我的公司 Saxonica 生产。

【讨论】:

  • 感谢您的意见。免责声明。
【解决方案2】:

我找到了自己的答案,所以我发帖以防将来对其他人有所帮助。解决方案的关键是使用 DomParser 将 XML 和 XSL 从其字符串形式解析为文档。

灵感来自这个 SO 问题Workaround for xml data islands ,这导致了这个MDN article about Using XML Data Islands in Mozilla,他们在其中解释了一种解决方法,他们做了类似于加载 HTML5 '数据块'的事情。

注意:如果您查看您的开发控制台,您可能会看到很多与 DOM 异常和跨域相关的错误。看起来这段代码不适用于 SO sn-p 机器,但如果您将其作为脚本块剪切并粘贴到自己的 html 中,它运行良好,会在控制台中生成令人愉悦的“#document-fragment”。

var xsltProcessor, resultDocument, xml, xsl;

var xml = '<?xml version="1.0" encoding="UTF-8"?><catalog><cd><title>Empire Burlesque</title></cd></catalog>';
var xsl = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/">    <xsl:for-each select="catalog/cd">      <xsl:value-of select="title" />    </xsl:for-each></xsl:template></xsl:stylesheet>';

// Secret sauce start. 
var parser = new DOMParser();
var xsl_doc = parser.parseFromString(xsl, "application/xml");
var xml_doc = parser.parseFromString(xml, "application/xml");
// end of secret sauce.

xsltProcessor = new XSLTProcessor();
try {
  xsltProcessor.importStylesheet(xsl_doc);
} catch (error) {
  console.log('err=' + error);
}
resultDocument = xsltProcessor.transformToFragment(xml_doc, document);

console.log(resultDocument);

【讨论】:

    猜你喜欢
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 2016-02-12
    • 1970-01-01
    相关资源
    最近更新 更多