2016-05-11 68 views
2

我正在努力解決我在進行客戶端XSL轉換時只遇到Internet Explorer 10和11的問題。我的目標是轉換給定的XML字符串,其中包含HTML標記<pre>...</pre>,以便準備格式化輸出。 (btw:即使將它們包裝到CDATA容器中也是如此),甚至更令人困惑的是,在轉換後,輸出包含其他cr/t字符, lfs在任意位置。IE10 + 11:XSLT轉換將任意CR/LF添加到XML中

這僅發生在IE 10/11中。沒有這樣的問題與Chrome或Firefox,既沒有Edge!

我知道在IE中XSLT的處理方式與其他瀏覽器不同,我已經在我的示例中考慮過兩種不同的替代方法,但是兩者都產生相同的輸出。

請檢查我下面的HTML代碼段(只是嘗試在IE和Chrome/FF,你就會明白我的意思...):

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
<title>Test maker</title> 
 

 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> 
 
<script type="text/javascript"> 
 

 
var xml = "<Actions><action><html><body><pre xml:space=\"preserve\">" 
 
\t + "\nThis line is not split and it ends with a dedicated cr-lf.\n" 
 
     + "This is a new line. It also continues until the full-stop, then has a cr-lf.\n" 
 
\t + "This is the third and therewith the last line.\n</pre></body></html></action></Actions>"; \t 
 

 
\t \t 
 
var xsl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
 
\t + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" 
 
\t + "<xsl:preserve-space elements=\"*\"/>" 
 
     + "<xsl:template match=\"/\"><Actions><xsl:for-each select=\"//action\"><action><description><xsl:apply-templates select=\"html/*\" />" 
 
     + "</description></action></xsl:for-each></Actions></xsl:template><xsl:template match=\"html//pre\"><xsl:text>&lt;code&gt;</xsl:text>" 
 
\t + "<xsl:apply-templates select=\"node()\"/><xsl:text>&lt;/code&gt;</xsl:text></xsl:template>" 
 
\t + "<xsl:template match=\"text()\"><xsl:value-of select=\".\"/></xsl:template></xsl:stylesheet>"; 
 
\t 
 
\t 
 
function applyAdapterRule(odtaDocument, ruleData, alt) { 
 
\t if (odtaDocument && ruleData) { 
 
     var result = null; 
 
\t  if (window.ActiveXObject || "ActiveXObject" in window) { \t \t \t \t // IE 
 
\t   //IE9 won't recognize the proper codepage 
 
       odtaDocument.charset = "UTF-8"; 
 
       odtaDocument.characterSet = "UTF-8"; 
 
\t \t odtaDocument.preserveWhiteSpace = true; 
 
\t \t switch(alt) { 
 
\t \t case 1: 
 
        var srcTree = new ActiveXObject("Msxml2.DOMDocument.6.0"); 
 
\t \t  srcTree.async=false; 
 
\t \t  srcTree.preserveWhiteSpace = true; 
 
\t \t  srcTree.load(odtaDocument); 
 
\t \t  var xslDoc = new ActiveXObject("Msxml2.DOMDocument.6.0"); 
 
\t \t  xslDoc.async = false; 
 
\t \t  xslDoc.preserveWhiteSpace = true; 
 
\t \t  xslDoc.load(ruleData); 
 
\t \t  return srcTree.transformNode(xslDoc); 
 
\t \t case 2: \t 
 
\t \t  var xslt = new ActiveXObject("Msxml2.XSLTemplate.6.0"); 
 
\t \t  var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.6.0"); 
 
\t \t  xslDoc.async = false; 
 
\t \t  xslDoc.preserveWhiteSpace = true; 
 
\t \t  xslDoc.load(ruleData); 
 
\t \t  xslt.stylesheet = xslDoc; 
 
\t \t  var xslProc = xslt.createProcessor(); 
 
\t \t  xslProc.input = odtaDocument; 
 
\t \t  xslProc.transform(); 
 
\t \t  return xslProc.output; 
 
\t \t } 
 
\t \t \t \t 
 
     } else if (document.implementation && document.implementation.createDocument) { \t // Chrome, Mozilla 
 
       xsltProcessor = new XSLTProcessor(); 
 
       xsltProcessor.importStylesheet(ruleData); 
 
       resultDocument = xsltProcessor.transformToDocument(odtaDocument); 
 
       return resultDocument; 
 
     } 
 
\t } 
 
}; 
 
\t \t 
 
