如何将 XML 文件转换为 Javascript 中的文档对象?

How can I convert an XML file into Document object in Javascript?

我正在做一个项目,我需要阅读一个长(50,000 行)XML 文件。我决定使用默认的 Javascript Document 或 XMLDocument 类 而不是第三方 XML 解析器。 DOM 默认 Javascript XML 解析器的树结构非常适合我的设计,因为我需要自由地遍历子节点和父节点。

我尝试按以下方式使用 XMLHttpRequest:

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        myFunction(this);
    }
};
xhttp.open("GET", "xmls/EXAMPLE.xml", true);
xhttp.send();

function myFunction(xml) {
    var xmlDoc = xml.responseXML;
    console.log(xmlDoc.getElementsByTagName("example")[0].getAttributeNode("name").nodeValue);
}

这尤其适用于 xmlDoc 对象,但在 xhttp.send() 之后,文档不再可访问。我希望文档保持可用状态,因为我需要根据客户的选择在不同时间访问文档的不同部分。

我也研究过 DOMParser,但我不确定它是否是将 50,000 行文本转换为字符串然后将其转换为 Document 对象的有效方法。

比如var xmlDoc = new DOMParser().parseFromString(xml, "application/xml");

我一直在研究堆栈溢出和 MDN 中的一些问题,但一直无法找出一种简单的方法来做到这一点。

编辑: 当我将 xmlDoc 变量设置为全局变量时,出现错误 "Cannot read property 'getElementsByTagName' of undefined"。以下是我尝试使其成为全球性的方式:

var xmlDoc;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        xmlDoc = this.responseXML;
        myFunction(this);
    }
};
xhttp.open("GET", "xmls/EXAMPLE.xml", true);
xhttp.send();

function myFunction(xml) {
    console.log(xmlDoc.getElementsByTagName("example")[0].getAttributeNode("name").nodeValue);
}

console.log(xmlDoc.getElementsByTagName("example")[0].getAttributeNode("name").nodeValue);

此处 "myFunction" 中的 console.log 有效,但另一个无效。我相信 xmlDoc 在 send() 之后变为 null。

此外,这就是我在 javascript 文件中的所有内容,没有其他用于测试目的。

问题是我不明白异步函数是如何工作的。一旦我意识到console.log(xmlDoc.getElementsByTagName("example")[0].getAttributeNode("name").nodeValue);的第二行不能立即执行,因为需要完成异步功能。

我已经切换到 promise 实现,但是这让我质疑在异步函数完成之前让全局变量或 class 变量为 null 是否是一个好的设计,我写了另一个问题是: What is a good design for global variables from Async functions in Javascript?

但是,目前我正在做的是:

self.xmlDoc = null;

this.promiseXML = new Promise(function(resolve, reject){
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", "xmls/EXAMPLE.xml", true);
    xhttp.onload = function(){
        if(xhttp.status == 200){
            self.xmlDoc = xhttp.responseXML;
            resolve();
        }else{
            reject(xhttp.statusText);
        }
    };
    xhttp.onerror = function(){
        reject(xhttp.statusText);
    }
    xhttp.send();
})

this.promiseXML.then(function(){
    console.log(self.xmlDoc.getElementsByTagName("parameter")[0].getAttributeNode("name").nodeValue);
}).catch(function(err){
    console.log(err);
});

似乎我重用 xmlDoc 的问题不一定得到解决,因为如果您在 promise 之后立即尝试 console.log(self.xmlDoc.getElementsByTagName("example")[0].getAttributeNode("name").nodeValue);,它仍然是空的。但是,我会在承诺范围内完成我需要做的一切,一旦应用程序启动,肯定会启动 self.xmlDoc

因此,如果需要在用户进行更改后使用,它是没有问题的。我最初的错误是因为我试图在任何时间过去之前 运行 我的 console.log

关于我的原始代码如何不工作,请查看 Daniel 的评论并查看异步函数和回调。了解 javascript 中的事件循环也很有帮助。

对于一个好的设计方法,我仍然不确定,但你可以尝试关注我的其他问题或者也许有人会帮助发表评论。

PS:没有必要使用 promise,但对于我的情况来说这似乎是一种更好的做法。