【问题标题】:Chrome and Safari XSLT using JavaScript使用 JavaScript 的 Chrome 和 Safari XSLT
【发布时间】:2010-01-11 13:44:00
【问题描述】:

我有以下应用 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);
        }
    }

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

更新

ResultDocument = xsltProcessor.transformToFragment(xml, document);

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

更新

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

更新

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

代码在 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和xsl都是传入的对象。

更新

我尝试将 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>

更新

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

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

我使用 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>

代码调用如下:

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

xData 是 Web 服务返回的 xml。

【问题讨论】:

  • 请提供更多信息,例如异常消息。我推荐使用 Sarissa(用于跨浏览器 XML/XSLT 的开源 JavaScript)。
  • 也许 XML 上的 XSLT 没有返回任何结果,因为 XSLT 中的模板都不匹配 XML 文档。请参阅我的博客“避免常见的 XSLT 错误”(dev.ektron.com/blogs.aspx?id=22956),尤其是链接“XSLT:命名空间”(dev.ektron.com/kb_article.aspx?id=481
  • 看起来在 xslt 中使用 xsl:include 有问题。目前正在寻找解决方法。
  • Rupert 能否用 xml 更新问题以及如何调用 Test.Xml.xslTransform
  • Rupert 似乎在使用对象时存在问题。你能确认我发布的修复对你有用吗?

标签: javascript jquery xslt safari google-chrome


【解决方案1】:

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

请参阅此铬错误报告并支持它! http://code.google.com/p/chromium/issues/detail?id=8441

该错误实际上是在 webkit 中。有关更多信息 here's 另一个链接,该链接更详细地说明了它为什么不起作用。

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

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

更新:

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

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

input.xml 只是一个包含&lt;root /&gt; 的简单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<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;
};

现在使用之前粘贴的测试 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>

这是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>

利用之前在jquery.transform.js 中发布的修复,现在将在所有浏览器上插入包含的&lt;h1&gt;Test&lt;/h1&gt;

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

【讨论】:

  • 这似乎是导致问题的 xsl:include 问题。我正在考虑可能尝试使用 Sarissa
  • 更新了另一个旨在解决此问题的库。 jQuery 插件易于设置,您不必重写 xslt,即使预处理会增加一些延迟,这也可以节省大量时间。
  • 我认为我会遇到的问题是 xml 文件是动态生成的,所以我认为转换功能不会起作用
  • 示例页面具有误导性,您也可以通过传递 xmlobj 而不是 xml 来传递 XML 对象。看看他们的官方页面:daersystems.com/jquerytransform.asp.
  • 抱歉最后一个问题。你使用客户端还是服务器?如果 xsl:include 可以与 xslobj 一起使用,您现在也可以吗?在 IE 中工作没有问题
【解决方案2】:

这不是原始问题的答案,但在我通过互联网搜索可在 chrome 上运行的示例 xslt 转换期间,我多次找到此线程的链接。我一直在寻找一种不使用任何开源或第三方库/插件并且与 silverlight 配合良好的解决方案。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-26
    • 2011-01-28
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    相关资源
    最近更新 更多