AS 2.0: XMLObject-Klasse
von luke_the_duke
am 27.04.07 um 14:22 (148 Hits)
Mit der XMLObject-Klasse lassen sich XML-Dateien laden. Im Unterschied zur XML-Klasse wird das Ergebnis jedoch gleich in eine Objekt-Struktur umgewandelt, so dass man statt mit ewigen childNodes[xy]-Ketten simpel mit den Tag- und Attributnamen auf einen Knoten, einen Wert oder ein Attribut zugreifen kann.
Die Klasse:
Code :
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 92class XMLObject { //Native onLoad public var onLoad: Function; //Loader Objects private var xml: XML; private var lv: LoadVars; //Constructor function XMLObject () { mx.events.EventDispatcher.initialize(this); addEventListener ("onLoad", this); } //Dispatcher Functions function dispatchEvent() {}; function addEventListener() {}; function removeEventListener() {}; //Broadcaster Function private function broadcastMessage(obj: Object, en: String): Void { obj.target = this; obj.type = en; dispatchEvent(obj); } //Adds Event-Listener public function addListener (obj): Void { addEventListener("onLoad", obj); } //Removes Event-Listener public function removeListener (obj): Void { removeEventListener("onLoad", obj); } //Load Funtion public function load (data: LoadVars, Url: String, Method: String, showSource: Boolean): Void { var p: XMLObject = this; xml = new XML(); xml.ignoreWhite = true; lv = new LoadVars (); lv = data; xml.onLoad = function () { if (showSource) trace (this); var obj: Object = p.getObj(this.firstChild); p.broadcastMessage(obj, "onLoad"); } lv.sendAndLoad(Url, xml, Method); } //Converts Node to Object, calls itself if node has Children private function nodeToObject (obj: Object, n: XMLNode): Void { var e: Number = n.childNodes.length; var l: Number = e; while (l--) { var node: XMLNode = n.childNodes[l]; var id: String = node.nodeName; if (node.hasChildNodes()) { var str: String = (obj[id]) ? id+"_"+(e-l): id; obj[str] = {}; nodeToObject (obj[str], node); for (var i: String in node.attributes) obj[str][i] = (typeof(node.attributes[i]) == "number") ? Number (node.attributes[i]): String (node.attributes[i]); } else if (node.nodeValue != null) obj.value = (typeof(node.nodeValue) == "number" || !isNaN(Number(node.nodeValue))) ? Number (node.nodeValue): String (node.nodeValue); } } //Starts convertion private function getObj (node: XMLNode): Object { var obj: Object = {}; nodeToObject(obj, node); return obj; } }
Konstruktor:
Code :
1 var xmObject = new XMLObject();
Methoden:
load (Data: LoadVars, Url: String, Method: String, showSource: Boolean): Void
Diese Funktion lädt eine XML-Datei in die Instanz der XMLObject-Klasse.
Parameter:
Data: Ein LoadVars-Objekt, in dem alle benötigten Parameter gespeichert sind.
Url: String, URL der XML-Datei.
Method: Methode, mit der die Lade-Aktion durchgeführt wird ("GET" oder "POST").
showSource: Optional. Wenn showSource auf true gesetzt wird, printet das XMLObject die ursprünglich geparste XML-Datei ins Ausgabe-Fenster.
addListener (ZielObjekt: Object): Void
Mit diese Methode können weitere Objekte als Event-Listener des enstprechenden XMLObjects registriert werden.
Parameter:
ZielObjekt: Object. Ein Listener-Objekt, auf dem die Event-Methoden des XMLObjects aufgerufen werden
removeListener (ZielObjekt: Object): Void
Mit dieser Methode wird ein Objekt aus der Liste der Listener entfernt.
Parameter:
ZielObjekt: Object. Name des Objekts, das ausgetragen werden soll.
Ereignisse:
onLoad = function (dataObject: Object)
Wird aufgerufen, wenn die XML-Datei komplett geladen, geparst und umgewandelt ist
Parameter:
dataObject: Object, das die umgewandelte XML-Struktur beinhaltet
Ich habe bei der Programmation ein paar Konventionen festlegen müssen, ich erkläre das Teil und seine Macken am besten an einem Beispiel. Folgendes XML-Dokument wollen wir in Flash umsetzen:
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <xm> <person id="1"> <vorname>Hans</vorname> <name>Muster</name> <beruf>Informatiker</beruf> </person> <person id="2"> <vorname>Veronica</vorname> <name>Beispiel</name> <beruf>Floristin</beruf> </person> <person id="3"> <vorname>Hermann</vorname> <name>Vorlage</name> <beruf>Sachbearbeiter</beruf> </person> </xm>
Nun erstellen wir ein XMLObject mit einem Lade-Aufruf inkl. LoadVars und Parameter und einer onLoad-Funktion:
Code :
1 2 3 4 5 6 7 8 9 10var xmlData: XMLObject = new XMLObject(); xmlData.onLoad = function (obj: Object) { for (var i: String in obj) trace (i+": "+obj[i]); } var lv: LoadVars = new LoadVars(); lv.id = "5"; xmlData.load(lv, "meineXMLDatei.xml", "GET", true);
Konvention 1:
Jede XML-Datei, die mit dem XMLObject geparst werden will, muss über einen Mutterknoten verfügen, der über allen anderen Knoten steht. In unserem Beispiel wäre das nun der xm-Knoten.
Die Ausgabe dieses Codes sollte etwa so aussehen:
Code :
1 2 3 person: Object person_2: Object person_3: Object
Und hier wird schon Konvention 2 ersichtlich:
Verfügt ein Knoten über mehrere Kindknoten gleichen Namens, wird das erste Kind-Objekt wie der Tagname getauft, alle folgenden jedoch mit einem Affix versehen, dass sich aus einem Tiefstrich und einer fortlaufend inkrementierten Zahl zusammensetzt.
Spielen wir das Beispiel mit einer etwas modifizierten onLoad-Ausgabe durch:
Code :
1 2 3xmlData.onLoad = function (obj: Object) { for (var i: String in obj.person) trace (i+": "+obj.person[i]); }
Diese Ausgabe sieht nun so aus:
Code :
1 2 3 4 vorname: Object name: Object beruf: Object id: 1
Da in jedem Person-Knoten jeder Tagname nur einmal vorkommt, wird auch kein Objekt mit einem Affix versehen.
Und nun kommen wir zur dritten und vierten Konvention:
Attribute werden wie auch Kindknoten direkt als Member des Mutterknotens eingetragen und mit dem entsprechenden Wert belegt.
Der Inhalt von Knotenpunkten, die über einen Text als Kindknoten verfügen, also das letzte Glied in der Reihe sind, kann dieser Text über das Member-Objekt value aufgerufen werden. Das mag ein wenig unschön erscheinen, ist aber unumgänglich (man belehre mich eines Besseren), da bei der Diagnose auch ein Textknoten als Kindknoten gewertet wird.
Mit folgender letzter onLoad-Funktion referenziere ich abssolut drei verschiedene Werte:
- Das id-Attribut des ersten person-Knotens
- Den Beruf des zweiten person-Knotens
- Den Vor- und Nachnamen des dritten Knotens
Code :
1 2 3 4 5xmlData.onLoad = function (obj: Object) { trace (obj.person.id); trace (obj.person_2.beruf.value); trace (obj..person_3.vorname.value+" "+obj.person_3.name.value); }
Auf das die Klasse eure Arbeit mit XML und Flash erleichtern möge.
VIel Spass!




.

