2010-01-11 102 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應用程序。