aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/xmlhttprequest/html_in_xmlhttprequest/index.html
blob: 74e8cac761d2f5584d9a4f8fd4f9f1ef8bc4fb3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
---
title: HTML in XMLHttpRequest
slug: Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest
translation_of: Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest
---
<p>W3C {{domxref("XMLHttpRequest")}} 规范为 <a href="/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a>添加HTML语法解析功能, 此前仅支持XML语法解析。该功能允许Web应用程序使用<code>XMLHttpRequest作为解析的DOM。</code></p>

<h2 id="局限">局限</h2>

<p>为了阻止同步使用XMLHttpRequest,HTML在同步模式下不支持使用。并且,只有当responseType属性设置为'document'的情况下,HTML支持才可用。这种限制避免了浪费时间解析HTML,而传统代码在默认模式下使用XMLHttpRequest来检索text/html资源的responseText. 此外,该限制避免了遗留代码的问题,该代码假定Http错误页面(通常具有text/html响应正文)的responseXML为空。</p>

<h2 id="用法">用法</h2>

<p>使用XMLHttpRequest将HTML资源恢复为DOM就像使用XMLHttpRequest将XML资源恢复为DOM一样,除了您不能使用同步模式,您必须通过将字符串“document”分配给responseType属性来显式请求文档调用open()之后调用send()之前的XMLHttpRequest对象。</p>

<p> </p>

<pre class="brush: js">var xhr = new XMLHttpRequest();
xhr.onload = function() {
  console.log(this.responseXML.title);
}
xhr.open("GET", "file.html");
xhr.responseType = "document";
xhr.send();
</pre>

<h2 id="功能检测">功能检测</h2>

<h3 id="方法1">方法1</h3>

<p>该方法依赖于功能的“强制异步”性质。当你尝试设置一个以“sync”方式打开的XMLHttpRequest对象后,尝试将设置responseType会在实现该功能的浏览器上引发错误,其他浏览器则运行良好。</p>

<div class="line" id="LC13">
<pre class="brush: js">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;
}
</pre>
</div>

<p><a href="https://jsfiddle.net/HTcKP/1/">在JSFiddle中查看</a></p>

<p>This method is synchronous, does not rely on external assets though it may not be as reliable as method 2 described below since it does not check the actual feature but an indication of that feature.</p>

<h3 id="方法2">方法2</h3>

<p> </p>

<p>检测浏览器是否支持XMLHttpRequest中的HTML解析有两个挑战。首先,检测结果是异步获取的,因为HTML支持仅在异步模式下可用。Second, you have to actually fetch a test document over HTTP, because testing with a <code>data:</code> URL would end up testing <code>data:</code>URL support at the same time.</p>

<p>因此,为了检测HTML支持,服务器上需要一个测试HTML文件。这个测试文件很小,格式不是很完整:</p>

<pre class="brush: js">&lt;title&gt;&amp;amp;&amp;&lt;&lt;/title&gt;</pre>

<p>如果文件名为detect.html,以下功能可用于检测HTML解析支持:</p>

<pre class="brush: js">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 &amp;&amp; !done) {
      done = true;
      callback(!!(this.responseXML &amp;&amp; this.responseXML.title &amp;&amp; this.responseXML.title == "&amp;&amp;&lt;"));
    }
  }
  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);
  }
}
</pre>

<p>参数callback是一个函数,如果HTML解析是支持的,则将以true作为唯一参数被异步调用,如果不支持HTML解析,则为false。</p>

<p><a href="https://jsfiddle.net/xfvXR/1/">在JSFiddle中查看</a></p>

<h2 id="字符编码">字符编码</h2>

<p>如果在HTTP Content-Type 头部中声明了字符编码,则使用该字符编码。否则,如果存在字节顺序标记,则使用由字节顺序标记指示的编码。否则,如果有一个meta tag声明文件的前1024个字节中的编码,则使用该编码。否则,文件被解码为UTF-8。</p>

<h2 id="老版本的浏览器中处理HTML">老版本的浏览器中处理HTML</h2>

<p>XMLHttpRequest最初只支持XML解析。 HTML解析支持是最近的一个补充。对于较老的浏览器,您甚至可以使用与正则表达式关联的responseText属性,以获取例如已知其ID的HTML元素的源代码:</p>

<pre class="brush: js">function getHTML (oXHR, sTargetId) {
  var  rOpen = new RegExp("&lt;(?!\!)\\s*([^\\s&gt;]+)[^&gt;]*\\s+id\\=[\"\']" + sTargetId + "[\"\'][^&gt;]*&gt;" ,"i"),
       sSrc = oXHR.responseText, aExec = rOpen.exec(sSrc);

  return aExec ? (new RegExp("(?:(?:.(?!&lt;\\s*" + aExec[1] + "[^&gt;]*[&gt;]))*.?&lt;\\s*" + aExec[1] + "[^&gt;]*[&gt;](?:.(?!&lt;\\s*\/\\s*" + aExec[1] + "\\s*&gt;))*.?&lt;\\s*\/\\s*" + aExec[1] + "\\s*&gt;)*(?:.(?!&lt;\\s*\/\\s*" + aExec[1] + "\\s*&gt;))*.?", "i")).exec(sSrc.slice(sSrc.indexOf(aExec[0]) + aExec[0].length)) || "" : "";
}

var oReq = new XMLHttpRequest();
oReq.open("GET", "yourPage.html", true);
oReq.onload = function () { console.log(getHTML(this, "intro")); };
oReq.send(null);
</pre>

<div class="note"><strong>注:</strong> 该解决方案对于解释器来说更为昂贵. <strong>仅在确实需要的情况下使用</strong>.</div>

<h2 id="Specifications">Specifications</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('XMLHttpRequest')}}</td>
   <td>{{Spec2('XMLHttpRequest')}}</td>
   <td>Initial definition</td>
  </tr>
 </tbody>
</table>

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{CompatibilityTable}}</p>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari (WebKit)</th>
  </tr>
  <tr>
   <td>Support</td>
   <td>18</td>
   <td>{{CompatGeckoDesktop("11.0")}}</td>
   <td>10</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatNo}}<br>
    {{CompatVersionUnknown}}<sup>[1]</sup></td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Phone</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>Support</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatGeckoMobile("11.0")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
 </tbody>
</table>
</div>

<p>[1] This feature was implemented in {{WebKitBug("74626")}}.</p>