如何使用 JavaScript 转换 XML 和 XSLT?

IT技术 javascript xml internet-explorer browser xslt
2021-02-26 15:56:07

我想使用 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>
5个回答

您最好允许浏览器使用 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!
});

我已经更新了我的例子来展示这种技术。您可以在此处找到一些有效的演示代码


要执行转换,您最终会得到第三个 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.writeor的字符串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 中对此进行了测试。您可以在我的 testbed 中找到一个简化的准系统工作示例

祝你好运,编码愉快!

另外,有没有办法在 jQuery 中做到这一点?
2021-04-17 15:56:07
浏览器 XSLT 实现版本是 1.0 还是 2.0?
2021-04-18 15:56:07
非常感谢,但我很难过他们说问题不在剧本中。XSLT 文件中的内容相当简单....
2021-04-20 15:56:07
我已经用一个示例更新了我的答案,说明如何加载实际的 XML 和 XSL 文件。有关工作示例,请参阅嵌入的链接。
2021-04-28 15:56:07
非常感谢您的反馈,但我不确定如何在您提供的代码中加载 xml 或 xslt
2021-05-05 15:56:07

浏览器可以为您执行转换。不需要 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"/>
在我看来,在某些情况下,用户可能不知道更好的解决方案,并且在大多数情况下只是将 XSLT 文件指示为 XML 文件的样式表会很好地工作。
2021-04-24 15:56:07
提问者想使用 Javascript,这不是正确的答案。
2021-04-25 15:56:07
是的,但我想这不是被问到的。
2021-05-04 15:56:07

使用此脚本使用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>
@MateenKadwaikar 我相信 Chrome 放弃了原生 XSLT 支持。我想我已经接近找出一个 shim,这样我就可以逐步增强 Chrome 和任何未来不再支持的浏览器。
2021-04-23 15:56:07
transformToFragment 在 Chrome 中给出一个空值,importStylesheet 在 Chrome 中作为样式表导入,但在 Mozilla 中它不会导入。
2021-04-24 15:56:07

这适用于 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);
         }
     }


 }

由于声誉低,只是以答案形式发表评论。如果你通过AJAX调用的文件,不要回报xhttp.responseXML不要返回xhttp.responseXML.documentElement

两者都可以使用 XMLSerializer 转换为文档的有意义的表示,但只有第一条语句是 XSL 转换的可行参数。

如果使用后者,则 XSLTransformation 的返回值(使用任一toDocumenttoFragment函数)null在我的情况下(使用 Chrome)

就此而言,我不相信 Chrome 已经放弃了 XSLT 支持,如页面上某处所述。

希望有帮助