Skip to content

Instantly share code, notes, and snippets.

@Simn
Created March 14, 2014 09:25
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Simn/9544643 to your computer and use it in GitHub Desktop.
Save Simn/9544643 to your computer and use it in GitHub Desktop.
Haxe abstract + macro Xml fun
import haxe.macro.Expr;
using haxe.macro.Tools;
abstract Fast(Xml) from Xml to Xml {
@:noCompletion public inline function new(xml:Xml) this = xml;
public var name(get,never):String;
inline function get_name() return this.nodeName;
public var elements(get,never):FastIterator;
inline function get_elements():FastIterator return this.elements();
public var element(get,never):ElementAccess;
function get_element():ElementAccess return new ElementAccess(this);
@:arrayAccess inline function attribute(s:String) return this.get(s);
@:arrayAccess inline function setAttribute<T>(s:String, value:String) return this.set(s, value);
@:op(-X) public function remove() {
if (this.parent != null) this.parent.removeChild(this);
}
@:op(A += B) public inline function addChild(s:String) {
this.addChild(Xml.parse(s).firstElement());
}
inline function toString() {
return this.toString();
}
}
abstract ElementAccess(Xml) {
public inline function new(xml:Xml) this = xml;
@:arrayAccess public inline function elementsNamed(s:String):FastIterator return this.elementsNamed(s);
}
abstract FastIterator(Iterator<Fast>) from Iterator<Fast> to Iterator<Fast> {
macro static public function where(ethis:ExprOf<FastIterator>, cond:ExprOf<Bool>) {
var f = macro function(element:Fast) return $cond;
var e = macro Fast.FastIterator.doFilter($ethis, $f);
trace(e.toString());
return e;
}
macro static public function find(ethis:ExprOf<FastIterator>, cond:ExprOf<Bool>) {
var f = macro function(element:Fast) return $cond;
var e = macro Fast.FastIterator.doFind($ethis, $f);
trace(e.toString());
return e;
}
function doFilter(f:Fast->Bool):FastIterator {
return [for (xml in this) if (f(xml)) xml].iterator();
}
function doFind(f:Fast->Bool):Fast {
for (xml in this) {
if (f(xml)) return xml;
}
return null;
}
@:arrayAccess function get(i:Int) {
var n = this.next();
while (i > 0) {
if (!this.hasNext()) return null;
n = this.next();
}
return n;
}
inline function next() return this.next();
}
class Main {
static function main() {
var xml = Xml.parse('<sales vendor="John">
<item type="peas" price="4" quantity="6"/>
<item type="carrot" price="3" quantity="10"/>
<item type="chips" price="5" quantity="3"/>
</sales>; ');
var sales:Fast = xml.firstElement();
// selectors
trace(sales.element["item"].find(element["type"] == "carrot")["quantity"]);
trace(sales["vendor"]);
// remove
-sales.element["item"][0];
// add
sales += '<item type="oranges" price="4"/>';
// selector + setter
sales.element["item"].find(element["type"] == "oranges")["quantity"] = "4";
for (it in sales.elements.where(Std.parseInt(element["price"]) < 5)) {
trace(it);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment