Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > e4xu

Всякие разные штуки сомнительной полезности сделанные в свободное от работы время.
Оценить эту запись

HaXe Работа с XML.

Запись от wvxvw размещена 15.01.2010 в 00:21
Обновил(-а) wvxvw 15.01.2010 в 00:58

Можно очень долго спорить о достоинствах и недостатках компиляторов, опасных и безопасных поинтерах, оптимизации и т.п. Но, для повседневной жизни как правило такие вещи мало на что влияют, а вот удобство и скорость разработки становятся гораздо важнее. Наверное для человека переходящего с AS2, JavaScript или PHP на HaXe Xml класс покажется вполне себе обычой штукой, ну и приятный момент - на всех платформах будет работать одинаково. Но уговорить себя отказаться от E4X очень тяжело. Естественно, для первой же разработки мне пришлось вплотную познакомится с имеющимися в наличии инструментами и подходами.

Итак, по-порядку:


Решение "в лоб" - использовать Xml класс.

Достоинства: не нужно изобретать велосипед, все вроде как работает и наверняка уже протестировано и пофиксено.
Недостатки: собственно, этот класс по своим API сильно напоминает аналогичный из AS2 - что значит куча вложеных циклов для нахождения нужного узла, аттрибуты не считаются за XML, может быть много корневых узлов. Отличия от AS2 класса: итераторы - но это отдельная тема. Сейчас оговорюсь о них только потому что в HaXe циклы устроены по-другому, и в свете поствленной задачи итераторы скорее неудачный подход т.как невозможно наперед узнать количество дочерних узлов. Т.е. можно использовать Lambda.count(myXml); но это вам не быстрый геттер а все та же итерация. Еще одно отличие - отсутствует свойство ignoreWhite. Т.е. если хотите получить XML без пустых текстовых узлов, то эти пустые текстовые узлы прийдется убирать руками. Еще одна немаловажная деталь - пространства имен никак не отрабатываются.

Пример:
Код:
var xml:Xml = Xml.parse("<a><b/><b/><b/></a>").firstElement();
var i:Iterator<Xml> = xml.elements();
while (i.hasNext()) trace(i.next());
Результат:
Код:
<b/>
<b/>
<b/>
Очевидно понимая эту ситуацию были придуманы эти два решения.


haxe.xml.Fast
http://haxe.org/doc/advanced/xml_fast
Это утилитный класс для более быстрой обработки XML. Он не быстрее обычного Xml, просто у него запись короче и некоторые циклы можно сократить.
Достоинства: как уже говорилось - меньше писанины.
Недостатки: Этот класс реализован в AS3 как любой другой пользовательский класс. Т.е. если его использовать, ваш SWF станет на несколько килобайт больше. И, откровенно говоря для записи сложных конструкций он малопригоден, т.е. выигрыш по сравнению с Xml будет минимальным. Еще один не совсем удачный момент - Fast основан на коллекциях типа List<Xml>, а Xml - на коллекциях типа Array<Null<Xml>> - т.е. они не очень друг с дугом совместимы.
Пример:
Код:
var xml:Xml = Xml.parse("<a><b/><b/><b/></a>").firstElement();
var fast:Fast = new Fast(xml);
for (p in fast.elements) trace(p.name);
Результат:
Код:
b
b
b

Скомпилировать AS3 и встроить или загрузить в HaXe.
Ну вот, за что боролись... опять для компиляции нужен JDK, куча времени и системных ресурсов... Да и сборки в несколько заходов как-то видятся малоприятным времяпровождением. Вобщем, для статического кода, который можно скомпилировать один раз и использовать всегда вроде как и ничего, но если этот код нужно компилировать на сервере по запросу - ситуация видится малоприятной.
Достоинства: используем любимый E4X, и потом, без особых усилий встраиваем его в нашу программу используя интринсик классы.
Недостатки: HaXe задумывался как средство программировать все на одном языке... а тут мы опять пишем платформозависимый код, да еще и делаем лишние усилия для того, чтобы его встроить...

