使用jQuery转换插件在Google Chrome上使用xsl:include和xsl:param

时间:2010-09-06 18:45:19

标签: jquery xslt jquery-plugins google-chrome

我一直在尝试将XSL与谷歌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模板中使用默认包含,这包括使用传递给顶级模板的参数。

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

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

3 个答案:

答案 0 :(得分: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. 创建/查找解决此问题的黑客行为,例如通过模拟Chrome / Webkit xsl:include(可能需要大量工作/开发黑客攻击)
  3. 尝试找到一种不需要这种特定XSL功能的方式编写软件的方法(或者在服务器端运行XSL转换)
  4. 我的建议:避免在客户端使用xsl:include with xsl:param,除非您愿意放弃跨浏览器兼容性

答案 1 :(得分:1)

我知道的旧话题,但请回到此处查看问题是否已解决。

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

答案 2 :(得分:0)

这很痛苦,但您也可以使用客户端垫片来解决这个问题,该垫片会在浏览器中预加载任何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<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;
    }
}

}