【问题标题】:xsl:include and xsl:param at Google Chrome, with jQuery transform pluginGoogle Chrome 中的 xsl:include 和 xsl:param,带有 jQ​​uery 转换插件
【发布时间】:2010-09-06 18:45:18
【问题描述】:

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

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

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

就像我有一个声明 [xsl:param name="param" /] 的 top.xsl 模板,我将此参数与 included.xsl,由第一个使用 [xsl:include href="included.xsl"] 调用。这适用于 Firefox 和 Internet Explorer,但不适用于 Chrome。我在 stackoverflow 上看到了一个问题,有人从插件中重新编写了 webkit 修复功能,但它不适用于 xsl:param 这种方式。

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

【问题讨论】:

  • 看起来只有在通过 javascript 运行转换时才如此。如您所见,我的 XML/XSLT 驱动站点工作正常:www.aranedabienesraices.com.ar
  • 嗨 Alejandro,是的,这是通过 javascript 转换实现的。我需要通过 javascript 来做到这一点。
  • user357812:请解释一下:这个链接与这个问题有什么关系?

标签: jquery xslt jquery-plugins google-chrome


【解决方案1】:

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

"Issue 8441: XSLTProcessor in JS does not permit xsl:include for http" 中提出的 Chromium 项目中已明确指出缺少此功能。似乎该问题是由 WebKit(Chrome 中使用的渲染引擎)中的一些架构问题引起的。由于此问题源于 WebKit,因此该错误被标记为 WontFix - 随着 WebKit 中的原始问题得到解决,将来会(希望)提供修复。

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

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

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

【讨论】:

  • 嗨 jsalonen,感谢您的回答。由于问题来自 2010 年 9 月,我设法通过“重新编译”xsl 页面来解决这个问题。当我在服务器端使用 .net 时,我制作了一个脚本来删除 xsl:include 并将 xsl 包含文件连接到调用它的文件中。我很确定它可以用 javascript 解决这个问题,但正如你所说,要管理它需要大量的工作和大量的代码。所以我只是在服务器上这样做,使我仍然可以重用 xsl:templates 编辑原始文件,以及读取服务器生成 xsl 文件的 javascript。
【解决方案2】:

我知道旧话题,但回来查看问题是否已解决。

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

【讨论】:

    【解决方案3】:

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

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

    module DD.Render.DOM.XSLT {
    
    export class StandardXSLTDOMTransformerFactory implements IXSLTDOMTransformerFactory {
    
        constructor(private _domParser:DOMParser, private _document:Document) {
        }
    
        createTransformerFromPath<T>(xslPath: string, xmlTransformer: IStringTransformer<T>, onSuccess: (transformer: IParameterizedDOMTransformer<T>) => 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 = <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 = <Element>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<T>(xsl: Node, xmlTransformer: IStringTransformer<T>): IParameterizedDOMTransformer<T> {
            var nodeTransformer = new DOMParserDOMTransformer(this._domParser, xmlTransformer);
            var xsltProcessor = new XSLTProcessor();
            xsltProcessor.importStylesheet(xsl);
            return new StandardXSLTDOMTransformer<T>(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;
        }
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-23
      • 2012-03-06
      • 1970-01-01
      • 2014-09-02
      • 1970-01-01
      • 2012-07-02
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多