Das Verabeiten von XML-Daten in AS3 ist meiner Ansicht nach einfacher als in AS2. Hier ein einfaches Beispiel:
XML bei Adobe
Hier werden 2 Möglichkeiten vorgestellt eine XML Datei zu laden und diese Daten in ein Array oder Objekt zu packen. Als erstes über eine for Schleife und als zweite, wesentlich sinnvollere Methode über eine for each in Schleife.
<?xml version="1.0" encoding="utf-8"?>
<bilder>
<bild id="1">
<dateiname>img/img_01.jpg</dateiname>
<blende>8.0</blende>
<belichtung>1/250</belichtung>
<iso>200</iso>
<datum>11.11.2011</datum>
</bild>
<bild id="2">
<dateiname>img/img_02.jpg</dateiname>
<blende>5.0</blende>
<belichtung>1/250</belichtung>
<iso>200</iso>
<datum>11.11.2011</datum>
</bild>
<bild id="3">
<dateiname>img/img_03.jpg</dateiname>
<blende>4.0</blende>
<belichtung>1/250</belichtung>
<iso>200</iso>
<datum>11.11.2011</datum>
</bild>
<bild id="4">
<dateiname>img/img_04.jpg</dateiname>
<blende>7.0</blende>
<belichtung>1/250</belichtung>
<iso>200</iso>
<datum>11.11.2011</datum>
</bild>
</bilder>
var bilder:Array = new Array(); var loader:URLLoader = new URLLoader(); loader.load(new URLRequest("bilder.xml")); loader.addEventListener(Event.COMPLETE, parseXML); function parseXML(evt:Event) { var xml_document:XML=new XML(evt.target.data); xml_document.ignoreWhitespace=true; for (var i:int=0; i < xml_document.bild.length(); i++) { var bild = new Object(); bild.dateiname=xml_document.bild[i].dateiname.text(); bild.blende=xml_document.bild[i].blende.text(); bild.belichtung=xml_document.bild[i].belichtung.text(); bild.iso=xml_document.bild[i].iso.text(); bild.datum=xml_document.bild[i].datum.text(); bilder[bilder.length]=bild; } }
var bilder:Array = new Array(); var loader:URLLoader = new URLLoader(); loader.load(new URLRequest("bilder.xml")); loader.addEventListener(Event.COMPLETE, parseXML); function parseXML(evt:Event) { var xml_document:XML=new XML(evt.target.data); xml_document.ignoreWhitespace=true; for each (var knoten:XML in xml_document.bild) { bilder.push(knoten); } }
Beide Aktionen packen die XML Daten in ein Array. In beiden Varianten kann man auf folgende Weise auf das vierte Element des Arrays "bilder" zugreifen:
trace(bilder[3].dateiname);
trace(bilder[3].blende);
trace(bilder[3].belichtung);
trace(bilder[3].iso);
trace(bilder[3].datum);
Es ist jedoch nicht gleiche. Hier lasse ich mir bei der for-each-in-Schleife das vierte Element komplett ausgeben:
trace(bilder[3]);
Es wird folgendes angezeigt:
<bild id="4">
<dateiname>img/img_04.jpg</dateiname>
<blende>7.0</blende>
<belichtung>1/250</belichtung>
<iso>200</iso>
<datum>11.11.2011</datum>
</bild>
Man sieht dass im zweiten Beispiel die XML Struktur im Array eingefügt wird, daher wäre die richtige Schreibeweise folgende:
bilder[3].dateiname.text();
Da alle Daten und die Struktur in XML schon vorhanden ist macht es nicht wirklich Sinn, alles nochmal in einem Objekt nachzubauen, wie im ersten Beispiel. Wichtig ist ja nur, wie man auf die Daten zugreifen kann, um sie zu benutzen.
Mit appendChild kann man sich die XML Daten zusammanbauen. Die Aktion fügt den kompletten Baum eines XML Objekts zwischen das Wurzelelement eines anderen XML Objekts, welches appendChild aufruft. Alle weiteren appendChild Aufrufe fügen die XML Daten unten an. Selbstverständlich kann man den appendChild-Aufruf auch innerhalb eines untergeordneten Elements aufrufen.
a.bilder.appendChild(b);
var a:XML =; var b:XML = ; var c:XML = 1.jpg 2.jpg Michael Albers ; a.appendChild(b); a.appendChild(c); trace(a);
Das sieht dann so aus.
<bildliste>
<bilder>
<bild id="1">1.jpg</bild>
<bild id="2">2.jpg</bild>
</bilder>
<autor>Michael Albers</autor>
</bildliste>
Mit delete kann man XML Elemente löschen. In den folgenden Beispielen ist die folgenden XML Struktur immer die Ausgangsitutation.
var a:XML=<bildliste>
<bilder>
<bild id="1">1.jpg</bild>
<bild id="2">2.jpg</bild>
</bilder>
<autor>Michael Albers</autor>
</bildliste>;
delete a.bilder.bild[0];
<bildliste>
<bilder>
<bild id="2">2.jpg</bild>
</bilder>
<autor>Michael Albers</autor>
</bildliste>
delete a.bilder.bild.@id;
<bildliste>
<bilder>
<bild>1.jpg</bild>
<bild>2.jpg</bild>
</bilder>
<autor>Michael Albers</autor>
</bildliste>
delete a.bilder.bild;
<bildliste>
<bilder/>
<autor>Michael Albers</autor>
</bildliste>
Im letzten Beispiel bleibt das Element <bilder /> als alleinstehendes Tag erhalten.
Hier erstellen wir ein XML Objekt, wobei einige Werte aus Variablen stammen. Man bedient sich dazu der geschweiften Klammern.
var imgUrl1:String="1.jpg";
var imgUrl2:String="2.jpg";
var a:XML=<bildliste>
<bilder>
<bild id="1">{imgUrl1}</bild>
<bild id="2">{imgUrl2}</bild>
</bilder>
</bildliste>
trace(a.toXMLString());
Die trace Ausgabe sieht so aus:
<bildliste>
<bilder>
<bild id="1">1.jpg</bild>
<bild id="2">2.jpg</bild>
</bilder>
</bildliste>
Hier werde ich jetzt anhand der nächsten Beispiele Schritt für Schritt erklären, wie man mehrere Bilder in einen MC lädt. Der MC könnte als Leiste mit Vorschaubildern dienen, daher die Namen der Klassendateien prevMovies.as Sämtliche Daten werden in einer externen XML-Datei gespeichert, z.B.: Die Titel der Bilder oder die URL der Bilder. In den ersten beiden Beispielen kommt die XML-Datei noch nicht zum Einsatz.
Die Klasse erbt vom Typ Movieclip. Es werden 2 Bilder in das Objekt geladen. Das zweite Bild wird um 200 Pixel nach rechts versetzt.
var gallery:PrevMovies1 = new PrevMovies1();
addChild(gallery);
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.net.URLRequest; public class PrevMovies1 extends MovieClip { public function PrevMovies1() { var request:URLRequest = new URLRequest("img/1.jpg"); var ldr:Loader = new Loader(); ldr.load(request); this.addChild(ldr); request = new URLRequest("img/2.jpg"); ldr = new Loader(); ldr.load(request); ldr.name="bild"+String(2); this.addChild(ldr); getChildByName("bild2").x=200; } } }
Hier werden mehrere Bilder mit einer For-Schleife geladen. In der Konstruktorfunktion ist ein Parameter hinzugekommen, der die Anzahl der zu ladenen Bilder festlegt.
var gallery:PrevMovies2 = new PrevMovies2(6);
addChild(gallery);
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.net.URLRequest; public class PrevMovies2 extends MovieClip { private var request:URLRequest; private var ldr:Loader; public function PrevMovies2(anzahl:uint) { for (var i:uint=1; i<=anzahl; i++) { request = new URLRequest("img/"+String(i)+".jpg"); ldr = new Loader(); ldr.load(request); this.addChild(ldr); this.getChildAt(i-1).x=i*200-200; } } } }
Hier kommt jetzt das Laden der XML-Datei hinzu. Nachdem die XML-Datei geladen ist, werden die Bilder geladen. Etwas kniffelig ist hier das richtige Referenzieren.
<?xml version="1.0" encoding="utf-8"?>
<Bilderliste>
<Bild titel="Finn auf dem Balkon">img/1.jpg</Bild>
<Bild titel="Finn sitzend">img/2.jpg</Bild>
<Bild titel="Finn im Wald">img/3.jpg</Bild>
<Bild titel="Finn auf der Strae">img/4.jpg</Bild>
<Bild titel="Finn auf d em Sofa">img/5.jpg</Bild>
<Bild titel="Beagle">img/6.jpg</Bild>
<Bild titel="Der kleine Finn">img/7.jpg</Bild>
<Bild titel="Finn im Feld">img/8.jpg</Bild>
</Bilderliste>
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.net.URLRequest; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; public class PrevMovies3 extends MovieClip { private var request:URLRequest; private var ldr:Loader; public function PrevMovies3() { var externalXML:XML; var loader:URLLoader = new URLLoader(); var request:URLRequest = new URLRequest("bilderliste.xml"); loader.load(request); loader.addEventListener(Event.COMPLETE, onComplete); function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); for (var i:uint=0; i<externalXML.children().length(); i++) { request = new URLRequest(externalXML.child(i)); this.ldr = new Loader(); this.ldr.load(request); this.ldr.name="bild"+String(i); addChild(this.ldr); getChildByName("bild"+i).x=i*200-200; } } else { trace("loader is not a URLLoader!"); } } } } }
Hier werden auch die Titel der Bilder hinzugefügt. Die Titel wurden als Attribute in der XML-Datei definiert.
<?xml version="1.0" encoding="utf-8"?>
<Bilderliste>
<Bild titel="Finn auf dem Balkon">img/1.jpg</Bild>
<Bild titel="Finn sitzend">img/2.jpg</Bild>
<Bild titel="Finn im Wald">img/3.jpg</Bild>
<Bild titel="Finn auf der Strae">img/4.jpg</Bild>
<Bild titel="Finn auf d em Sofa">img/5.jpg</Bild>
<Bild titel="Beagle">img/6.jpg</Bild>
<Bild titel="Der kleine Finn">img/7.jpg</Bild>
<Bild titel="Finn im Feld">img/8.jpg</Bild>
</Bilderliste>
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.net.URLRequest; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; import flash.text.*; public class PrevMovies4 extends MovieClip { private var request:URLRequest; private var ldr:Loader= new Loader(); private var myText:TextField; private var loader:URLLoader = new URLLoader(); public function PrevMovies4() { var externalXML:XML; XML.ignoreComments = true; XML.ignoreWhitespace = true; request = new URLRequest("bilderliste.xml"); this.loader.load(request); this.loader.addEventListener(Event.COMPLETE, onComplete); function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); for (var i:uint=0; i<externalXML.children().length(); i++) { request = new URLRequest(externalXML.Bild[i]); this.ldr = new Loader(); this.ldr.load(request); this.ldr.name="bild"+String(i); addChild(this.ldr); getChildByName("bild"+i).x=i*200; } for (i=0; i<externalXML.children().length(); i++) { myText = new TextField(); myText.text=externalXML.Bild[i].@titel; myText.name="t"+String(i); addChild(myText); myText.y=130; getChildByName("t"+i).x=i*200; } } else { trace("loader is not a URLLoader!"); } } } } }
Hier kommt eine etwas geänderte XML Datei zum Einsatz, neben Titel, Vorschaubild-url ist nun noch eine URL hinzugekommen, die beim Anklicken eines Vorschaubildes aufgerufen werden soll. Die einzelnen URLs werden in einem Array hinterlegt: filmURL Das Problem ist hier dem DisplayObjekt die richtige URL zuzuweisen. Da auch die DisplayObjekte in der Namensgebung durchnumeriert sind (bild1, bild2, bild3...etc.) Ziehe ich mir die Nummer aus dem Namen und nehmen diese als Index für das Array filmURL[index]. Siehe dazu meinen AS2 Tipp: Schreibmaschineneffekt, substring, etc.
Unten ist noch eine Bewegungsfunktion hinzugekommen, die man in ähnlicher Form in meinen AS2 und AS3 Tipps (programmierte Bewegung) findet.
<?xml version="1.0" encoding="utf-8"?>
<Bilderliste>
<Bild>
<titel>Finn auf dem Balkon</titel>
<bildurl> img/1.jpg</bildurl>
<filmurl>http://www.pastorpixel.de</filmurl>
</Bild>
<Bild>
<titel>Finn sitzend</titel>
<bildurl>img/2.jpg</bildurl>
<filmurl>http://www.on-design.de</filmurl>
</Bild>
<Bild>
<titel>Finn im Wald</titel>
<bildurl>img/3.jpg</bildurl>
<filmurl>http://www.malebengucken.de</filmurl>
</Bild>
<Bild>
<titel>Finn auf der Strae</titel>
<bildurl>img/4.jpg</bildurl>
<filmurl>http://www.checkdent.com</filmurl>
</Bild>
<Bild>
<titel>Finn auf d em Sofa</titel>
<bildurl>img/5.jpg</bildurl>
<filmurl>http://www.pastorpixel.de</filmurl>
</Bild>
<Bild>
<titel>Beagle</titel>
<bildurl>img/6.jpg</bildurl>
<filmurl>http://www.on-design.de</filmurl>
</Bild>
<Bild>
<titel>Der kleine Finn</titel>
<bildurl>img/7.jpg</bildurl>
<filmurl>http://www.malebengucken.de</filmurl>
</Bild>
<Bild>
<titel>Finn im Feld</titel>
<bildurl>img/8.jpg</bildurl>
<filmurl>http://www.pastorpixel.de</filmurl>
</Bild>
</Bilderliste>
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.net.*; import flash.events.Event; import flash.events.MouseEvent; import flash.net.URLLoader; import flash.net.URLRequest; import flash.text.*; public class PrevMovies5 extends MovieClip { private var request:URLRequest; private var ldr:Loader= new Loader(); private var myText:TextField; private var loader:URLLoader = new URLLoader(); private var filmURL:Array = new Array; private var xziel:Number; private var ab:uint=20; public function PrevMovies5() { var externalXML:XML; XML.ignoreComments = true; XML.ignoreWhitespace = true; request = new URLRequest("prevListe.xml"); this.loader.load(request); this.loader.addEventListener(Event.COMPLETE, onComplete); function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); for (var i:uint=0; i<externalXML.children().length(); i++) { request = new URLRequest(externalXML.Bild[i].bildurl[0]); filmURL[i] = externalXML.Bild[i].filmurl[0]; this.ldr = new Loader(); this.ldr.load(request); this.ldr.name="bild"+String(i); addChild(this.ldr); getChildByName("bild"+i).x=i*200; getChildByName("bild" + i).addEventListener(MouseEvent.CLICK, function (evt:MouseEvent):void{ var filmrequest:URLRequest; //die Nummer für: filmURL[1] wird aus displayObjektname generiert: bild1, siehe AS2 Tipp substring etc. filmrequest = new URLRequest(filmURL[evt.currentTarget.name.substring(Number(evt.currentTarget.name.lastIndexOf("d")+1))]); navigateToURL(filmrequest,"_blank"); } ); } for (i=0; i<externalXML.children().length(); i++) { myText = new TextField(); myText.text=externalXML.Bild[i].titel[0]; myText.name="t"+String(i); addChild(myText); myText.y=130; getChildByName("t"+i).x=i*200; } } else { trace("loader is not a URLLoader!"); } } this.addEventListener(MouseEvent.MOUSE_MOVE,mauspos); this.addEventListener(Event.ENTER_FRAME, bewegung); } public function mauspos(evt:MouseEvent):void { xziel = (((evt.currentTarget.width-550)/(550-ab*2))*(evt.stageX-ab))*-1; } public function bewegung(evt:Event):void { evt.currentTarget.x = evt.currentTarget.x+(xziel-evt.currentTarget.x)/6; } } }
Hier noch eine kleine Änderung und zwar werden hier die Links über Buttons aufgerufen. Vorraussetzung ist, dass sich in der Bibliothek ein Button befindet der den Klassennamen "butblue" hat. Beachte, wie ich hier die Links den einzelnen Buttons zuweise. Diese Methode ist mit Loader Objekt nicht möglich. Daher ist es im vorigen Beispiel anders gelöst. Siehe auch den AS3 Tipp Display Objekte.
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.net.*; import flash.events.Event; import flash.events.MouseEvent; import flash.net.URLLoader; import flash.net.URLRequest; import flash.text.*; public class PrevMovies6 extends MovieClip { private var request:URLRequest; private var ldr:Loader= new Loader(); private var myText:TextField; private var loader:URLLoader = new URLLoader(); private var xziel:Number; private var ab:uint=20; private var but:butblue; public function PrevMovies6() { var externalXML:XML; XML.ignoreComments = true; XML.ignoreWhitespace = true; request = new URLRequest("prevListe.xml"); this.loader.load(request); this.loader.addEventListener(Event.COMPLETE, onComplete); function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); for (var i:uint=0; i<externalXML.children().length(); i++) { request = new URLRequest(externalXML.Bild[i].bildurl[0]); this.ldr = new Loader(); this.ldr.load(request); this.ldr.name="bild"+String(i); addChild(this.ldr); getChildByName("bild"+i).x=i*201; but = new butblue(); but.name="but"+String(i); but.link= externalXML.Bild[i].filmurl[0]; addChild(but); getChildByName("but"+String(i)).x=i*201; getChildByName("but"+String(i)).addEventListener(MouseEvent.CLICK, function (evt:MouseEvent):void{ var filmrequest:URLRequest; filmrequest= new URLRequest(evt.currentTarget.link); navigateToURL(filmrequest,"_blank"); } ); myText = new TextField(); myText.text=externalXML.Bild[i].titel[0]; myText.name="t"+String(i); addChild(myText); myText.y=130; getChildByName("t"+i).x=i*201; } } else { trace("loader is not a URLLoader!"); } } this.addEventListener(MouseEvent.MOUSE_MOVE,mauspos); this.addEventListener(Event.ENTER_FRAME, bewegung); } public function mauspos(evt:MouseEvent):void { xziel = (((evt.currentTarget.width-550)/(550-ab*2))*(evt.stageX-ab))*-1; } public function bewegung(evt:Event):void { evt.currentTarget.x = evt.currentTarget.x+(xziel-evt.currentTarget.x)/6; } } }
if (meinContainer.numChildren != 0) {
while (meinContainer.numChildren) {
meinContainer.removeChildAt(0);
}
}