如何将 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,但对于我的情况来说这似乎是一种更好的做法。
我正在做一个项目,我需要阅读一个长(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,但对于我的情况来说这似乎是一种更好的做法。