Edge 和 IE11 XSLT 空间问题

Posted

技术标签:

【中文标题】Edge 和 IE11 XSLT 空间问题【英文标题】:Edge and IE11 XSLT space issue 【发布时间】:2020-08-19 01:21:06 【问题描述】:

我遇到了 Edge 和 IE11 使用 XSLT 将 html 转换为 XML 的问题。 转换时,仅包含空格(一个或多个)的元素在 Edge 和 IE11 中转换后变成空元素或自闭合元素; Chrome 和 Firefox 保留空格。从 XML 到 HTML 和从 HTML 到 XML 确实如此 我创建了一个从 HTML 到 XML 的问题的 Codepen 示例,它是代码的超精简版本,以最小的噪音演示我正在使用的过程是什么。https://codepen.io/akealey/pen/YzyEmpz

在 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);

【问题讨论】:

如果使用xsl:output method="html",IE 或 Edge 是否更有效?毕竟,将使用 transformToFragment 生成的 XSLT 结果插入到 HTML DOM 中,只有使用该输出方法才有意义。 @mplungjan 不幸的是没有。输出保持完全相同。 对于纯基于 IE 的脚本,我想我记得 MSXML 在其 DOMDocument 上有一个 preserveWhitespace 属性,默认情况下为 false,因此对于 IE,您应该能够通过确保设置该属性来解决问题在使用 loadloadXML 之前设置为 true。我不确定如何指导 Edge 假设或设置它。您是否能够使用例如修复 XML 输入? &lt;div xml:space="preserve"&gt; &lt;/div&gt; 解析前? 【参考方案1】:

对于直接使用 MSXML 的 IE,我认为在使用 loadloadXML 之前,您需要在任何 DOMDocument 上将 preserveWhiteSpace 设置为 true,因为该属性的默认值为 false (https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms761353(v%3Dvs.85))。

对于 Edge,设置 &lt;div xml:space="preserve"&gt; &lt;/div&gt; 可能会有所帮助。

【讨论】:

这确实为 Edge 保留了空间(我明天会去 IE11)。但是,我无法将 'xml:space="preserve"' 添加到文档中的每个元素(它们很大,尽管我对包含页面本身进行了控制,但我无法控制导入的文档)。此外,该元素不得出现在最终文档中(尽管在转换过程中可能会删除该元素)。有什么方法可以将 xml:space="preserve" 应用于元素和下面的所有内容? 如果您将属性应用于根元素或任何容器元素,它也会应用于所有后代,除非在树的下方被覆盖。【参考方案2】:

您的 codepen 在 IE 中有错误。 transformNode 在 IE 中未定义。您需要在 IE 中使用 new ActiveXObject('Msxml2.DOMDocument.6.0')loadXML 而不是 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>

【讨论】:

以上是关于Edge 和 IE11 XSLT 空间问题的主要内容,如果未能解决你的问题,请参考以下文章

中风 url 在 Edge 和 IE 11 SVG 中不起作用

prepend/append 适用于 Chrome 和 Firefox,但不适用于 IE11 和 Edge

Bootstrap 4 表格列宽在 IE11 和 Microsoft Edge 中的格式不正确

为啥这个 CSS3 动画在 MS Edge 或 IE11 中不起作用?

文档模式为 Edge 时 IE11 中的 ReportViewer 高度问题

IE11/Edge 不尊重 DOM 中的链接/css 顺序