javascript - Edge 和 IE11 XSLT 空间问题
问题描述
我遇到了 Edge 和 IE11 使用 XSLT 从 HTML 转换为 XML 的问题。
转换时,仅包含空格(一个或多个)的元素在仅在 Edge 和 IE11 中转换后变成空元素或自闭合元素;Chrome 和 Firefox 保留空格。从 XML 到 HTML 和 HTML 到 XML 确实如此。
我创建了一个 Codepen 示例,说明从 HTML 到 XML 的问题,这是一个超精简的代码版本,以最小的噪音演示我正在使用的过程是什么。
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);
解决方案
您的 codepen 在 IE 中有错误。transformNode
在 IE 中未定义。您需要在 IE中使用new ActiveXObject('Msxml2.DOMDocument.6.0')
and而不是解析 XML。对于 Edge,我赞成 Martin 的回答:应用于根元素,然后它也将应用于所有后代。loadXML
DOMParser
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>
推荐阅读
- ssl - 我得到 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 的另一种情况
- java - Apache Wicket - DropDownChoice 实时搜索
- c# - 在 Unity3D 中刷新 ScrollView
- javascript - JS:将检查设置为 true 不起作用
- java - 为什么两个枚举与 == 运算符不兼容?
- python - 一个文本文件,在同一行中有 2 个由空格分隔的变量,其中的数据行以这种方式排列,如何将相应的数据添加在一起?
- excel - 基于不同列的vba条件格式
- python - 如何将 lat 和 long 添加回 Google 时区 API 的响应中?
- javascript - 删除 JSON 数组中特定索引的对象而不留下“null”(Node.js)
- javascript - 停止动画并在悬停时将所有圆圈对齐在同一条线上