function do_it(alternative) { 
 
      var rule = $.parseXML(xsl); 
 
\t  var new_xml = ""; 
 
      
 
      var tempDoc = $.parseXML(xml); 
 
// \t  tempDoc.preserveWhiteSpace = true; 
 
    
 
      tempDoc = applyAdapterRule(tempDoc, rule, alternative); 
 
      if (typeof tempDoc === "string") { 
 
       new_xml = tempDoc; \t \t \t \t \t \t // IE 
 
      } else { 
 
       new_xml = new XMLSerializer().serializeToString(tempDoc); \t // Chrome, Mozilla 
 
      } 
 
\t  $("#out").replaceWith("<pre>"+new_xml+"</pre>"); 
 
}; 
 
    
 
</script> 
 
</head> 
 

 
<body> 
 
<button onclick="javascript:do_it(1);">Test 1</button> 
 
<button onclick="javascript:do_it(2);">Test 2</button> 
 
<div><div id="out">See what happens...</div></div> 
 
</body> 
 
</html>

有什麼我在IE的情況下,仍然在做錯XSL轉換?

/編輯:

從上面的例子,我希望下面的輸出(因爲我來自Chrome和Firefox獲得):

enter image description here

隨着我的IE11不過,我得到這個輸出,不管如果我按第一或第二按鈕(即我是否執行的情況1或情況2分支):

enter image description here

+0

...要在IE中運行腳本(這是這裏的問題),可能需要將代碼複製並粘貼到本地HTML文件中,並用IE打開它。我只注意到,僅僅使用[run code snippet] -button時,ActiveX對象不會正確實例化。 –

+0

請編輯您的問題並解釋並在代碼片段中顯示您期望從XSLT轉換中獲得的結果。我不確定你在尋找什麼,並且將瀏覽器的XML解析和序列化的API與通過JQuery的附加解析和序列化混合在一起,這使得很難理解問題是什麼以及它來自哪裏。一個簡單的測試用例使用IE的MSXML API,然後在http://home.arcor.de/martin.honnen/xslt/test2016051201.html的HTML文檔的文本節點中簡單地輸出transformNode結果並不會顯示任何問題我可以說。 –

+0

我試圖擴展以前的測試,以支持'XSLTProcessor'的瀏覽器,現在我有http://home.arcor.de/martin.honnen/xslt/test2016051202.html,據我可以告訴結果在IE 11和Firefox 46的空白區域以及Windows 10的Edge上是相同的。 –

回答

0

對於IE,我建議直接使用MSXML API,不要將JQuery與MSXML API混合使用。使用http://home.arcor.de/martin.honnen/xslt/test2016051202.html基本上加載您xmlxsl字符串作爲MSXML DOM文檔

var xml = "<Actions><action><html><body><pre xml:space=\"preserve\">" 
    + "\nThis line is not split and it ends with a dedicated ctrl-lf.\n" 
     + "This is a new line. It also continues until the full-stop, then has a ctrl-lf.\n" 
    + "This is the third and therewith the last line.\n<\/pre><\/body><\/html><\/action><\/Actions>"; 


var xsl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
    + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" 
    + "<xsl:preserve-space elements=\"*\"/>" 
     + "<xsl:template match=\"/\"><Actions><xsl:for-each select=\"//action\"><action><description><xsl:apply-templates select=\"html/*\" />" 
     + "<\/description><\/action><\/xsl:for-each><\/Actions><\/xsl:template><xsl:template match=\"html//pre\"><xsl:text>&lt;code&gt;<\/xsl:text>" 
    + "<xsl:apply-templates select=\"node()\"/><xsl:text>&lt;/code&gt;<\/xsl:text><\/xsl:template>" 
    + "<xsl:template match=\"text()\"><xsl:value-of select=\".\"/><\/xsl:template><\/xsl:stylesheet>"; 

function test1() { 
    if (typeof DOMParser != 'undefined' && typeof XSLTProcessor != 'undefined') { 
     var xmlDoc = new DOMParser().parseFromString(xml, 'application/xml'); 
     var sheet = new DOMParser().parseFromString(xsl, 'application/xml'); 

     var proc = new XSLTProcessor(); 
     proc.importStylesheet(sheet); 

     var resultDoc = proc.transformToDocument(xmlDoc); 
     var result = new XMLSerializer().serializeToString(resultDoc); 

     var pre = document.createElement('pre'); 
     pre.textContent = result; 
     document.getElementById('test1').appendChild(pre); 
    } 
    else { 
     try { 
      var xmlDoc = new ActiveXObject('Msxml2.DOMDocument.6.0'); 
      xmlDoc.loadXML(xml); 

      var sheet = new ActiveXObject('Msxml2.DOMDocument.6.0'); 
      sheet.loadXML(xsl); 

      var result = xmlDoc.transformNode(sheet); 

      var pre = document.createElement('pre'); 
      pre.textContent = result; 

      document.getElementById('test1').appendChild(pre); 
     } 
     catch (e) { 
      console.log(e); 
      throw e; 
     } 
    } 
} 

