Javascript webworker不会通过XMLHttpRequest加载XML文件

时间:2012-01-30 23:22:21

标签: javascript xmlhttprequest web-worker

我很想让一个webworker从我主页面的同一个域加载一个XML文件,任何帮助都将不胜感激。

function readXML(){
 var xhr = new XMLHttpRequest(); //Only for FF
 xhr.open("GET","../db/pointer.xml",true);
 xhr.send(null);
 xhr.onreadystatechange = function(e){

 if(xhr.status == 200 && xhr.readyState == 4){
    //Post back info to main page
    postMessage(xhr.responseXML.getElementsByTagName("value").length);
 }
}

当它在主页上的脚本标签中运行时,我得到一个3。 通过WebWorker运行时,FireBug给了我

  

hr.responseXML为空

     

的postMessage(xhr.responseXML.getElementsByTagName( “值”)的长度。);

在FireBug控制台中,GET请求以

响应
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <value>A value</value>
    <value>Another Value</value>
    <value>A third Value</value>
</root>

所以答案是正确的,但我无法弄清楚它出错的地方。 如果我将responseXML更改为responseText,则输出

  

值另一个值第三个值

哪个是对的!为什么脚本不会将其作为XML文档打开?

更新

function readXML(){
 var xhr = new XMLHttpRequest(); //Only for FF
 xhr.open("GET","../db/pointer.xml",false);
 xmlhttp.setRequestHeader('Content-Type',  'text/xml');
 xhr.overrideMimeType('text/xml');
 xhr.send(null);
 xhr.onreadystatechange = function(e){

 if(xhr.status == 200 && xhr.readyState == 4){
    //Post back info to main page
    postMessage(xhr.responseXML.getElementsByTagName("value").length);
 }
}

当setRequestHeader&amp; overrideMimeType被更改,onreadystatechange永远不会触发,无论status和readyState是否存在都无关紧要,它将不会运行。如果我完全删除onreadystatechange并运行xhr.responseXML,我再次得到null错误。

我仍然在控制台中获得正确的XML作为响应,这是一个webworker问题而不是httprequest问题吗?在这里绝望:)

index.html http://www.axlonline.se/worker/index.html
worker.js http://www.axlonline.se/worker/worker.js

3 个答案:

答案 0 :(得分:3)

根据标准,Web工作者无法访问任何类型的DOM操作。

  

此规范的此版本中的工作人员无法使用DOM API(节点对象,文档对象等)。

responseXML和channel属性在ajax请求中始终为null,因为XML的解析是DOM API。无论请求和响应标头如何,除非您手动解析它,否则无法获取requestXML。

答案 1 :(得分:1)

有同样的问题。显然,Web工作者无法进行XML解析。 我使用sax.js来解析web worker上的XML。 https://github.com/isaacs/sax-js

这基本上是我的解析器。

function xmlParser(strict){
    this.parser = sax.parser(strict, {lowercase:true});
}

xmlParser.prototype.parseFile = function(file, callback){
    var _this = this;
    $.ajax.get({
        cache: false,
        url: file,
        dataType: "xml",
        success: function(data){
            var dom = _this.parseText(data.text);
            callback( dom );
        },
        error: function(data){
        }
    });
}

xmlParser.prototype.parseText = function(xlmText){
    var dom = undefined;
    var activeNode = dom;

    this.parser.onerror = function (e) { };
    this.parser.onend = function () {};

    this.parser.ontext = function (t) {
        if(activeNode != undefined)
            activeNode.Text = t;
    };
    this.parser.onopentag = function (node) {
        var node = new xmlNode(node.name, activeNode, node.attributes, dom);
        if(dom === undefined){
            dom = node;
            activeNode = node;
        }else{
            activeNode.Children.push(node);
            activeNode = node;
        }
    };
    this.parser.onclosetag = function (node) {
        activeNode = activeNode.Parent;
    };

    this.parser.write(xlmText).close();
    return dom;
}

xmlNode启用类似于处理树的jquery。

function xmlFilterResult(){
    this.length = 0;
}

xmlFilterResult.prototype.push = function(element){
    this[this.length++] = element;
}

xmlFilterResult.prototype.attr = function(atribute){
    if(this.length == 0)
        return '';
    return this[0].Attributes[atribute];
}
xmlFilterResult.prototype.text = function(atribute){
    if(this.length == 0)
        return '';
    return this[0].Text;
}

xmlFilterResult.prototype.children = function(search, result){
    if(result == undefined)
        result = new xmlFilterResult();
    if(search == undefined){
        for(var i = 0; i < this.length; i++){
            this[i].children(search, result);
        }
    }else{
        this.find(search, true, result);
    }
    return result;
}
xmlFilterResult.prototype.find = function(search, nonrecursive, result){
    if(result == undefined)
        result = new xmlFilterResult();
    if(search.charAt(0) == '.')
        return this.findAttr('class', search.substring(1), nonrecursive, result);
    else if(search.charAt(0) == '#')
        return this.findAttr('id', search.substring(1), nonrecursive, result);
    else
        return this.findName(search, nonrecursive, result);
}
xmlFilterResult.prototype.findAttr = function(attr, value, nonrecursive, result){
    if(result == undefined)
        result = new xmlFilterResult();
    var child;
    for(var i = 0; i < this.length; i++){
        child = this[i];
        child.findAttr(attr, value, nonrecursive, result);
    }
    return result
}
xmlFilterResult.prototype.findName = function(name, nonrecursive, result){
    if(result == undefined)
        result = new xmlFilterResult();
    var child;
    for(var i = 0; i < this.length; i++){
        child = this[i];
        child.findName(name, nonrecursive, result);
    }
    return result
}
// xmlFilterResult.prototype.findID = function(id, nonrecursive){
    // var child, result = new xmlFilterResult();
    // for(var i = 0; i < this.length; i++){
        // child = this[i];
        // child.findID(id, nonrecursive, result);
    // }
    // return result
// }




function xmlNode(name, parent, atributes, root){
    this.Name = name;
    this.Children = [];
    this.Parent = parent;
    this.Attributes = atributes;
    this.Document = root;
    this.Text = '';
}

xmlNode.prototype.attr = function(atribute){
    return this.Attributes[atribute];
}
xmlNode.prototype.text = function(atribute){
    return this.Text;
}

xmlNode.prototype.children = function(search, result){
    if(result == undefined)
        result = new xmlFilterResult();
    if(search == undefined){
        for(i in this.Children)
            result.push(this.Children[i]);
    }else{
        return this.find(search, true, result);
    }
    return result;
}
xmlNode.prototype.find = function(search, nonrecursive, result){
    if(search.charAt(0) == '.')
        return this.findAttr('class', search.substring(1), nonrecursive, result);
    else if(search.charAt(0) == '#')
        return this.findAttr('id', search.substring(1), nonrecursive, result);
    else
        return this.findName(search, nonrecursive, result);
}
xmlNode.prototype.findAttr = function(attr, value, nonrecursive, result){
    var child, i;
    if(result == undefined)
        result = new xmlFilterResult();
    for(i in this.Children){
        child = this.Children[i];
        if(child.Attributes[attr] == value)
            result.push(child);
        if(!nonrecursive)
            child.findAttr(attr, value, nonrecursive, result);
    }
    return result
}
xmlNode.prototype.findName = function(name, nonrecursive, result){
    var child, i;
    if(result == undefined)
        result = new xmlFilterResult();
    for(i in this.Children){
        child = this.Children[i];
        if(child.Name == name){
            result.push(child);
        }
        if(!nonrecursive)
            child.findName(name, nonrecursive, result);
    }
    return result
}

它没什么特别的,但你明白了这一点。

答案 2 :(得分:-2)

您只需在服务器端将内容类型标头设置为text/xml即可。 如果您请求的文档不是XML,则responseXML为null。具体而言,内容类型应为text/htmltext/xmlapplication/xml之一,或以+xml结尾的内容。请参阅the spec

另请参阅:responseXML is nullresponseXML always null

请注意:由于Web worker本身是异步的,因此您无需在open调用中将async标志设置为true。