如何使用 JavaScript 转换 XML 和 XSLT?
Posted
技术标签:
【中文标题】如何使用 JavaScript 转换 XML 和 XSLT?【英文标题】:How can I use JavaScript to transform XML & XSLT? 【发布时间】:2011-08-09 00:11:39 【问题描述】:我想使用 javascript 来显示我的 XSLT,但在我的服务器上,浏览器中没有显示任何内容。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="main.js"></script>
<meta http-equiv="Content-Language" content="en-us"/>
<title>Contracting, Licensing and Compliance News</title>
</head>
<body>
<script language="javascript">
function displayMessage()
// Load XML
var xml = new ActiveXObject("Microsoft.XMLDOM")
xml.async = false
xml.load("site-index.xml")
// Load the XSL
var xsl = new ActiveXObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load("site-index.xsl")
// Transform
document.write(xml.transformNode(xsl))
</script>
</body>
</html>
【问题讨论】:
ActiveXObject
仅适用于 Microsoft 的 JScript。在 Internet Explorer 下查看。
继续使用 xslt 2.0,因为当 xsl 包含 ext:node-set 时 edgeHTML 14 会中断。在 XSLT 2.0 中,不再需要使用节点集函数的结果树片段。在所有情况下,您都会得到一个节点集。
【参考方案1】:
您最好允许浏览器使用 Xenan 概述的方法执行转换。但是,在 JavaScript 中也完全可以做到这一点。下面概述了如何以跨浏览器的方式完成此任务。
首先,您需要加载 XML 和 XSL。有很多方法可以做到这一点。通常,它会涉及某种 AJAX,但不一定。为了让这个答案简单,我假设您已经涵盖了这部分,但是如果您需要更多帮助,请告诉我,我将编辑以包含加载 XML 的示例。
因此,让我们假设我们有这些对象:
var xml, xsl;
xml
包含一个 XML 结构,xsl
包含您希望转换的样式表。
编辑:
如果您需要加载这些对象,您最终将使用某种形式的 AJAX 来执行此操作。有很多跨浏览器 AJAX 的例子。您最好使用库来完成此操作,而不是滚动您自己的解决方案。我建议你研究一下 jquery 或 YUI,这两者都做得很好。
但是,基本思想非常简单。为了完成这个答案,这里有一些非库特定的代码以跨浏览器的方式完成这个:
function loadXML(path, callback)
var request;
// Create a request object. Try Mozilla / Safari method first.
if (window.XMLHttpRequest)
request = new XMLHttpRequest();
// If that doesn't work, try IE methods.
else if (window.ActiveXObject)
try
request = new ActiveXObject("Msxml2.XMLHTTP");
catch (e1)
try
request = new ActiveXObject("Microsoft.XMLHTTP");
catch (e2)
// If we couldn't make one, abort.
if (!request)
window.alert("No ajax support.");
return false;
// Upon completion of the request, execute the callback.
request.onreadystatechange = function ()
if (request.readyState === 4)
if (request.status === 200)
callback(request.responseXML);
else
window.alert("Could not load " + path);
;
request.open("GET", path);
request.send();
你可以通过给它一个指向你的 XML 的路径来使用这段代码,并在加载完成时执行一个函数:
loadXML('/path/to/your/xml.xml', function (xml)
// xml contains the desired xml document.
// do something useful with it!
);
我已经更新了我的示例来展示这种技术。你可以找到一些工作演示代码here。
要执行转换,您最终会得到第三个 XML 文档,它是该转换的结果。如果您使用 IE,则使用“transformNodeToObject”方法,如果您使用其他浏览器,则使用“transformToDocument”方法:
var result;
// IE method
if (window.ActiveXObject)
result = new ActiveXObject("MSXML2.DOMDocument");
xml.transformNodeToObject(xsl, result);
// Other browsers
else
result = new XSLTProcessor();
result.importStylesheet(xsl);
result = result.transformToDocument(xml);
此时,result
应该包含生成的转换。这仍然是一个 XML 文档,您应该这样对待它。如果你想要一个可以传递给document.write
或innerHTML
的字符串,你还有一些工作要做。
再一次,有一个 IE 方法可以解决这个问题,还有一个适用于其他浏览器的方法。
var x, ser, s = '';
// IE method.
if (result.childNodes[0] && result.childNodes[0].xml)
for (x = 0; x < result.childNodes.length; x += 1)
s += result.childNodes[x].xml;
// Other browsers
else
ser = new XMLSerializer();
for (x = 0; x < result.childNodes.length; x += 1)
s += ser.serializeToString(result.childNodes[x]);
现在s
应该包含生成的 XML 作为字符串。您应该能够将它传递给 document.write 或 innerHTML 并让它做一些有用的事情。请注意,它可能包含一个 XML 声明,您可能希望删除或不删除。
我已经在 Chrome、IE9 和 FF4 中对此进行了测试。您可以找到一个简化的准系统working example of this in my testbed。
祝你好运,编码愉快!
【讨论】:
非常感谢您的反馈,但我不确定如何在您提供的代码中加载 xml 或 xslt 我已经更新了我的答案,举例说明了如何加载实际的 XML 和 XSL 文件。请参阅嵌入式链接以获取工作示例。 非常感谢,但我很遗憾他们说问题不在脚本中。这在 XSLT 文件中相当简单...... 浏览器 XSLT 实现是 1.0 版还是 2.0 版? 另外,有没有办法在 jQuery 中做到这一点?【参考方案2】:浏览器可以为您执行转换。不需要 javascript,只需像这样从 .xml 链接 .xsl:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="site-index.xsl" ?>
只提供 xml,没有 html。假设您的 .xsl 包含正确的代码,沿线
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.01" indent="yes"/>
<xsl:output doctype-system="http://www.w3.org/TR/html4/strict.dtd"/>
<xsl:output doctype-public="-//W3C//DTD HTML 4.01//EN"/>
【讨论】:
是的,但我认为这不是被问到的。 提问者想使用Javascript,这不是正确答案。 在我看来,在某些情况下用户可能不知道更好的解决方案,并且在大多数情况下只是将 XSLT 文件指示为 XML 文件的样式表会很好地工作。【参考方案3】:使用此脚本通过 test.xsl 转换 test.xml 并将输出附加到 container。
<div id="container"></div>
<script>
function loadXMLDoc(filename)
if (window.ActiveXObject)
xhttp = new ActiveXObject("Msxml2.XMLHTTP");
else
xhttp = new XMLHttpRequest();
xhttp.open("GET", filename, false);
xhttp.send("");
return xhttp.responseXML;
xml = loadXMLDoc("test.xml");
xsl = loadXMLDoc("test.xsl");
if (document.implementation && document.implementation.createDocument)
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToFragment(xml, document);
document.getElementById('container').appendChild(resultDocument);
</script>
【讨论】:
transformToFragment 在 Chrome 中给出一个空值,并且 importStylesheet 在 Chrome 中作为样式表导入,但在 Mozilla 中它不导入。 @MateenKadwaikar 我相信 Chrome 放弃了原生 XSLT 支持。我想我已经快要找到一个 shim,这样我就可以逐步增强 Chrome 和任何未来放弃支持的浏览器了。【参考方案4】:这适用于 Chrome/Firefox/Edge/IE11
function loadXMLDoc(filename)
if (window.ActiveXObject || "ActiveXObject" in window)
xhttp = new ActiveXObject("Msxml2.XMLHTTP");
else
xhttp = new XMLHttpRequest();
xhttp.open("GET", filename, false);
xhttp.send("");
return xhttp.responseXML;
if (window.ActiveXObject || "ActiveXObject" in window)
ie();
else
xml = loadXMLDoc("input.xml");
xsl = loadXMLDoc("mmlctop2_0.xsl");
if (document.implementation && document.implementation.createDocument)
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToDocument(xml, document);
var serializer = new XMLSerializer();
var transformed = serializer.serializeToString(resultDocument.documentElement);
alert(transformed);
// https://msdn.microsoft.com/en-us/library/ms753809(v=vs.85).aspx
function ie()
var xslt = new ActiveXObject("Msxml2.XSLTemplate.3.0");
var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");
var xslProc;
xslDoc.async = false;
xslDoc.load("mmlctop2_0.xsl");
if (xslDoc.parseError.errorCode != 0)
var myErr = xslDoc.parseError;
alert("You have error " + myErr.reason);
else
xslt.stylesheet = xslDoc;
var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
xmlDoc.async = false;
xmlDoc.load("input.xml");
if (xmlDoc.parseError.errorCode != 0)
var myErr = xmlDoc.parseError;
alert("You have error " + myErr.reason);
else
xslProc = xslt.createProcessor();
xslProc.input = xmlDoc;
xslProc.addParameter("param1", "Hello");
xslProc.transform();
alert(xslProc.output);
【讨论】:
【参考方案5】:由于声誉低,仅以答案的形式发表评论。
如果您通过 AJAX 调用获取文档,DO 返回xhttp.responseXML
并且请勿 返回xhttp.responseXML.documentElement
。
两者都可以使用 XMLSerializer 转换为有意义的文档表示,但只有第一个语句是 XSL 转换的可行参数。
如果使用后者,则 XSLTransformation(使用 toDocument
或 toFragment
函数)的返回值在我的情况下是 null
(使用 Chrome)
就此而言,我不认为 Chrome 已经放弃了对 XSLT 的支持,如此处页面某处所述。
希望有帮助
【讨论】:
以上是关于如何使用 JavaScript 转换 XML 和 XSLT?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Javascript 将 XML 转换为 JSON(并返回)