2010-01-11 110 views
10

我有一种将XSLT样式Chrome和Safari XSLT使用JavaScript

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:包括。需要找到一种方式来获得包括工作,我会在这里贴进步

更新

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

更新

,我想是被应用到XML文件的XSL最终结果。其中包含xsl文件。我希望trasnfer理想地在客户端上发生。

更新 鲁珀特,你可以更新与XML,以及如何你调用Test.Xml.xslTransform的问题?

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

的代码被称为如下的XML:

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

扩展数据是由Web服务返回的XML。

+0

请提供更多信息,例如异常消息。我建议使用Sarissa(用于跨浏览器XML/XSLT的开源JavaScript)。 – 2010-01-11 13:56:26

+0

也许XML上的XSLT没有返回任何结果,因为XSLT中的模板都没有匹配XML文档。查看我的博客“避免常见的XSLT错误”(http://dev.ektron.com/blogs.aspx?id=22956),特别是链接“XSLT:namespaces”(http://dev.ektron.com/kb_article.aspx ?id = 481) – 2010-01-11 15:25:17

+0

在xslt中使用xsl:include看起来有问题。目前正在寻找方法。 – Rupert 2010-01-11 17:34:57

回答

14

如果你的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更轻巧。

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> 

这个测试的HTML页面都在Chrome /火狐/ IE浏览器的工作原理。

input.xml只是一个简单的xml文件,包含<root /> 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它将会插入包括所有浏览器上的<h1>Test</h1>

您可以在这里的行动看出来:http://www.mpdreamz.nl/xsltest

+0

它似乎是导致问题的xsl:include问题。我正在寻找可能试图使用萨里萨 – Rupert 2010-01-11 17:33:39

+0

更新与另一个旨在解决这个问题的库。 jQuery插件很容易设置,即使预处理会增加一些延迟,您也不必重写xslt,这是一个巨大的定时器。 – 2010-01-11 19:59:27

+0

我认为我会遇到的问题是xml文件正在实时生成,所以我不认为转换函数会起作用 – Rupert 2010-01-12 12:19:58

5

这不是一个答案,原来的问题,但我的搜索在网上找了样品XSLT转换上的镀铬工作期间,我发现链接到本线多次。我一直在寻找一种不使用任何开源或第三方库/插件的解决方案,并且可以与Silverlight一起使用。

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

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