Перевод: Андрей Горбатов (блог)

Оригинал статьи

1. Устанавливайте resultFormat="e4x" для HTTPService

По умолчанию, resultFormat для <mx:HTTPService> является "object". Но при получении XML данных, "object" - это не то, что вам нужно. Если же задать "e4x", то lastResult будет являтся XML объектом, который можно парсить с помощью E4X выражений.

2. E4X выражения не ссылаются на самый верхний тег XML

Итак, имеем <mx:HTTPService>, названный myService с resultFormat="e4x", возвращающим следующую структуру:

<?xml version="1.0"?>  
<people>    
	<person>mike</person>    
	<person>sho</person>    
	<person>nj</person>  
</people>

Эти данные содержатся в myService.lastResult (или в event.result.) Как получить XMLList всех элементов <person>?

Часто думают, что E4X выражения составляют от корневого тега <people>:

var personNodes:XMLList = myService.lastResult.people.person; // неправильно 

А правильно так :

var personNodes:XMLList = myService.lastResult.person; // правильно 

3. Используйте for each, а неfor

ECMAScript давно имеет структуру for (ключ в коллекции). Но обратите внимание, что при использовании этого выражения переменной цикла является ключ коллекции, а не значение текущего элемента, поэтому в цикле необходимо писать коллекция[ключ] для ображения к его значению.

E4X добавляет следующую структуру (которую можно использовать на любой коллекции): for each (значение в коллекции). Рассмотрим примеры:

for (var key:* in myService.lastResult.person)  {    

	var value:* = myService.lastResult.person[key];    
	...  
}

А теперь for each:

for each (var value:* in myService.lastResult.person)  {    ...  }

 

4. Используйте for each (child in parent.*), вместо for each (child in parent)

Итак, есть документ :

var mydocument:XML =    
<root>      
	<cat>        
		<mouse />        
		<mouse />        
		<mouse />      
	</cat>    
</root>  
var cats:XMLList = mydocument.cat; // это только один элемент

Теперь необходимо перебрать всех мышей у этого кота.

Чтобы получить атрибуты объекта ActionScript, можно написать следующее:

var o:Object = ...;  for each (var property:* in o) ...

Вы думаете, что следующим образом вы делаете тоже самое:

for each (var mouse:XML in cats) ... // неправильно 

Увы, E4X отличается. В E4X, "cats" - это коллекция -- список узлов <cat>, а в примере есть только один <cat>.

Поэтому, чтобы перебрать всех мышей необходимо использовать следующую структуру:

// перебрать все прямые дочерние элементы   
for each (var mouse:XML in cats.*) { ... }     
// или перебрать всех прямых потомков, которые являются узлами <mouse>  
for each (var mouse:XML in cats.mouse) { ... }

5. E4X специально стирает различия между XML и XMLList

При изучении E4X, вы узнаете, что есть два типа данных: XML и XMLList. Вроде легко, но потом появляются проблемы с неправильной типизацией данных.

var mydocument =    
<root>      
<rabbit name="Brownster Johansson McGee" />    
</root>;     
// 'mydocument.rabbit' - список всех узлов <rabbit>, значит  
// myPetRabbit должен быть XMLList?  Но я назвал переменную  
// 'myPetRabbit', а не 'myPetRabbits',  
// потому что я знаю, что заяц только один.
  
var myPetRabbit:XMLList = mydocument.rabbit;     
// Как же его зовут?  Почему следующее выражение не вызывает ошибки, 
//ведь myPetRabbit - это XMLList?  

trace(myPetRabbit.@name);

Причина в том, что E4X намеренно стирает различия между XML и XMLList. Каждый XMLList, который содержит один элемент, будет рассматриваться как XML. (Если 'myPetRabbit' будет содержать несколько узлов, то myPetRabbit.@name будет возвращать список всех атрибутов "name" все узлов <rabbit>.)

Например, рассмотрим документацию по методу XMLList.toString():

То есть если XMLList содержит <node>hello</node>, то toString() вернет "hello"; но если он содержит <node>hello</node><node>goodbye</node>, toString() вернет "<node>hello</node><node>goodbye</node>" (а не "hellogoodbye"). Если же вам всегда нужен полный XML, используйте toXMLString() вместо of toString().

6. Внимание! Простое выражение может вам дорого обойтись

При использовании простых объектов нет ничего удивительного в использовании следующего кода:

var x:Object = ...;  if (x.y.z == 3)    foo(x.y.z);

Код работает быстро, проблем не вознкает.

Но в E4X операция типа "x.y.z" будет означать, что цикл проходит через всю XML-структуру и ищет соответствующие совпадения:

var mydocument:XML = ...;  if (mydocument.cat.mouse.length() == 3)    foo(mydocument.cat.mouse);

This looks very similar to the plain-Object example, but the difference is that "mydocument.cat.mouse" is actually executing a whole lot of code behind the scenes. It has to walk through your XML structures, figure out which XML nodes match the given expression, and then create a new XMLList containing only those nodes.

Итак, если вам потом понадобиться использовать результат, то лучше сохранить его в XMLLis переменнойt:

var mydocument:XML = ...;  var mice:XMLList = mydocument.cat.mouse;  if (mice.length() == 3)    foo(mice);

7. Используйте дебаггер

Отладчик поможет вам разобраться в значениях XML и XMLList переменных.

XML variables