IE10 + 11:XSLT转换将任意CR / LF添加到XML中

时间:2016-05-11 21:06:00

标签: javascript xml internet-explorer xslt

我正在努力解决在客户端XSL转换时我只遇到Internet Explorer 10和11的问题。我的目标是转换包含HTML标记<pre>...</pre>的给定XML字符串,以便准备格式化的输出。

Carriagereturn-linefeed字符(&#34; \ n&#34;)在转换过程中迷失了(顺便说一句:即使将它们包装到CDATA容器中),在转换后输出的更令人困惑的是输出在任意位置包含其他cr / lfs。

仅在IE 10/11中发生。 Chrome或Firefox没有这样的问题,也没有Edge!

我知道IE中的XSLT与其他浏览器的处理方式不同,我在我的例子中已经考虑过两种不同的选择,但两者都会产生相同的输出。

请查看我的以下HTML代码段(只需在IE和Chrome / FF中试用,您就会明白我的意思......):

&#13;
&#13;
<!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\">"
	+ "\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"
	+ "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 applyAdapterRule(odtaDocument, ruleData, alt) {
	if (odtaDocument && ruleData) {
        var result = null;
	    if (window.ActiveXObject || "ActiveXObject" in window) {				  // IE
	        //IE9 won't recognize the proper codepage
                odtaDocument.charset = "UTF-8";
                odtaDocument.characterSet = "UTF-8";
		odtaDocument.preserveWhiteSpace = true;
		switch(alt) {
		  case 1:
                    var srcTree = new ActiveXObject("Msxml2.DOMDocument.6.0");
		    srcTree.async=false;
		    srcTree.preserveWhiteSpace = true;
		    srcTree.load(odtaDocument); 
		    var xslDoc = new ActiveXObject("Msxml2.DOMDocument.6.0");
		    xslDoc.async = false;
		    xslDoc.preserveWhiteSpace = true;
		    xslDoc.load(ruleData);
		    return srcTree.transformNode(xslDoc);
		  case 2:	
		    var xslt = new ActiveXObject("Msxml2.XSLTemplate.6.0");
		    var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.6.0");
		    xslDoc.async = false;
		    xslDoc.preserveWhiteSpace = true;
		    xslDoc.load(ruleData);
		    xslt.stylesheet = xslDoc;
		    var xslProc = xslt.createProcessor();
		    xslProc.input = odtaDocument;
		    xslProc.transform();
		    return xslProc.output; 
		}
				
        } else if (document.implementation && document.implementation.createDocument) {	// Chrome, Mozilla 
                xsltProcessor = new XSLTProcessor();
                xsltProcessor.importStylesheet(ruleData);
                resultDocument = xsltProcessor.transformToDocument(odtaDocument);
                return resultDocument;
        }
	}
};
		
function do_it(alternative) {
            var rule = $.parseXML(xsl);
	    var new_xml = "";
            
            var tempDoc = $.parseXML(xml);
//	    tempDoc.preserveWhiteSpace = true;
 
            tempDoc = applyAdapterRule(tempDoc, rule, alternative);
            if (typeof tempDoc === "string") {
                new_xml = tempDoc;						// IE
            } else {
                new_xml = new XMLSerializer().serializeToString(tempDoc);	// Chrome, Mozilla
            }
	    $("#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>
&#13;
&#13;
&#13;

在IE案例中,我的XSL转换还有什么问题吗?

/编辑:

从上面的示例中,我希望得到以下输出(我从Chrome和Firefox获得):

enter image description here

然而,使用我的IE11,无论是按第一个还是第二个按钮(即我是执行案例1还是案例2分支),我都会得到此输出:

enter image description here

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

因此,当我使用xmlDoc.loadXML(xml)替换方法xmlDoc.load(xmlObj)时,代码如下所示:

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>