使用 JavaScript 的 Chrome 和 Safari XSLT

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2042178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:32:13  来源:igfitidea点击:

Chrome and Safari XSLT using JavaScript

javascriptjqueryxsltsafarigoogle-chrome

提问by Rupert

I have the following code that applies a XSLT style

我有以下应用 XSLT 样式的代码

Test.Xml.xslTransform = function(xml, xsl) {
    try {
        // code for IE
        if (window.ActiveXObject) {
            ex = xml.transformNode(xsl);
            return ex;
        }
        // code for Mozilla, Firefox, Opera, etc.
        else if (document.implementation && document.implementation.createDocument) {
            xsltProcessor = new XSLTProcessor();
            xsltProcessor.importStylesheet(xsl);
            resultDocument = xsltProcessor.transformToFragment(xml, document);
            return resultDocument;
        }
    } catch (exception) {
        if (typeof (exception) == "object") {
            if (exception.message) {
                alert(exception.message);
            }
        } else {
            alert(exception);
        }
    }

The code is working in IE and firefox but not in Chrome and Safari. Any ideas why?

该代码在 IE 和 firefox 中有效,但在 Chrome 和 Safari 中无效。任何想法为什么?

Update

更新

ResultDocument = xsltProcessor.transformToFragment(xml, document);

The line above is returning null. No error is being thrown.

上面的行返回 null。没有错误被抛出。

Update

更新

The code is not working as the xslt file contains xsl:include. Need to find a way to get the include working I will paste progress here

该代码不起作用,因为 xslt 文件包含 xsl:include。需要找到一种方法来使包含工作,我将在此处粘贴进度

Update

更新

It has been recomended that I use the http://plugins.jquery.com/project/Transform/plugin. I am trying to use the client side libary as the example of include works here (http://daersystems.com/jquery/transform/).

建议我使用http://plugins.jquery.com/project/Transform/插件。我正在尝试使用客户端库作为包含工作的示例(http://daersystems.com/jquery/transform/)。

The code works in IE but still not in chrome.

该代码在 IE 中有效,但在 chrome 中仍然无效。

Test.Xml.xslTransform = function(xml, xsl) {
        try {
                $("body").append("<div id='test' style='display:none;'></div>");
                var a = $("#test").transform({ xmlobj: xml, xslobj: xsl });
                return a.html();
        }
        catch (exception) {
            if (typeof (exception) == "object") {
                if (exception.message) {
                    alert(exception.message);
                }
            } else {
                alert(exception);
            }

        }
    }

xml and xsl are both objects being passed in.

xml 和 xsl 都是传入的对象。

Update

更新

I tried changing the XSL file to being something very simple with no include and Chrome is still not applying the stylesheet and IE is. The XSL that is being brought in as an object is:

我尝试将 XSL 文件更改为没有包含的非常简单的文件,但 Chrome 仍然没有应用样式表,而 IE 是。作为对象引入的 XSL 是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:rs="urn:schemas-microsoft-com:rowset"
    xmlns:z="#RowsetSchema"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:spsoap="http://schemas.microsoft.com/sharepoint/soap/"
    >
    <xsl:output method="html"/>
    <xsl:template match="/">
        <h1>test</h1>
    </xsl:template>

</xsl:stylesheet>

Update

更新

The end result that I want is for the xsl to be applied to the xml file. The xsl file has in it includes. I want the trasnfer to happen on the client ideally.

我想要的最终结果是将 xsl 应用于 xml 文件。xsl 文件包含在其中。我希望理想情况下传输发生在客户端上。

UpdatedRupert could you update the question with the xml and how you're calling Test.Xml.xslTransform ?

更新的Rupert 你能用 xml 更新问题以及你如何调用 Test.Xml.xslTransform 吗?

I got the xml using ie8

我使用 ie8 得到了 xml

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SearchListItemsResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/"><SearchListItemsResult><listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
                    <rs:data ItemCount="1">
                        <z:row ows_Title="Test" ows_FirstName="Test 4" ows_UniqueId="74;#{1A16CF3E-524D-4DEF-BE36-68A964CC24DF}" ows_FSObjType="74;#0" ows_MetaInfo="74;#" ows_ID="74" ows_owshiddenversion="10" ows_Created="2009-12-29 12:21:01" ows_FileRef="74;#Lists/My List Name/74_.000" ReadOnly="False" VerificationRequired="0"/>
                    </rs:data>
                </listitems></SearchListItemsResult></SearchListItemsResponse></soap:Body></soap:Envelope>

The code is being called as follows:

代码被调用如下:

xsl = Test.Xml.loadXMLDoc("/_layouts/xsl/xsl.xslt");
var doc = Test.Xml.xslTransform(xData.responseXML, xsl);

xData is the xml returned by a web service.

xData 是 Web 服务返回的 xml。

回答by Martijn Laarman

If your XSLT is using xsl:includeyou might receive weird unexplainable errors but always with the same end result: your transformation failing.

如果您的 XSLT 正在使用,xsl:include您可能会收到奇怪的无法解释的错误,但最终结果总是相同:您的转换失败。

See this chromium bug report and please support it! http://code.google.com/p/chromium/issues/detail?id=8441

看到这个铬错误报告,请支持它! http://code.google.com/p/chromium/issues/detail?id=8441

The bug is actually in webkit though. For more info here'sanother link which goes into more detail why it doesn't work.

该错误实际上在 webkit 中。有关更多信息,请访问另一个链接,其中详细介绍了为什么它不起作用。

The only way around this is to pre-process the stylesheet so that it injects the included stylesheets. Which is what a crossbrowser XSLT library like Sarissa will do for you automatically.

解决这个问题的唯一方法是预处理样式表,以便它注入包含的样式表。这就是像 Sarissa 这样的跨浏览器 XSLT 库会自动为您做的事情。

If your looking for jQuery solution:
http://plugins.jquery.com/project/Transform/is a cross browser XSL plug-in. I've succesfully used this to get xsl:includeworking in the past without much hassle. You don't have to rewrite your xsl's this plugin will pre-process them for you. Definitely worth looking at as it's more lightweight then Sarissa.

如果您正在寻找 jQuery 解决方案:
http: //plugins.jquery.com/project/Transform/是一个跨浏览器的 XSL 插件。我已经成功地使用它xsl:include在过去工作而没有太多麻烦。你不必重写你的 xsl,这个插件会为你预处理它们。绝对值得一看,因为它比 Sarissa 更轻巧。

UPDATE:

更新:

<html>
<head>
<script language="javascript" src="jquery-1.3.2.min.js"></script> 
<script language="javascript" src="jquery.transform.js"></script>  
<script type="text/javascript">
function loadXML(file)
{
    var xmlDoc = null;
    try //Internet Explorer
    {
        xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async=false;
        xmlDoc.load(file);
    }
    catch(e)
    {
        try //Firefox, Mozilla, Opera, etc.
        {
            xmlDoc=document.implementation.createDocument("","",null);
            xmlDoc.async=false;
            xmlDoc.load(file);
        }
        catch(e)
        {
            try //Google Chrome
            {
                var xmlhttp = new window.XMLHttpRequest();
                xmlhttp.open("GET",file,false);
                xmlhttp.send(null);
                xmlDoc = xmlhttp.responseXML.documentElement;
            }
            catch(e)
            {
            error=e.message;
            }
        }
    }
    return xmlDoc;
}
function xslTransform(xmlObject, xslObject)
{
    try 
    {
        $("body").append("<div id='test'></div>");
        var a = $("#test").transform({ xmlobj: xmlObject, xslobj: xslObject });
    }
    catch (exception) 
    {
        if (typeof (exception) == "object" && exception.message) 
            alert(exception.message);
        else alert(exception);
    }
}
var xmlObject = loadXML("input.xml");
var xslObject = loadXML("transform.xsl");
$(document).ready(function()  
{
    xslTransform(xmlObject, xslObject);
});
</script>
</head>
<body>

</body>
</html>

This test html page works both in Chrome/FireFox/IE.

此测试 html 页面在 Chrome/FireFox/IE 中均可使用。

input.xml is just a simple xml file containing <root />transform.xsl is the stripped down xsl you posted.

input.xml 只是一个简单的 xml 文件,其中包含<root />transform.xsl 是您发布的精简后的 xsl。

EDIT

编辑

It does however seem the $.transform has problems importing stylesheets from included files:

然而,似乎 $.transform 从包含的文件中导入样式表有问题:

Here's how to fix this:

以下是解决此问题的方法:

Locate

定位

var safariimportincludefix = function(xObj,rootConfig) {

in jquery.transform.jsand replace the entire function with this:

injquery.transform.js并用这个替换整个函数:

var safariimportincludefix = function(xObj,rootConfig) {
    var vals = $.merge($.makeArray(xObj.getElementsByTagName("import")),$.makeArray(xObj.getElementsByTagName("include")));

    for(var x=0;x<vals.length;x++) {
        var node = vals[x];
        $.ajax({
            passData : { node : node, xObj : xObj, rootConfig : rootConfig},
            dataType : "xml",
            async : false,
            url : replaceref(node.getAttribute("href"),rootConfig),
            success : function(xhr) {
                try {
                    var _ = this.passData;
                    xhr = safariimportincludefix(xhr,_.rootConfig);

                    var imports = $.merge(childNodes(xhr.getElementsByTagName("stylesheet")[0],"param"),childNodes(xhr.getElementsByTagName("stylesheet")[0],"template"));
                    var excistingNodes = [];
                    try 
                    {
                        var sheet = _.xObj;
                        var params = childNodes(sheet,"param");
                        var stylesheets = childNodes(sheet,"template");
                        existingNodes = $.merge(params,stylesheets);
                    }
                    catch(exception) 
                    {
                        var x = exception;
                    }
                    var existingNames = [];
                    var existingMatches = [];
                    for(var a=0;a<existingNodes.length;a++) {
                        if(existingNodes[a].getAttribute("name")) {
                            existingNames[existingNodes[a].getAttribute("name")] = true;
                        } else {
                            existingMatches[existingNodes[a].getAttribute("match")] = true;
                        }
                    }

                    var pn = _.node.parentNode;
                    for(var y=0;y<imports.length;y++) {
                        if(!existingNames[imports[y].getAttribute("name")] && !existingMatches[imports[y].getAttribute("match")]) {
                            var clonednode = _.xObj.ownerDocument.importNode(imports[y],true);
                            //pn.insertBefore(clonednode,_.xObj);
                            pn.insertBefore(clonednode,childNodes(_.xObj,"template")[0]);
                        }
                    }
                    pn.removeChild(_.node);
                } catch(ex) { 

                }
            }
        });
    }

    return xObj;
};

Now using the previously pasted test index.html use this for transform.xsl:

现在使用之前粘贴的测试 index.html 将其用于transform.xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >
        <xsl:include href="include.xsl" />
    <xsl:output method="html"/>
    <xsl:template match="/">
            <xsl:call-template name="giveMeAnIncludedHeader" />
    </xsl:template>
</xsl:stylesheet>

And this for include.xsl

而这对于 include.xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template name="giveMeAnIncludedHeader">
        <h1>Test</h1>
    </xsl:template>
</xsl:stylesheet>

With the previously posted fix in jquery.transform.jsthis will now insert the included <h1>Test</h1>on all the browsers.

使用之前发布的修复程序,jquery.transform.js现在将插入包含<h1>Test</h1>在所有浏览器中的内容。

You can see it in action here: http://www.mpdreamz.nl/xsltest

你可以在这里看到它的实际效果:http: //www.mpdreamz.nl/xsltest

回答by moonlightdock

This is not an answer to the original question but during my search over internet looking for a sample xslt transformation that works on chromeI found links to this thread many times. I was looking for a solution that doesn't use any open-source or third party libraries/plugins and works well with silverlight.

这不是原始问题的答案,但在我在互联网上搜索寻找适用于 chrome示例 xslt 转换时,我多次找到指向该线程的链接。我一直在寻找一种不使用任何开源或第三方库/插件并且适用于 Silverlight 的解决方案。

The problem with chrome and safari is the limitation that prevents loading xml files directly. The suggested workaround at http://www.mindlence.com/WP/?p=308is to load the xml file via any other method and pass it as a string to the xslt processor.

chrome 和 safari 的问题是限制直接加载 xml 文件。http://www.mindleence.com/WP/?p=308 上的建议解决方法是通过任何其他方法加载 xml 文件并将其作为字符串传递给 xslt 处理器。

With this approach I was able to perform xsl transformations in javascript and pass on the result to silverlight app via HTML Bridge.

通过这种方法,我能够在 javascript 中执行 xsl 转换,并通过 HTML Bridge 将结果传递给 Silverlight 应用程序。