Google Chrome上的xsl:include和xsl:param,带有jQuery转换插件

我一直在尝试将XSL与谷歌Chrome一起使用,但没有成功。
我读到Chrome有一些XSLT漏洞,其中一个是它不支持xsl:include。 可以在此处检查错误: http : //code.google.com/p/chromium/issues/detail?id = 8441 。
经过一些研究后,我发现了Daer System的转换插件的新版本,它使xsl:include在Chrome上工作。

可以从http://plugins.jquery.com/project/Transform找到jQuery Transform插件

现在我的问题是:
我在一些xsl模板中使用默认包含,这包括使用传递给顶级模板的参数。

所以就像我有top.xsl模板声明一个[xsl:param name =“param”/],我使用这个param与included.xsl ,由第一个调用[xsl:include href = “included.xsl”]。 这适用于Firefox和Internet Explorer,但不适用于Chrome。 我在stackoverflow上看到一个问题,其中一些人从插件重写了webkit修复函数,但它不能用xsl:param这样工作。

有谁知道在谷歌浏览器中使用[xsl:param]这样的方法吗?

您的问题是Google Chrome(= Chromium)不支持xsl:include

Chromium项目中缺少此function,如“问题8441:JS中的XSLTProcessor不允许xsl:include for http”所述 。 似乎问题是由WebKit(Chrome中使用的渲染引擎)中的一些架构问题引起的。 由于此问题源自WebKit,因此该错误被标记为WontFix – 随着WebKit中的原始问题得到解决,将来会提供修复(希望如此)。

我看到了如何解决这个问题的三种可能的替代方案:

  1. 等到WebKit / Chrome获得修复此问题的补丁(可能需要很长时间……)
  2. 创建/找到解决此问题的hack,例如通过以某种方式模拟xsl:include for Chrome / Webkit (可能需要大量工作/开发hack)
  3. 尝试找到一种以不需要此特定XSLfunction的方式编写软件的方法(或者在服务器端运行XSL转换)

我的建议:避免在客户端使用xsl:include with xsl:param,除非你愿意放弃跨浏览器的兼容性

我知道的老话题,但回过头来查看问题是否已经解决。

我再次测试它,至少在Chrome的第47版中。 最后你可以使用xsl:include。

这很痛苦,但您也可以使用客户端垫片来解决这个问题,该垫片在浏览器中预加载任何xsl:import / xsl:includes。

以下是TypeScript(基本上是静态类型的JavaScript,编译成JavaScript),并且有一些参考接口……我没有去除,但它似乎在Chrome中工作(不确定其他浏览器),应该是足以让任何人开始解决方案。

 module DD.Render.DOM.XSLT { export class StandardXSLTDOMTransformerFactory implements IXSLTDOMTransformerFactory { constructor(private _domParser:DOMParser, private _document:Document) { } createTransformerFromPath(xslPath: string, xmlTransformer: IStringTransformer, onSuccess: (transformer: IParameterizedDOMTransformer) => void, onFailure: (e: any) => void): void { DD.Util.readXML( xslPath, (node: Node) => { // look up any xsl:import or xsl:includes and pull those in too! var onIncludesPreloaded = () => { console.log(node); var transformer = this.createTransformerFromNode(node, xmlTransformer); onSuccess(transformer); }; this.rewriteIncludes(xslPath, node, {}, onIncludesPreloaded, onFailure); }, function (e: any) { onFailure(e); } ); } rewriteIncludes(path:string, node: Node, imported: { [_: string]: boolean }, onRewritten:()=>void, onFailure:(e:any)=>void): void { var result; var element = node; var importNodes = element.querySelectorAll("import,include"); if (importNodes.length == 0) { onRewritten(); result = false; } else { var rewrittenNodes = 0; // load imports for (var i = 0; i < importNodes.length; i++) { var importElement = importNodes.item(i); var href = importElement.getAttribute("href"); // TODO work out relative path var relativePath = DD.Util.appendRelativePath(path, href); console.log("importing " + href +" + "+path+" -> "+relativePath); if (!imported[relativePath]) { var e = importElement; imported[relativePath] = true; DD.Util.readXML(relativePath, (importedStylesheet: Node) => { this.rewriteIncludes(relativePath, importedStylesheet, imported, function () { // replace the import with this node (minus stylesheet container) for (var j = 0; j < importedStylesheet.firstChild.childNodes.length; j++) { var templateNode = importedStylesheet.firstChild.childNodes.item(j); if (templateNode.nodeName.indexOf("template") >= 0) { e.parentNode.insertBefore(templateNode, e); } } e.parentNode.removeChild(e); rewrittenNodes++; if (rewrittenNodes == importNodes.length) { if (onRewritten) { onRewritten(); } } }, onFailure); }, onFailure); } else { importElement.parentNode.removeChild(importElement); } } result = true; } return result; } createTransformerFromNode(xsl: Node, xmlTransformer: IStringTransformer): IParameterizedDOMTransformer { var nodeTransformer = new DOMParserDOMTransformer(this._domParser, xmlTransformer); var xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xsl); return new StandardXSLTDOMTransformer(xsltProcessor, nodeTransformer, this._document); } } } module DD.Util { export function readXML(path: string, onSuccess: (node: Node) => void, onFailure: (e: any) => void) { var xhr = new XMLHttpRequest(); xhr.onload = function () { onSuccess(xhr.responseXML); }; xhr.onerror = function (e: ErrorEvent) { onFailure(e); }; xhr.open("GET", path, true); xhr.send(null); } export function appendRelativePath(originalPath: string, relativePath: string, originalPathIsDirectory?: boolean) { if (originalPathIsDirectory == null) { originalPathIsDirectory = originalPath.charAt(originalPath.length - 1) == '/'; } if (!originalPathIsDirectory) { // remove file imediately var lastSlash = originalPath.lastIndexOf('/'); if (lastSlash >= 0) { originalPath = originalPath.substring(0, lastSlash + 1); } else { originalPath = ""; } } var slashIndex = relativePath.indexOf('/'); if (slashIndex >= 0) { var relativeDirectory = relativePath.substring(0, slashIndex + 1); var relativeRemainder = relativePath.substring(slashIndex + 1); if (relativeDirectory == "../") { // trim off a directory on the original path if (originalPath.charAt(originalPath.length - 1) == '/') { originalPath = originalPath.substring(0, originalPath.length - 1); } var dirIndex = originalPath.lastIndexOf('/'); if (dirIndex >= 0) { originalPath = originalPath.substring(0, dirIndex + 1); } else { originalPath = ""; } } else { // append to the original path if (originalPath.charAt(originalPath.length - 1) != '/') { originalPath += '/'; } originalPath += relativeDirectory; } appendRelativePath(originalPath, relativeRemainder, true); } else { // append and be done if (originalPath.charAt(originalPath.length - 1) != '/') { originalPath += '/'; } return originalPath + relativePath; } } }