我在Edge和IE11中遇到了一个问题,使用XSLT将HTML转换为XML。当转换时,只有Edge和IE11中的元素在转换后会变成一个空的或自我关闭的元素,而Chrome和Firefox则会保留空格。这是真实的从XML到HTML和HTML到XML的问题,我已经创建了一个Codepen的例子,从HTML到XML,这是一个超精简版的代码,以最小的噪音来展示我使用的过程。https:/codepen.ioakealeypenYzyEmpz)。
在Chrome和Edge中运行钢笔,结果会显示Edge删除了空格。有什么方法可以保留这些空格吗?我已经通过各种不同的属性和设置来做到这一点,但没有任何效果。被转换的标记存在于一个网页上(网页我有完全的控制权,文档我没有)。
var outStr, processor, implementationObject, transformedDocument;
// a trimmed down document all the way to the element in question
var xmlStr = '<div> </div>';
// an alternate bare bones xslt. also does not generate a space in the output
var xsltStr = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\n<xsl:output method="xml" encoding="utf-8" indent="no"/>\n<xsl:template match="/">\n<xsl:copy-of select="*" />\n</xsl:template></xsl:stylesheet>';
// create the dom parser
var domParser = new DOMParser();
// parse both xml and xslt into actual dom objects. Note xml has the xml header prepended
var xmlDoc = domParser.parseFromString('<?xml version="1.0" ?>' + xmlStr, 'text/xml');
var xsltDoc = domParser.parseFromString(xsltStr, 'text/xml');
// test what xslt processors are available. if chrome, firefox, edge - else ie11
if (typeof XSLTProcessor !== "undefined" && XSLTProcessor !== null) {
// Chrome
// Edge
// Firefox
processor = new XSLTProcessor();
processor.importStylesheet(xsltDoc);
//edge has the space inside xmlDoc up to this point
transformedDocument = processor.transformToFragment(xmlDoc, document);
// inspecting the tansformed document in Edge shows the element has no space but chrome and firefox does
} else if ('transformNode' in xmlDoc) {
// IE11
transformedDocument = xmlDoc.transformNode(xsltDoc);
} else {
console.log('no transform engine found');
}
// turn the converted xml document into a string
var xmlSerializer = new XMLSerializer();
var transformResult = xmlSerializer.serializeToString(transformedDocument);
console.log(transformResult);
// In Edge .serializeToString() turns the element in to a self closing tag (as there is no content)
var hasSpace = /> <\//.test(transformResult);
console.log(hasSpace);
对于直接使用MSXML的IE来说,我认为你需要设置为 preserveWhiteSpace
到 true
前,在任何DOMDocument上使用 load
或 loadXML
,因为该属性的默认值为false(https:/docs.microsoft.comen-usprevious-versionswindowsdesktopms761353(v%3Dvs.85)).
对于Edge来说,设置 <div xml:space="preserve"> </div>
.
你的codepen在IE中出现了错误。transformNode
在IE中未定义。你需要使用 new ActiveXObject('Msxml2.DOMDocument.6.0')
和 loadXML
而不是IE中的 DOMParser
来解析XML。对于Edge,我赞成Martin的答案。应用 xml:space="preserve"
那么它也将适用于所有的子代元素。
最后的代码示例是这样的,它可以在IE和Edge中很好地工作(请注意 //IE11
代码中的部分)。)
function textOrConsole(text, elementSelector) {
var processorElement = document.querySelector(elementSelector);
if (processorElement)
processorElement.innerText = text;
else
console.log(text);
}
var outStr, processor, implementationObject, transformedDocument, transformResult;
// a trimmed down document all the way to the element in question
var xmlStr = '<div xml:space="preserve"><div> </div></div>';
// an alternate bare bones xslt. also does not generate a space in the output
var xsltStr = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\n<xsl:output method="xml" encoding="utf-8" indent="no"/>\n<xsl:template match="/">\n<xsl:copy-of select="*" />\n</xsl:template></xsl:stylesheet>';
// create the dom parser
var domParser = new DOMParser();
// parse both xml and xslt into actual dom objects. Note xml has the xml header prepended
var xmlDoc = domParser.parseFromString('<?xml version="1.0" ?>' + xmlStr, 'text/xml');
var xsltDoc = domParser.parseFromString(xsltStr, 'text/xml');
// test what xslt processors are available. if chrome, firefox, edge - else ie11
if (typeof XSLTProcessor !== "undefined" && XSLTProcessor !== null) {
// Chrome
// Edge
// Firefox
textOrConsole('XSLTProcessor (transformToFragment)', '#transform');
processor = new XSLTProcessor();
processor.importStylesheet(xsltDoc);
//edge has the space inside xmlDoc up to this point
transformedDocument = processor.transformToFragment(xmlDoc, document);
// inspecting the tansformed document in Edge shows the element has no space but chrome and firefox does
} else if (!!window.ActiveXObject || "ActiveXObject" in window) {
// IE11
var docxml = new ActiveXObject('Msxml2.DOMDocument.6.0');
docxml.loadXML(xmlStr);
var docxsl = new ActiveXObject('Msxml2.DOMDocument.6.0');
docxsl.loadXML(xsltStr);
transformedDocument = docxml.transformNode(docxsl);
textOrConsole('xmlDoc.transformNode', '#transform');
} else {
console.log('no transform engine found');
}
// turn the converted xml document into a string
var xmlSerializer = new XMLSerializer();
if (!!window.ActiveXObject || "ActiveXObject" in window) {
// IE11
transformResult = transformedDocument;
} else {
transformResult = xmlSerializer.serializeToString(transformedDocument);
}
// In Edge .serializeToString() turns the element int oa self closing tag (as there is no content)
var hasSpace = /> <\//.test(transformResult);
textOrConsole("Transformed element: " + transformResult, '#text');
textOrConsole("Has space: " + hasSpace, '#hasSpace');
<h3>Result</h3>
<span>Transform used: </span><span id="transform"></span>
<div id="text"></div>
<div id="hasSpace"></div>
</body>