window.onload = function() { 
    test1(); 
} 

轉換結果的代碼具有原始換行符保留:

<?xml version="1.0"?><Actions><action><description>&lt;code&gt; 
This line is not split and it ends with a dedicated ctrl-lf. 
This is a new line. It also continues until the full-stop, then has a ctrl-lf. 
This is the third and therewith the last line. 
&lt;/code&gt;</description></action></Actions> 
+0

...只是想澄清一點: 我不認爲這個問題是JQuery和MSXML API的混合! 此外,在我看來好像只有load()方法會導致問題。在上面的Martins片段中,使用了'loadXML()'方法,這個方法可以正常工作(對於我來說,切換到該方法就是解決方案)。 我試過馬丁的代碼,但用'xmlDoc.load(xmlObj)'(將字符串xml轉換成'Object xmlObj'後)替換了'xmlDoc.loadXML(xml)',並且因此又出現了這個問題。 –

0

所以,當我替代物的方法xmlDoc.loadXML(xml)用代碼如下所示:

var xml = "<Actions><action><html><body><pre xml:space=\"preserve\">" 
    + "\nThis line is not split and it ends with a dedicated ctrl-lf.\n" 
    + "This is a new line. It also continues until the full-stop, then has a ctrl-lf.\n" 
    + "This is the third and therewith the last line.\n<\/pre><\/body><\/html><\/action><\/Actions>"; 


var xsl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
    + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" 
    + "<xsl:preserve-space elements=\"*\"/>" 
    + "<xsl:template match=\"/\"><Actions><xsl:for-each select=\"//action\"><action><description><xsl:apply-templates select=\"html/*\" />" 
    + "<\/description><\/action><\/xsl:for-each><\/Actions><\/xsl:template><xsl:template match=\"html//pre\"><xsl:text>&lt;code&gt;<\/xsl:text>" 
    + "<xsl:apply-templates select=\"node()\"/><xsl:text>&lt;/code&gt;<\/xsl:text><\/xsl:template>" 
    + "<xsl:template match=\"text()\"><xsl:value-of select=\".\"/><\/xsl:template><\/xsl:stylesheet>"; 

function test1() { 
    if (typeof DOMParser != 'undefined' && typeof XSLTProcessor != 'undefined') { 
     var xmlDoc = new DOMParser().parseFromString(xml, 'application/xml'); 
     var sheet = new DOMParser().parseFromString(xsl, 'application/xml'); 

     var proc = new XSLTProcessor(); 
     proc.importStylesheet(sheet); 

     var resultDoc = proc.transformToDocument(xmlDoc); 
     var result = new XMLSerializer().serializeToString(resultDoc); 

     var pre = document.createElement('pre'); 
     pre.textContent = result; 
     document.getElementById('test1').appendChild(pre); 
    } 
    else { 
     try { 

      var xmlDoc = new ActiveXObject('Msxml2.DOMDocument.6.0'); 

      var xmlObj = $.parseXML(xml);  //convert XML String to XML Object 
      xmlDoc.load(xmlObj);    //use load() instead of loadXML() 

      var sheet = new ActiveXObject('Msxml2.DOMDocument.6.0'); 
      sheet.loadXML(xsl); 

      var result = xmlDoc.transformNode(sheet); 

      var pre = document.createElement('pre'); 
      pre.textContent = result; 

      document.getElementById('test1').appendChild(pre); 
     } 
     catch (e) { 
      console.log(e); 
      throw e; 
     } 
    } 
} 

window.onload = function() { 
    test1(); 
} 

並得到的輸出是:

<?xml version="1.0"?><Actions><action><description>&lt;code&gt;This line is not split and it ends with a dedicated 
ctrl-lf. This is a new line. It also continues until the full-stop, then has a 
ctrl-lf. This is the third and therewith the last line. 
&lt;/code&gt;</description></action></Actions>