比較修改

使用 E4X 處理 XML

版本 272798:

Revision 272798 by superwulei on

版本 210270:

Revision 210270 by superwulei on

標題:
使用 E4X 處理 XML
使用 E4X 處理 XML
URL代稱:
E4X/使用_E4X_處理_XML
E4X/使用_E4X_處理_XML
內容:

修訂版本 272798
修訂版本 210270
t7    <p>t
8      {{ Js_minversion_header("1") }}
9    </p>
10    <h2 id="使用_E4X_處理_XML" name="使用_E4X_處理_XML">
11      使用 E4X 處理 XML
12    </h2>
13    <p>
14      JavaScript 在 1.6 版本中首次引入,<strong><a class="internal" href="
>/zh_tw/E4X" title="zh tw/E4X">E4X</a></strong> 引入原生的 XML 物件以供 Jav 
>aScript 語言使用,並新增用來在 JavaScript 的代碼中嵌入照字面表達的 XML 文件的語法。 
15    </p>
16    <p>
17      E4X 的完整定義可以在 <a class="external" href="http://www.ecma-inte
>rnational.org/publications/standards/Ecma-357.htm">Ecma-357 規範</a 
>> 中找到。本章提供實踐中的語言概要;但這並不是全面的參考資料。 
18    </p>
19    <h3 id="相容性的問題" name="相容性的問題">
20      相容性的問題
21    </h3>
22    <p>
23      在主要的瀏覽器支援 <code>&lt;script&gt;</code> 元素以前,對於嵌入到頁面裡的 JavaSc
>ript 存有一種常見的做法,就是使用 HTML 的註解標籤將其包夾,避免瀏覽器直接把 <code>&lt;script&gt;< 
>/code> 裡的 JavaScript 代碼顯示在使用者眼前。如今已無須這麼做,不過仍殘存在部分遺留下來的代碼中。為了向後相容的 
>需要,E4X 預設會忽略註解和 CDATA 區段。你可以給你的 <code>&lt;script&gt;</code> 標籤加上  
><code>e4x=1</code> 參數以解除這項限制︰ 
24    </p>
25    <pre>
26&lt;script type="text/javascript;e4x=1"&gt;
27...
28&lt;/script&gt;
29</pre>
30    <h3 id="XML_物件的建立" name="XML_物件的建立">
31      XML 物件的建立
32    </h3>
33    <p>
34      E4X 提供兩種建立 XML 物件的方式。第一種是傳入字串給 <code>XML</code> 建構子︰
35    </p>
36    <pre class="eval">
37 var languages = new XML('&lt;languages type="dynamic"&gt;&lt;lan
>g&gt;JavaScript&lt;/lang&gt;&lt;lang&gt;Python&lt;/lang&gt;&lt;/l 
>anguages&gt;'); 
38</pre>
39    <p>
40      第二種是直接在你的 Script 中嵌入 XML︰
41    </p>
42    <pre class="eval">
43 var languages = &lt;languages type="dynamic"&gt;
44   &lt;lang&gt;JavaScript&lt;/lang&gt;
45   &lt;lang&gt;Python&lt;/lang&gt;
46 &lt;/languages&gt;;
47</pre>
48    <p>
49      在這兩種情況裡,產生都會是 E4X <code>XML</code> 物件,他提供了方便的語法用以存取並更新其內夾藏著
>的資料。 
50    </p>
51    <p>
52      XML 物件在外觀上和行為上都和普通的 JavaScript 物件很類似,但有兩件事並不相同。E4X 引入的新語法只能
>用在 E4X XML 物件上。雖然新語法被設計成對 JavaScript 設計者而言較熟悉的形式,但 E4X 並不提供從 XML  
>到原生 JavaScript 物件的完整對應;只是看起來很像而已。 
53    </p>
54    <p>
55      可以把變數加入到 XML 的字面中用來建立元素的名稱(或是內容)。
56    </p>
57    <pre>
58var h = 'html';
59var text = "Here's some text";
60var doc = &lt;{h}&gt;&lt;body&gt;{text}&lt;/body&gt;&lt;/{h}&gt;;
61alert(doc.toXMLString());
62// 產生的是
63&lt;html&gt;
64  &lt;body&gt;Here's some text&lt;/body&gt;
65&lt;/html&gt;
66</pre>
67    <h3 id="屬性的運用" name="屬性的運用">
68      屬性的運用
69    </h3>
70    <p>
71      當你需要動態的建立標記的時候,XML 字面語法明顯更勝 <code>XML</code> 建構子。使用 E4X 可輕易
>的在標記中嵌入動態值。只需使用花括弧 ({}) 包夾要建立的屬性值,並省略一般會加上的引號標記,變數和表達式即可用於建立屬性值,如 
>同下例所示︰ 
72    </p>
73    <pre class="eval">
74 var a = 2;
75 var b = &lt;foo bar={a}&gt;"hi"&lt;/foo&gt;;
76</pre>
77    <p>
78      開始執行時,變數的值會被求出,並自動在適當的位置加上引號。前面的例子產生的 XML 物件看起來就像這樣︰<code>&
>lt;foo bar="2"&gt;"hi"&lt;/foo&gt;</code>。 
79    </p>
80    <p>
81      在屬性的替換方面,雙引號會被跳脫成 &amp;quot;,單引號則按平常方式處理。
82    </p>
83    <pre class="eval">
84var b = 'He said "Don\'t go there."';
85var el = &lt;foo a={b}/&gt;;
86alert(el.toXMLString());
87// 產生︰&lt;foo a="He said &amp;quot;Don't go there.&amp;quot;"/&gt
>; 
88</pre>
89    <p>
90      小於和 &amp; 符號也會被跳脫成各自的等價實體。由於大於符號不會被跳脫,因此如果包含了 <a class="int
>ernal" href="/zh_tw/DOM/CDATASection" title="zh tw/DOM/CDATASecti 
>on">CDATA</a> 結束序列 (]]&gt;),就有可能產生 XML 錯誤。 
91    </p>
92    <p>
93      通常不會直接在字面(或變數)的屬性內容之中作修改(例如,<code>bar="a{var1}{var2}"</code
>>)。如果有必須使用 JavaScript 表達式計算變數來替代的內容的話(例如,<code>bar={'a'+var1+var2 
>}</code>),在元素字面之前先定義新的變數,在變數中包含完整的修改內容,然後在字面中含入這個變數,或在字面之後取回屬性並將其 
>修改(見下)。 
94    </p>
95    <p>
96      可如同屬性值一般的修改屬性的名稱︰
97    </p>
98    <pre>
99var a = 'att';
100var b = &lt;b {a}='value'/&gt;;
101alert(b);
102// Gives:
103&lt;b att="value"/&gt;
104 
105</pre>
106    <p>
107      …但之後就不能修改表達式(例如,&lt;b {a}&gt;)。
108    </p>
109    <p>
110      執行上面的例子之後,參考 XML 物件的語言變數與 XML 文件中的 <code>&lt;languages&gt;<
>/code> 結點一致。這個結點只有一個屬性︰type,這個屬性可用各種方式來存取並更新︰ 
111    </p>
112    <pre class="eval">
113 alert(languages.@type); // 警報 "dynamic"
114 languages.@type = "agile";
115 alert(languages.@type); // 警報 "agile"
116</pre>
117    <pre class="eval">
118 alert(languages.toString());
119 /* 警報:
120   &lt;languages type="agile"&gt;&lt;lang&gt;JavaScript&lt;/lang&
>gt;&lt;lang&gt;Python&lt;/lang&gt;&lt;/languages&gt; 
121 */
122</pre>
123    <p>
124      注意,如果想要把取回的屬性與其他的字串作比較,就有必要先把屬性作轉換,即使屬性有可能會在其他地方被轉換成字串(例如插入
>到文字框中)。 
125    </p>
126    <pre class="eval">
127if (<a class=" link-mailto" href="mailto:languages.@type.toString
>()" rel="freelink">languages.@type.toString()</a> === 'agile') { 
128 ...
129}
130</pre>
131    <h3 id="XML_物件的運用" name="XML_物件的運用">
132      XML 物件的運用
133    </h3>
134    <p>
135      XML 物件提供一系列的方法用來查閱並更新其中的內容。這類物件亦支援 JavaScript 的點 (.) 和 <cod
>e>[]</code> 符號,但不是用來存取物件的屬性,E4X 覆蓋了這些運算子,改用來存取元素的子結點︰ 
136    </p>
137    <pre>
138var person = &lt;person&gt;
139  &lt;name&gt;Bob Smith&lt;/name&gt;
140  &lt;likes&gt;
141    &lt;os&gt;Linux&lt;/os&gt;
142    &lt;browser&gt;Firefox&lt;/browser&gt;
143    &lt;language&gt;JavaScript&lt;/language&gt;
144    &lt;language&gt;Python&lt;/language&gt;
145  &lt;/likes&gt;
146&lt;/person&gt;;
147 
148alert(person.name); // Bob Smith
149alert(person['name']); // Bob Smith
150alert(person.likes.browser); // Firefox
151alert(person['likes'].browser); // Firefox
152</pre>
153    <p>
154      如果你使用多於一個以上的元素來存取的話,你會得到 <code>XMLList</code>︰
155    </p>
156    <pre>
157alert(person.likes.language.length()); // 2
158</pre>
159    <p>
160      和 DOM 一樣,<code>*</code> 可以用來存取所有的子結點︰
161    </p>
162    <pre>
163alert(person.likes.*.length()); // 4
164</pre>
165    <p>
166      <code>.</code> 運算子會直接存取指定結點的子結點,<code>..</code> 運算子則會存取所有的子
>結點,不論嵌入的有多深︰ 
167    </p>
168    <pre>
169alert(person..*.length()); // 11
170</pre>
171    <p>
172      <code>length()</code> 方法在此返回 11,因為元素結點和文字結點兩者都被包含在 <code>XM
>LList</code> 的結果中。 
173    </p>
174    <p>
175      用來表示 XML 元素的物件提供一系列實用的方法,部分方法的解說見下︰<span class="comment">TO
>DO: Add all of the methods to the JavaScript reference, link from 
> here</span> 
176    </p>
177    <pre>
178alert(person.name.text()) // Bob Smith
179 
180var xml = person.name.toXMLString(); // 內含 XML 的字串
181 
182var personCopy = person.copy(); // XML 物件的深層複製
183 
184var child = person.child(1); // 第二個子結點;目前是 &lt;likes&gt; 元素
185</pre>
186    <h3 id="XMLLists_的運用" name="XMLLists_的運用">
187      XMLLists 的運用
188    </h3>
189    <p>
190      除了 XML 物件以外,E4X 也引入了 <code>XMLList</code> 物件。<code>XMLList<
>/code> 是用來表示附有編號的 XML 物件的集合;例如,元素的列表。接續上面的例子,我們可以在頁面上存取 <code>XML 
>List</code> 的 <code>&lt;lang&gt;</code> 元素如下︰ 
191    </p>
192    <pre class="eval">
193 var langs = languages.lang;
194</pre>
195    <p>
196      <code>XMLList</code> 提供 <code>length()</code> 方法,可用來查出內含元素的
>數目︰ 
197    </p>
198    <pre class="eval">
199 alert(languages.lang.length());
200</pre>
201    <p>
202      注意,有別於 JavaScript 陣列的 length 屬性,這個 length 是方法,不是屬性,而且必須使用 <
>code>length()</code> 來呼叫。 
203    </p>
204    <p>
205      我們可以迭代所有相配的元素,就像這樣︰
206    </p>
207    <pre class="eval">
208 for (var i = 0; i &lt; languages.lang.length(); i++) {
209     alert(languages.lang[i].toString());
210 }
211</pre>
212    <p>
213      在此我們使用同一個語法存取陣列中的已編號項。雖然這部分很類似普通的陣列,但 <code>XMLList</code> 
>並不支援 <code>Array</code> 的方法,如 <code>forEach</code>,且陣列的通用功能,如 <co 
>de>Array.forEach()</code> 也不相容於 <code>XMLList</code> 物件。 
214    </p>
215    <p>
216      我們也可以使用在 JavaScript 1.6 中所引入的 <a class="internal" href="/zh
>_tw/Core_JavaScript_1.5_%E5%8F%83%E8%80%83/%E8%AA%9E%E6%B3%95/for 
>_each...in" title="zh tw/Core JavaScript 1.5 參考/語法/for each...in" 
>>for each...in 語法</a>,他已支援 E4X 的部分︰ 
217    </p>
218    <pre class="eval">
219 for each (var lang in languages.lang) {
220     alert(lang);
221 }
222</pre>
223    <p>
224      <code>for each...in</code> 也可以用在普通的 JavaScript 物件,迭代出內含在物件中
>的值(不是鍵)。如同 <a class="internal" href="/zh_tw/Core_JavaScript_1.5_% 
>E5%8F%83%E8%80%83/%E8%AA%9E%E6%B3%95/for...in" title="zh tw/Core  
>JavaScript 1.5 參考/語法/for...in">for...in</a>,<a href="/en/Core_Jav 
>aScript_1.5_Reference/Statements/for...in#Description" title="en/ 
>Core_JavaScript_1.5_Reference/Statements/for...in#Description">非常 
>不建議</a> 和陣列一起使用。 
225    </p>
226    <p>
227      可以使用下面的 XML 字面語法來建立 <code>XMLList</code>,而無須建立格式正確的 XML 文件︰
228    </p>
229    <pre class="eval">
230 var xmllist = &lt;&gt;
231   &lt;lang&gt;JavaScript&lt;/lang&gt;
232   &lt;lang&gt;Python&lt;/lang&gt;
233 &lt;/&gt;;
234</pre>
235    <p>
236      <code>+=</code> 運算子可用來把新的元素附加到文件中的 <code>XMLList</code>︰
237    </p>
238    <pre class="eval">
239 languages.lang += &lt;lang&gt;Ruby&lt;/lang&gt;;
240</pre>
241    <p>
242      注意,有別於由普通的 DOM 方法所返回的結點列表,<code>XMLList</code> 只是靜態的,而且不會自動
>更新以反映在 DOM 中的改變。如果你在既有的 <code>XML</code> 物件底下建立 <code>XMLList</co 
>de> 作為子集,<code>XMLList</code> 並不會反映 XML 物件的改變;你需要重新建立 XMLList 以取得 
>最近的更新︰ 
243    </p>
244    <pre class="eval">
245 var languages = &lt;languages&gt;
246   &lt;lang&gt;JavaScript&lt;/lang&gt;
247   &lt;lang&gt;Python&lt;/lang&gt;
248 &lt;/languages&gt;;
249 
250 var lang = languages.lang;
251 alert(lang.length()); // 警報 2
252 
253 languages.lang += &lt;lang&gt;Ruby&lt;/lang&gt;;
254 alert(lang.length()); // 仍舊警報 2
255 
256 lang = languages.lang; // 重新建立 XMLList
257 alert(lang.length()); // 警報 3
258</pre>
259    <h3 id="搜尋和過濾" name="搜尋和過濾">
260      搜尋和過濾
261    </h3>
262    <p>
263      E4X 提供特殊的運算子用來在通過指定條件的文件內部選取結點。這種過濾動作是由括弧裡面的表達式所指定的︰
264    </p>
265    <pre>
266var html = &lt;html&gt;
267  &lt;p id="p1"&gt;First paragraph&lt;/p&gt;
268  &lt;p id="p2"&gt;Second paragraph&lt;/p&gt;
269&lt;/html&gt;;
270 
271alert(html.p.(@id == "p1")); // 警報 "First paragraph"
272</pre>
273    <p>
274      在表達式前面比對路徑的結點(在本例中即 p 元素)會在表達式求值之前先加上作用域的限縮。就如同已經用 <a class
>="internal" href="/zh_tw/Core_JavaScript_1.5_%E5%8F%83%E8%80%83/% 
>E8%AA%9E%E6%B3%95/with" title="zh tw/Core JavaScript 1.5 參考/語法/wi 
>th">with 語法</a> 指定了一樣。 
275    </p>
276    <p>
277      因此,過濾器也可以依據在目前元素中內含的單一結點的值來執行︰
278    </p>
279    <pre>
280var people = &lt;people&gt;
281  &lt;person&gt;
282    &lt;name&gt;Bob&lt;/name&gt;
283    &lt;age&gt;32&lt;/age&gt;
284  &lt;/person&gt;
285  &lt;person&gt;
286    &lt;name&gt;Joe&lt;/name&gt;
287    &lt;age&gt;46&lt;/age&gt;
288  &lt;/person&gt;
289&lt;/people&gt;;
290 
291alert(people.person.(name == "Joe").age); // 警報 46
292</pre>
293    <p>
294      也可以使用 JavaScript 函數當作過濾器的表達式︰
295    </p>
296    <pre>
297function over40(i) {
298    return i &gt; 40;
299}
300 
301alert(people.person.(over40(parseInt(age))).name); // 警報 Joe
302</pre>
303    <h3 id="命名空間的處理" name="命名空間的處理">
304      命名空間的處理
305    </h3>
306    <p>
307      E4X 也全面考慮到命名空間。任何代表結點或屬性的 XML 物件都提供了可返回 <code>QName</code> 
>物件的 <code>name()</code> 方法,使加上命名空間的元素的查詢更為容易。 
308    </p>
309    <h4 id="預設" name="預設">
310      預設
311    </h4>
312    <pre>
313default xml namespace = "http://www.w3.org/1999/xhtml";
314// 目前還沒有必要在 HTML 標記裡指定命名空間
315var xhtml = &lt;html&gt;&lt;head&gt;&lt;title&gt;&lt;/title&gt;&l
>t;/head&gt;&lt;body&gt; 
316            &lt;p&gt;text&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;;
317alert(xhtml.head); // 目前還沒有必要在此處的子元素中指定命名空間
318</pre>
319    <h4 id="非預設" name="非預設">
320      非預設
321    </h4>
322    <pre>
323var xhtml = &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
324        &lt;head&gt;
325                &lt;title&gt;Embedded SVG demo&lt;/title&gt;
326        &lt;/head&gt;
327        &lt;body&gt;
328                &lt;h1&gt;Embedded SVG demo&lt;/h1&gt;
329                &lt;svg xmlns="http://www.w3.org/2000/svg" 
330                        viewBox="0 0 100 100"&gt;
331                        &lt;circle cx="50"
332                                cy="50"
333                                r="20"
334                                stroke="orange"
335                                stroke-width="2px"
336                                fill="yellow" /&gt;
337                &lt;/svg&gt;
338        &lt;/body&gt;
339&lt;/html&gt;;
340 
341alert(xhtml.name().localName); // 警報 "html"
342alert(xhtml.name().uri); // 警報 "http://www.w3.org/1999/xhtml"
343</pre>
344    <p>
345      若要存取非預設命名空間內部的元素,首先建立 <code>Namespace</code> 物件把特定的命名空間的 UR
>I 加以封裝︰ 
346    </p>
347    <pre>
348var svgns = new Namespace('http://www.w3.org/2000/svg');
349</pre>
350    <p>
351      目前可以在 E4X 中使用 <code>namespace::localName</code> 代替一般的元素指定子來
>作查詢︰ 
352    </p>
353    <pre>
354var svg = xhtml..svgns::svg;
355alert(svg); // 顯示文件中的 &lt;svg&gt; 部分
356</pre>
357    <h2 id="參閱" name="參閱">
358      參閱
359    </h2>
360    <ul>
361      <li>
362        <a class="internal" href="/zh_tw/E4X" title="zh tw/E4X">E
>4X</a> 
363      </li>
364      <li>
365        <a class="internal" href="/zh_tw/E4X_%E6%95%99%E5%AD%B8" 
>title="zh tw/E4X 教學">E4X 教學</a> 
366      </li>
367    </ul>
368    <p>
369      {{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Process
>ing_XML_with_E4X", "zh-cn": "cn/Core_JavaScript_1.5_Guide/Process 
>ing_XML_with_E4X", "fr": "fr/Guide_JavaScript_1.5/Traitement_de_X 
>ML_avec_E4X", "ja": "ja/Core_JavaScript_1.5_Guide/Processing_XML_ 
>with_E4X" } ) }} 
370    </p>

回到編輯歷史