使用 JavaScript 的 Chrome 和 Safari XSLT [英] Chrome and Safari XSLT using JavaScript

查看:25
本文介绍了使用 JavaScript 的 Chrome 和 Safari XSLT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Test.Xml.xslTransform = function(xml, xsl) {尝试 {//IE 代码如果(window.ActiveXObject){ex = xml.transformNode(xsl);返回前;}//Mozilla、Firefox、Opera 等的代码else if (document.implementation && document.implementation.createDocument) {xsltProcessor = new XSLTProcessor();xsltProcessor.importStylesheet(xsl);resultDocument = xsltProcessor.transformToFragment(xml, document);返回结果文档;}} 捕获(异常){if (typeof (exception) == "object") {如果(异常消息){警报(异常.消息);}} 别的 {警报(例外);}}

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

更新

ResultDocument = xsltProcessor.transformToFragment(xml, document);

上面的行返回空值.没有抛出错误.

更新

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

更新

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

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

Test.Xml.xslTransform = function(xml, xsl) {尝试 {$("body").append("<div id='test' style='display:none;'></div>");var a = $("#test").transform({ xmlobj: xml, xslobj: xsl });返回一个.html();}捕获(异常){if (typeof (exception) == "object") {如果(异常消息){警报(异常.消息);}} 别的 {警报(例外);}}}

xml 和 xsl 都是传入的对象.

更新

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

更新

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

已更新Rupert 能否用 xml 更新问题以及如何调用 Test.Xml.xslTransform ?

我使用 ie8 得到了 xml

<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-00AA00C14888rs:microsoft-xml-行集" xmlns:z="#RowsetSchema"><rs:data ItemCount="1"><z:row ows_Title="测试" ows_FirstName="测试 4" ows_UniqueId="74;#{1A16CF3E-524D-4DEF-BE36-68A964CC24DF}" ows_FSObjType="74;#0" ows_ID"Info="74="74" ows_owshiddenversion="10" ows_Created="2009-12-29 12:21:01" ows_FileRef="74;#Lists/我的列表名称/74_.000" ReadOnly="False" VerificationRequired="0"/></rs:data></listitems></SearchListItemsResult></SearchListItemsResponse></soap:Body></soap:Envelope>

代码调用如下:

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

xData 是 Web 服务返回的 xml.

解决方案

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

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

这个错误实际上是在 webkit 中.欲了解更多信息这里是另一个更详细的链接为什么它不起作用.

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

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

更新:

<头><脚本语言="javascript" src="jquery-1.3.2.min.js"></script><script language="javascript" src="jquery.transform.js"></script><script type="text/javascript">功能加载XML(文件){var xmlDoc = null;尝试//Internet Explorer{xmlDoc=new ActiveXObject("Microsoft.XMLDOM");xmlDoc.async=false;xmlDoc.load(文件);}捕获(e){试试//Firefox、Mozilla、Opera 等.{xmlDoc=document.implementation.createDocument("","",null);xmlDoc.async=false;xmlDoc.load(文件);}捕获(e){试试//谷歌浏览器{var xmlhttp = new window.XMLHttpRequest();xmlhttp.open("GET",file,false);xmlhttp.send(null);xmlDoc = xmlhttp.responseXML.documentElement;}捕获(e){错误=e.message;}}}返回 xmlDoc;}函数 xslTransform(xmlObject, xslObject){尝试{$("body").append("<div id='test'></div>");var a = $("#test").transform({ xmlobj: xmlObject, xslobj: xslObject });}捕获(例外){if (typeof (exception) == "object" && exception.message)警报(异常.消息);否则警报(异常);}}var xmlObject = loadXML("input.xml");var xslObject = loadXML("transform.xsl");$(document).ready(function(){xslTransform(xmlObject, xslObject);});<身体>

这个测试 html 页面在 Chrome/FireFox/IE 中都可以使用.

input.xml 只是一个包含 的简单 xml 文件transform.xsl 是您发布的精简版 xsl.

编辑

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

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

定位

var safariimportincludefix = function(xObj,rootConfig) {

jquery.transform.js 中并将整个函数替换为:

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

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

这对于 include.xsl

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

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

I have the following code that applies a XSLT style

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?

Update

ResultDocument = xsltProcessor.transformToFragment(xml, document);

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

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

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/).

The code works in IE but still not in 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.

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:

<?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.

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

I got the xml using ie8

<?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.

解决方案

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

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

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

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.

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:include working 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.

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.

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

EDIT

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

Here's how to fix this:

Locate

var safariimportincludefix = function(xObj,rootConfig) {

in jquery.transform.js and replace the entire function with this:

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:

<?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

<?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.js this will now insert the included <h1>Test</h1> on all the browsers.

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

这篇关于使用 JavaScript 的 Chrome 和 Safari XSLT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