如何使用 JavaScript 转换 XML 和 XSLT?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5722410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I use JavaScript to transform XML & XSLT?
提问by okMonty
I want to use JavaScript to show my XSLT, but on my server nothing is showing up in the browser.
我想使用 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>
采纳答案by Xenan
The browser can perform the tranform for you. No javascript is needed, just link the .xsl from the .xml like this:
浏览器可以为您执行转换。不需要 javascript,只需像这样从 .xml 链接 .xsl:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="site-index.xsl" ?>
and just serve the xml, no html. Assuming your .xsl contains the right code, along the lines
并且只提供 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"/>
回答by Chris Nielsen
You are probably better off allowing the browser to perform the transformation using the method Xenan outlines. However, it is perfectly possible to do this in JavaScript as well. Here is an outline of how you might accomplish this in a cross-browser manner.
您最好允许浏览器使用 Xenan 概述的方法执行转换。但是,在 JavaScript 中也完全可以做到这一点。下面概述了如何以跨浏览器的方式完成此操作。
First, you will need to load the XML and XSL. There are many ways of doing this. Usually, it will involve some sort of AJAX, but not necessarily. To keep this answer simple, I will assume you have this part covered, but please let me know if you need more help, and I will edit to include an example of loading XML.
首先,您需要加载 XML 和 XSL。有很多方法可以做到这一点。通常,它会涉及某种 AJAX,但不一定。为简单起见,我假设您已经涵盖了这部分内容,但如果您需要更多帮助,请告诉我,我将编辑以包含加载 XML 的示例。
Therefore, let us assume we have these objects:
因此,让我们假设我们有这些对象:
var xml, xsl;
Where xml
contains an XML structure, and xsl
contains the stylesheet that you wish to transform with.
其中xml
包含一个 XML 结构,并xsl
包含您希望转换的样式表。
Edit:
编辑:
If you need to load those objects, you will end up using some form of AJAX to do so. There are many examples of cross-browser AJAX out there. You will be better off using a library to accomplish this, rather than rolling your own solution. I suggest you look into jquery or YUI, both of which do an excellent job of this.
如果您需要加载这些对象,您最终将使用某种形式的 AJAX 来执行此操作。有很多跨浏览器 AJAX 的例子。您最好使用库来完成此操作,而不是滚动您自己的解决方案。我建议您查看 jquery 或 YUI,它们都在这方面做得很好。
However, the basic idea is pretty simple. To complete this answer, here is some non-library specific code that accomplishes this in a cross-browser manner:
但是,基本思想非常简单。为了完成这个答案,这里有一些非库特定的代码,它们以跨浏览器的方式完成:
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();
}
You would use this code by giving it a path to your XML, and a function to execute when loading is complete:
您可以通过给它一个指向您的 XML 的路径以及一个在加载完成时执行的函数来使用此代码:
loadXML('/path/to/your/xml.xml', function (xml) {
// xml contains the desired xml document.
// do something useful with it!
});
I have updated my example to show this technique. You can find some working demonstration code here.
我已经更新了我的例子来展示这种技术。您可以在此处找到一些有效的演示代码。
To perform a transformation, you will end up with a third XML document, which is the result of that transformation. If you are working with IE, you use the "transformNodeToObject" method, and if you are working with other browsers, you use the "transformToDocument" method:
要执行转换,您最终会得到第三个 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);
}
At this point, result
should contain the resulting transformation. This is still an XML document, and you should treat it as such. If you want a string which you can pass into document.write
or innerHTML
, you have a little more work to do.
此时,result
应该包含生成的转换。这仍然是一个 XML 文档,您应该这样对待它。如果您想要一个可以传入document.write
or的字符串innerHTML
,您还有一些工作要做。
Once again, there is an IE method for this, and a method that applies to other browsers.
再一次,这里有一个 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]);
}
}
Now s
should contain the resulting XML as a string. You should be able to pass this into document.write or innerHTML and have it do something useful. Note that it may contain an XML declaration, which you might want to strip out, or not.
现在s
应该包含作为字符串的结果 XML。您应该能够将它传递到 document.write 或 innerHTML 并让它做一些有用的事情。请注意,它可能包含一个 XML 声明,您可能希望将其删除或不删除。
I've tested this in Chrome, IE9, and FF4. You can find a simplified, barebones, working example of this in my testbed.
我已经在 Chrome、IE9 和 FF4 中对此进行了测试。您可以在我的 testbed 中找到一个简化的、准系统的工作示例。
Good luck and happy coding!
祝你好运,编码愉快!
回答by Sorter
Use this script to transform test.xmlusing test.xsland append the output to container.
使用此脚本使用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>
回答by murkle
This works in Chrome/Firefox/Edge/IE11
这适用于 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);
}
}
}
回答by BennyHilarious
Just a comment in a form of an answer due to low reputation.
if you get the documents via AJAX call, DOreturn the xhttp.responseXML
and do NOTreturn xhttp.responseXML.documentElement
.
由于声誉低,只是以答案形式发表评论。如果你通过AJAX调用的文件,不要回报xhttp.responseXML
和不要返回xhttp.responseXML.documentElement
。
Both can be converted using XMLSerializer to a meaningful representation of the document but only the first statement is a viable parameter for the XSL Transformation.
两者都可以使用 XMLSerializer 转换为有意义的文档表示,但只有第一条语句是 XSL 转换的可行参数。
If the latter is used the return value of the XSLTransformation (using either toDocument
or toFragment
function) is null
in my case (using Chrome)
如果使用后者,则 XSLTransformation 的返回值(使用任一toDocument
或toFragment
函数)null
在我的情况下(使用 Chrome)
For that matter, I don't believe Chrome has dropped XSLT support as stated somewhere on the page here.
就此而言,我不相信 Chrome 已经放弃了 XSLT 支持,如页面上某处所述。
Hope that helps
希望有帮助