Пример:
Код AS3:
package
{
	import flash.display.MovieClip;
 
	[SWF(backgroundColor='0xFFFFFF', frameRate='1', width='20', height='20')]
	public class CallE4X extends MovieClip
	{
		public function flashBrackets(data:* , func:Function):XMLList
		{
			return data.(func(valueOf()));
		}
	}
}
HaXe код вызывающий AS3 код (прошу прощения, это скопировано из чужого источника, я бы за такое руки поотрывал...) Но действующего варианта сейчас под рукой нету.
Код:
private function xmlloaded(event:Event):Void
{
	var info:XML = _xmlLoader.xml;
	var xmllist:XMLList = info.locations.child("*");
	for(i in 0...xmllist.length())
	{
		var func = function(data:XML):Bool
		{
			return data.attribute("y").toString() == "320" ||  
			data.attribute("x").toString() == "200";
		}
		var data:XML = xmllist[i];
		// AS3  Class CallE4X loaded into same ApplicationDomain
		var att:XMLList =  cast(_callE4X, CallE4X).flashBrackets(data, func).attribute('*');
		for (j in 0...att.length())
		{
			trace(att[j].name() + " " + att[j] + ' ' + i);
		}
	}
}

Так собственно и появился W.alk(Xml):
http://code.google.com/p/e4xu/source...vxvws/xml/W.hx
Что в нем пока что реализовано:
- последовательная разборка DOM влючающая детей, потомков, родителей, аттрибуты и текст.
- операция по нахождению одного узла или коллекции записывается в одну строку (на манер E4X) и выполняется в одно (продолжительное) действие.
- каждая операция состоит из под-операций в функциональном стиле. Т.е. можно добавить колбек, который будет вызван для каждого узла XML'я. (По моим тестам простые колбеки вроде как нормально инлайнятся, так что накладных расходов связаных с вызовами методов вроде как быть не должно).

Несколько примеров использования:
Код:
/**
* ...
* @author wvxvw
*/
package org.wvxvws;

import flash.Lib;
import flash.display.Sprite;
import org.wvxvws.xml.W;

class TestW extends Sprite
{
   private var _xml:Xml;
   
   public function new()
   {
      super();
      this._xml = Xml.parse("
      <a>
         <b/>
         <b/>
         <b>
            <c foo=\"bar0\">
               <d abcd=\"123\" qwerty=\"shouldn't catch\"/>
            </c>
            <c foo=\"bar1\"/>
            <c foo=\"bar2\">
               <d abcd=\"456\" qwerty=\"678\"/>
            </c>
            <c foo=\"bar3\"/>
         </b>
         <b/>
      </a>");
      
      // AS3 аналог: this._xml..*.(valueOf().@*.(toXMlString() == "bar2").length()).*.@qwerty;
      
      var a:Array<Hash<String>> = cast W.alk(this._xml).d().a(this.filter).c().a(this.filter2).z();
      
      trace(a); // TestW.hx 36: [{qwerty=>678}]
   }
   
   private inline function filter(attName:String, attValue:String, node:Xml):Bool
   {
      return attValue == "bar2";
   }
   
   private inline function filter2(attName:String, attValue:String, node:Xml):Bool
   {
      return attName == "qwerty";
   }
   
   public static function main() { Lib.current.addChild(new TestW()); }
}
Или вот, как сымитировать флешевый ignoreWhite:
Код:
this._removeWhite = ~/^[\t\s\r\n]*([^\t\s\r\n]+)*[\t\s\r\n]*$/g;
W.alk(this._xml).d().t(this.filterTexts);
....
private function filterTexts(text:String, node:Xml):Bool
{
   node.nodeValue = this._removeWhite.replace(text, "$1");
   return true;
}
Я еще до конца не разобрался с генератором документации, но как только разберусь, постараюсь написать доки и оформить как следует.
Размещено в HaXe
Комментарии 0 Отправить другу ссылку на эту запись
Всего комментариев 0

Комментарии

 

 


Часовой пояс GMT +4, время: 23:55.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.