--- title: HTML in XMLHttpRequest slug: HTML_in_XMLHttpRequest ---
W3C XMLHttpRequest规范添加了XMLHttpRequest
对象对HTML解析的支持(原本只支持XML解析).这项特性允许开发者使用XMLHttpRequest
来获取一个HTML资源经过解析后的DOM对象.
为了避免用户使用XMLHttpRequest
的同步模式,HTML解析被设计为只支持异步模式.而且,只有当responseType
属性被设置为"document"
时,HTML解析才会开启.这种限制是为了避免当用户只需要获取 text/html
类型资源的responseText
属性时浏览器做无用的HTML解析而浪费时间.另外,该限制也同样可以避免在HTTP错误页面(通常是text/html
类型的响应)中responseXML
属性为空的情况.
使用XMLHttpRequest
时,把HTML资源作为DOM检索和把XML资源作为DOM检索的区别只有两点:1. 不可以使用同步模式. 2. 请求一个文档时,在调用open()
方法之后,send()
方法之前,必须明确的指定 XMLHttpRequest
对象的responseType
属性为字符串"document"
.
var xhr = new XMLHttpRequest(); xhr.onload = function() { alert(this.responseXML.title); } xhr.open("GET", "file.html"); xhr.responseType = "document"; xhr.send();
此方法依赖于该特性的限制之一,即"强制异步模式".如果在同步模式中将"document"赋值给XMLHttpRequest
对象的responseType
属性,浏览器将会抛出异常.
function HTMLinXHR() { if (!window.XMLHttpRequest) return false; var req = new window.XMLHttpRequest(); req.open('GET', window.location.href, false); try { req.responseType = 'document'; } catch(e) { return true; } return false; }
{{ JSFiddleLink('HTcKP/1/') }}
该方法是同步执行的,并且不需要依赖任何外部资源.但是,由于该方法是间接的检测浏览器是否支持XMLHttpRequest
对象的HTML解析特性,所以下面的检测方法2可能更加直接更加可靠一点.
如何准确的检测浏览器是否支持XMLHttpRequest
中的HTML解析有两个难点.首先,检测的结果只能在异步模式中获得,因为HTML解析只支持异步模式.其次,你必须真实的通过HTTP协议获取一个文件, 因为,如果使用data:
URL,测试会因浏览器是否支持data:
URL而受到影响.
因此,要检测浏览器是否支持XMLHttpRequest中的HTML解析,需要在服务器上放置一个测试用的HTML文件,该测试文件体积较小,并且不是格式良好的XML文件:
<title>&&<</title>
如果该文件被命名为detect.html
, 那么下面的函数可以用来检测浏览器是否支持XMLHttpRequest中的HTML解析:
function detectHtmlInXhr(callback) { if (!window.XMLHttpRequest) { window.setTimeout(function() { callback(false); }, 0); return; } var done = false; var xhr = new window.XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState == 4 && !done) { done = true; callback(!!(this.responseXML && this.responseXML.title && this.responseXML.title == "&&<")); } } xhr.onabort = xhr.onerror = function() { if (!done) { done = true; callback(false); } } try { xhr.open("GET", "detect.html"); xhr.responseType = "document"; xhr.send(); } catch (e) { window.setTimeout(function() { if (!done) { done = true; callback(false); } }, 0); } }
参数callback
是一个函数,如果浏览器支持HTML解析,那么该函数被异步调用的时候,true
会作为唯一的参数传给callback
,不支持的话,false
会作为唯一的参数传给callback.
{{ JSFiddleLink }}('xfvXR/1/')
如果HTTP响应头Content-Type
字段定义了字符的编码类型, 那么文档的编码类型将指定为该编码. 否则, 如果文档存在BOM(byte order mark), 那么该BOM所表示的编码将会被使用. 再否则, 如果文档的前1024个字节中存在meta
元素,并且指定了文档的编码类型,那么该编码将会被使用.如果这些都没有指定,那么文件将会按UTF-8编码识别.
{{ CompatibilityTable() }}
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
Support | 18 | 11 | --- | --- | {{ compatno() }} (535.14) |
Feature | Android | Firefox Mobile (Gecko) | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
Support | --- | 11 | --- | --- | --- |
{{ languages({"ja":"ja/HTML_in_XMLHttpRequest","en":"en/HTML_in_XMLHttpRequest"}) }}