Zurück   Flashforum > Flash > Stuff

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 08-11-2007, 22:42   #1 (permalink)
relayit.de
 
Registriert seit: Sep 2001
Beiträge: 427
AS2 XML_Serializer - Flash/XML/PHP Datenmigration

Hallo Forum!

War schon länger nicht mehr hier, aber gerade hab ich ein wenig Zeit, euch ein kleines, sehr vielseitiges Tool vorzustellen. Wollte es eigetnlich auf meine neue Seite pakkn, mit kleiner Doku, etc. Aber ich glaube, das passiert nicht in absehbarer Zeit, da ich einfach zuviel externe Arbeit habe. Ausserdem vergesse ich langsam, was ich damals genau gecodet habe. Deswegen mach ich hier einfach n Thread und hoffe, dass ich es nicht vergesse und sich ein paar von euch daran erfreuen koennen

Also worum geht es? Einfach gesagt: Serialisieren von Daten zwischen PHP und Flash (oder auch Flash zu Flash) mit Hilfe von XML. Dabei soll sich der Entwickler im besten Fall nicht mit dem Generieren und Parsen der Daten auseinandersetzen müssen, sondern einfach sein zu übertragendes Objekt angeben und zurücklehnen.
Die Idee dafür stammt aus der PHP PEAR Library, wo es eine Klasse namens XML_Serializer gibt. Diese hübsche kleine Klasse konvertiert PHP-Datenstrukturen (Skalare sowie auch Komplexe) typsicher nach XML. Das zugehörige Pendant XML_Unserializer kann dann diese Struktur mittels des von XML_Serializer generierten XML's wiederherstellen. Hierzu zählen auch Objekte, die eine Klassendefinition besitzen. Nach dem Deserialisieren ergibt sich somit die gleiche Struktur mit den gleichen Klasseneigenschaften und Funktionen, wie beim Ausgangsobjekt, ohne dass der Entwickler sich mit dem XML auseinandersetzen muss.
Wenn das mal nicht cool ist ...

Also habe ich mir auch eine XML_Serializer Klasse in ActionScript2 geschrieben, die sich im Wesentlichen genauso benutzen lässt, wie die PHP Klasse. Das trifft sowohl auf die Optionen als auch die Schreibweise zu (naja, jedenfalls fast). Nicht nur, dass ich meine Flash-Laufzeit-Objekte für spätere Arbeiten speichern kann, sondern ich kann jetzt auch ohne Probleme Datensätze von Flash nach Flash, Flash nach PHP, PHP nach PHP und PHP nach Flash transferieren, ohne Struktur- oder Funktionsverlust.

Nehmen wir mal an, ich habe im ActionScript eine Klasse namens "Image" angelegt, die neben dem Pfad und Metadaten auch Funktionen zum Erstellen der Movieclips, Eventhandling, usw. hat. Nun möchte ich dynamisch mehrere "Images" von einer Datenbank oder aus einem File laden. Natürlich könnte ich eine genau auf das Zielobjekt abgestimmte Parsingfunktion schreiben. Oder aber ich erstelle direkt aus der XML Repräsentation mein internes Objek mit all den Funktionen, die ich in Flash dann brauche. Wenn ich dann noch in PHP die gleiche Klasse "Image" erstelle, diesmal mit Funktionen zur Speicherung/Änderung, lesen aus einer Datenbank, spare ich mir eine Menge Zeit und Code, weil ich keine Transportfunktionen oder Konvertierer mehr brauche. Ich drück auf "Laden" und mein Objekt kommt so, wie ich es haben möchte.

Natürlich ist das nur die halbe Wahrheit, schliesslich verhalten sich manche Datentypen in beiden Sprachen unterschiedlich und sowas kann man schwer mappen. So z.B. ein Array. In Flash gibt es für Arrays zwei Datentypen. Object fuer assoziative Arrays, Array für numerische. PHP macht da aber keinen Unterschied. Wie also will man eine Klasse schreiben, die nicht weiss, ob das XML aus Flash kommt oder PHP, und dann dennoch die richtigen Typen findet? Mehr dazu später!

Alles was in Flash dafür gebraucht wird, ist die as2lib und meine Klassen (Link unten). Für PHP benötigt man das genannte PEAR:XML_Serializer Paket.

Fangen wir mit einem kleinen Beispiel an (AS2 code)
ActionScript:
  1. import de.bilsingbilsing.util.xml.*;
  2. import de.bilsingbilsing.util.*;
  3.  
  4. // der serializer, zur Konstruktion später mehr
  5. var serializer = new Serializer( new KeyMap().push(Serializer.OPTION_TYPEHINTS, false) );
  6.  
  7. //Unser Testobjekt
  8. var test = new Object();
  9. test.zahl = 10;
  10. test.string = "Teststring";
  11. test.subobjekt = new Object();
  12. test.subobjekt.array = [1,2,3,4];
  13.  
  14. // ran an den speck
  15. var xml = serializer.serialize(test);
  16. trace(xml.childNodes[0].toString());
Als Output bekomme ich folgendes:
Code:
<XML_Serializer>
	<subobjekt>
		<array>
			<XML_Serializer_Tag>1</XML_Serializer_Tag>
			<XML_Serializer_Tag>2</XML_Serializer_Tag>
			<XML_Serializer_Tag>3</XML_Serializer_Tag>
			<XML_Serializer_Tag>4</XML_Serializer_Tag>
		</array>
	</subobjekt>
	<string>Teststring</string>
	<zahl>10</zahl>
</XML_Serializer>
Das schaut doch schonmal gut aus. Bei der XML-Repräsentation des Objekts, werden die Eigenschaften des Objekts als XML-Tags dargestellt. Die Struktur bleibt erhalten und ich kann nun mit folgendem Code, das gleiche Objekt wieder herstellen:
ActionScript:
  1. var unserializer = new Unserializer(new KeyMap().push(Unserializer.OPTION_COMPLEXTYPE, "object"));
  2.  
  3. var backup = unserializer.unserialize(xml).value;
  4. trace(backup.subobjekt.array[1]);
Output ist wie erwartet "2". Gehen wir jetztmal davon aus, ich habe das XML an PHP per Post übergeben in der Variable "test":
PHP-Code:
require_once 'XML/Unserializer.php';
    
    
$sopt = array( 
        
'encoding' => 'UTF-8',
    );
    
    
    
$unserializer =& new XML_Unserializer($sopt);
    
$status $unserializer->unserialize($_POST["test"]);
    
    if(
PEAR::isError($status)){ 
        
$this->last_err $status;
        die(
"error during parse");
    }
    
    
$backup $unserializer->getUnserializedData();
    
    echo 
$backup->subobjekt->array[1]; 
Und welch Überraschung, Output ist 2! "test" ist nun ein PHP Objekt ($backup), und kann dort wie jedes andere Objekt bearbeitet werden.

Jetzt werden sich einige Fragen, wo die Typsicherheit beim XML bleibt und wie der Serializer aufgrund der wenigen Informationen das richtige Objekt zusammenstellen kann. Gehen wir nochmal zurück zum AS2 Code, zur Initialisierung des Serializers:
ActionScript:
  1. var serializer = new Serializer( new KeyMap().push(Serializer.OPTION_TYPEHINTS, false) );
KeyMap ist eine Ableitung der as2lib-Klasse "org.as2lib.data.holder.map.HashMap" und wird hier dafür gebraucht, den Serializer zu konfigurieren und die Default Optionen zu überschreiben (auch eine KeyMap logischerweise). Funktioniert wie beim PHP XML_Serializer. Die KeyMap Klasse gibt in der Funktion "push" immer sich selbst zurueck, sodass ich endlos Optionen anhängen kann und als Ergebnis immer die Map bekomme (bsp: KeyMap().push(...).push(...).push(...) instanceof KeyMap = true) In diesem Fall überschreibe ich TYPEHINTS, was per default nämlich true ist. Ich habs im oberen Beispiel rausgenommen, um euch nicht gleich zu zubomben. Das hol ich jetzt nach
Code:
<XML_Serializer _class="Object" _type="object">
	<subobjekt _class="Object" _type="object">
		<array _type="array">
			<XML_Serializer_Tag _type="integer" _originalKey="0">1</XML_Serializer_Tag>
			<XML_Serializer_Tag _type="integer" _originalKey="1">2</XML_Serializer_Tag>
			<XML_Serializer_Tag _type="integer" _originalKey="2">3</XML_Serializer_Tag>
			<XML_Serializer_Tag _type="integer" _originalKey="3">4</XML_Serializer_Tag>
		</array>´
	</subobjekt>
	<string _type="string">Teststring</string>
	<zahl _type="integer">10</zahl>
</XML_Serializer>
Schaut das nicht toll aus? So werden zugehörige Typen und Klassen gleich mitgespeichert, damit beim Deserialisieren keine Fehler auftreten. Basistypen ermittelt der Serializer quick&dirty selbst, wobei Klassen mittels der as2lib Tools in org.as2lib.env.reflect.* ermittelt werden.

Der Serializer (sowie auch der Unserializer) besitzt noch viele Optionen aus der PEAR-Vorlage, beispielsweise Typ-, Class- oder Tag-Remapping. XML-Nodenamen gleich als Klassennamen benutzen, Skalare als XML-Attribute schreiben anstatt als Textnodes. Und so weiter, und so weiter.

So. das war erstmal Part I, im nächsten Part geht es dann um Klassenkonvertierungen, tiefere Einsichten in Typunteschiede und ein paar Beispiele.

Soweit erstmal alles Gute und viel Spass mit den Klassen!

PHP PEAR::XML_Serializer: http://pear.php.net/package/XML_Serializer
AS2 as2lib: http://www.as2lib.org/
AS2 XML_Serializer: http://bilsingbilsing.de/dev/XML_Serializer.zip
__________________
hmmm.....
japanitrat ist offline   Mit Zitat antworten
Alt 08-11-2007, 23:31   #2 (permalink)
mod_rewrite
 
Benutzerbild von sonar
 
Registriert seit: Feb 2003
Ort: München
Beiträge: 15.621
Hat das jetzt einen Sinn, dass du das in mehreren Bereichen gepostet hast oder..?
__________________
RTFM
Wie man Fragen richtig stellt.

Achim Bindannmalweg

Money makes the world go round, fear makes it turn much faster.
(New Model Army)
sonar ist offline   Mit Zitat antworten
Alt 09-11-2007, 01:58   #3 (permalink)
relayit.de
 
Registriert seit: Sep 2001
Beiträge: 427
mhm jep, steht in dem anderen post eigentlich auch drin...
__________________
hmmm.....
japanitrat ist offline   Mit Zitat antworten
Alt 09-11-2007, 08:18   #4 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.147
Wieso so viele Redundanzen? Die Hälfte der Infos kann weggelassen werden.
Omega Psi ist offline   Mit Zitat antworten
Alt 09-11-2007, 08:50   #5 (permalink)
mod_rewrite
 
Benutzerbild von sonar
 
Registriert seit: Feb 2003
Ort: München
Beiträge: 15.621
Also: ich hab den hier jetzt nach 'Stuff' verschoben und deinen Verweis darauf im 'Stuff'-Bereich gelöscht. Das Duplikat hast ja selber schon gelöscht...
__________________
RTFM
Wie man Fragen richtig stellt.

Achim Bindannmalweg

Money makes the world go round, fear makes it turn much faster.
(New Model Army)
sonar ist offline   Mit Zitat antworten
Alt 09-11-2007, 11:08   #6 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.147
Hier mal ein paar Anmerkungen:
  1. class und type sind nach meinem Verständnis deiner Struktur das gleiche
  2. Das Mapping des Typs Array ist inkonsistent.
  3. Die Reihenfolge in einem indizierten Array anzugeben ist auch überfüssig.
Ich würde das ganze etwas konsistenter und unkomplizierter aufziehen: einen Wurzelknoten <instances>, für jedes Instanz einer Klasse einer Klasse einen Knoten <instance> und jedes Datenfeld der Klasse einen Knoten <field>. Die Knoten <instance> und <field> bekommen ids und wenn sie auf einen anderen komplexen Datentyp verweisen eine Attribut ref. id die ist die id im Baum, ref zeigt auf die id eines anderen Knoten.Für folgende Klasse
ActionScript:
  1. /**
  2. * @author
  3. * @version
  4. *
  5. * Created with BeanButler (c) 2007, Florian Salihovic,
  6. * <a href='mailto:florian.salihovic@gmail.com'>florian.salihovic</a>
  7. */
  8. package {
  9.     public class Person {
  10.         private var age:Number;
  11.         private var name:String;
  12.         private var friends:Array;
  13.         public function Person() {
  14.             this.friends = new Array();
  15.         }
  16.         public function addFriend(friend:Person):void {
  17.             this.friends.push(friend);
  18.         }
  19.         public function getAge():Number {
  20.             return this.age;
  21.         }
  22.         public function getName():String {
  23.             return this.name;
  24.         }
  25.         public function getFriendAt(index:uint):Person {
  26.             return this.friends[index];
  27.         }
  28.         public function getFriends():Array {
  29.             return this.friends;
  30.         }
  31.         public function getFriendsCount():uint {
  32.             return this.friends.length;
  33.         }
  34.         public function removeFriendAt(index:uint):void {
  35.             this.friends.splice(index, 1);
  36.         }
  37.         public function setAge(age:Number):void {
  38.             this.age = age;
  39.         }
  40.         public function setName(name:String):void {
  41.             this.name = name;
  42.         }
  43.         public function setFriends(friends:Array):void {
  44.             this.friends = friends;
  45.         }
  46.         public function toString():String {
  47.             var asString:String = 'Person';
  48.             asString += ' - age: '+this.age;
  49.             asString += ' - name: '+this.name;
  50.             asString += ' - friends: '+this.friends;
  51.             return asString;
  52.         }
  53.     }
  54. }
sehe das Mapping so aus:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<instances>
	<instance id="p0" type="Person">
		<field id="f0" name="name" type="String">
			<value>Peter</value>
		</field>
		<field id="f1" name="age" type="Number">
			<value>23</value>
		</field>
		<field id="f2" name="friends" type="Array" />
	</instance>
</instances>
Das Problem an der Geschichte sind aber Objekte die Referenzen auf andere Objekte speichern. Hier kommt das Attribut ref in Spiel. In dem obigen Beispiel kann eine Person anderen Personen als Freunde speichern. Das heisst im Klartext: Instanzen dürfen auch nur einmal gespeichert werden. Foldende Instanzen
ActionScript:
  1. var person1:Person = new Person();
  2. person1.setAge(23);
  3. person1.setName("Peter");
  4. person2:Person = new Person();
  5. person2.setAge(45);
  6. person2.setName("Josef");
  7. person1.addFriend(person2);
müssen dann entsprechend serialisiert werden:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<instances>
	<instance id="p0" type="Person">
		<field id="f0" name="name" type="String">
			<value id="v0">Peter</value>
		</field>
		<field id="f1" name="age" type="Number">
			<value id="v1">23</value>
		</field>
		<field id="f2" name="friends" type="Array">
			<value id="v2" ref="p1" />
		</field>
	</instance>
	<instance id="p1" type="Person">
		<field id="f3" name="name" type="String">
			<value id="v3">Josef</value>
		</field>
		<field id="f4" name="age" type="Number">
			<value id="v4">45</value>
		</field>
		<field id="f5" name="friends" type="Array" />
	</instance>
</instances>
Bei assoziativen Arrays würde man dem Knoten <value> noch das Attribut name mitgeben.

Das sind halt so gutgemeinte Ratschäge.

Geändert von Omega Psi (09-11-2007 um 11:10 Uhr)
Omega Psi ist offline   Mit Zitat antworten
Alt 09-11-2007, 12:28   #7 (permalink)
relayit.de
 
Registriert seit: Sep 2001
Beiträge: 427
Hi Omega, danke für dein Feedback!


zu deinen Anmerkungen:

1. class und type sind eigentlich schon das gleiche. Aber in dem Tool geht es groesstenteils auch um die Kompatibilität zu PHP und in PHP sind Klassen "Extratypen". Wie ich schon sagte, ist der AS2 XML_Serializer eine Portierung des PEAR XML_Serializers. Das hat seinen Grund eben in der Portierbarkeit.

2. Hab ich angeschnitten, liegt eben auch an der Portierbarkeit zu PHP. Wenn du was anderes meinst, klär mich auf!

3. Das ist nun wirklich Unsinn. die Reihenfolge in einem indizierten Array IST wichtig. XML ist das egal, aber deiner Applikation vielleicht nicht.


Verstehe nicht ganz, wozu in deinem Beispiel "Fields" etwas anderes sind als "Instanzen". Alles in dem XML sind Instanzen, vom Boolean bis zur Klasseninstanz. Die wahre Macht des Tools ergibt sich ja aus der Umwandlung "lesbarer" XML's zu funktionierenden Objekten.
Warum der PEAR XML_Serializer die Daten so ausgibt, wie er sie nun ausgibt, sollteste dort vielleicht mal nachschauen. Ein paar Links hab ich schon gegeben, aber hier noch ein paar mehr:

http://www.sitepoint.com/article/xml...xml_serializer
http://www.melonfire.com/community/c...cle.php?id=244
http://www.devshed.com/index2.php?op...ge=0&hide_js=1



PS: über die Redundanz der Informationen kann man innem Forum nun garnich mekkern. Schau dir mal ein paar threads in den Anfängerforen an, dann weisste, wozu die Redundanz da ist
__________________
hmmm.....

Geändert von japanitrat (09-11-2007 um 12:39 Uhr)
japanitrat ist offline   Mit Zitat antworten
Alt 09-11-2007, 12:39   #8 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.147
  1. Ich kann kein PHP, deswegen ist mir die Differenzierung nicht klar.
  2. Siehe 1.
  3. Also wenn sich extra die Mühe macht Array-Element nicht der Reihe nach auszulesen, dann mag das einen Sinn haben... aber wer macht das?
  4. <field> ist ein Datenfeld einer Klasse - es bestht eine semantische und funktionale Abhängigkeit der Klasse zum Datenfeld.

Edit#1: Die Redudanzen in einem Forum und einem Datenmodell sind 2 paar Schuhe. Hast du in deinem Modell redundante Objektdaten werden diese womöglich 2x erzeugt und schon kannst du die Applikation... vergessen. Bzw. den Systemzustand.

Geändert von Omega Psi (09-11-2007 um 12:44 Uhr)
Omega Psi ist offline   Mit Zitat antworten
Alt 09-11-2007, 12:58   #9 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.147
Hab mich eben schlau gemacht und mal eben gestöbert. Hab bis jetzt noch kein komplexes OOP beispiel gefunden, in der eine komplexe Objekthierachie serialisiert wird.

type und class macht Sinn. Hab nicht daran gedacht, das es auch ncoh primitive Datentypen gibt...
Omega Psi ist offline   Mit Zitat antworten
Alt 09-11-2007, 13:00   #10 (permalink)
relayit.de
 
Registriert seit: Sep 2001
Beiträge: 427
aaaaahh _diese_ Redundanz meisnt du :> Wie ich schon sagte, es ist ein Port der PHP Version.
Natürlich wuerde ich auch gerne Referenzen mitimplementieren, aber die wuerde der PEAR Serializer nicht verstehen.

Ich mein, so kann man den Serializer natuerlich schoen gegen die Wand fahren. Stell dir vor ich hab zwei Objekte, die auf sich gegenseitig zeigen ... das geht ohne referenz-konvertierung/markierung/was-auch-immer natuerlich nicht. das endet einfach nur in einer endlos-rekursion.

nochmal zu deinen punkten

1. danke. Einfach mal reinschauen.
2. danke, s. 1
3. der satz ist mir ein rätsel.
4. aber wozu "field"? die semantische und funktionale Abhängigkeit besteht doch auch, wenn ich einen weiteren Subknoten einfüge, dessen name der "field"name ist. Ich zitiere mal deine Signatur "Complexity through simplicity"

Anyway. Häufig geht es ja auch darum, NICHT-Flash-Daten in Flash zu konvertieren. Beispielsweise Amazon-REST Outputs. Ich bin ehrlich gesagt auch völlig verblüfft, woran du dich so stößt. Im jetzigen Zustand gibt es natürlich Inkonsistenzen, die aber (wie auch schon im Thread öfter angemekrt" auf die Kompatibilität zur PEAR Library zurueckzuführen sind.
Die Vorteile und Zeitersparnisse, die ich dafür im Gegenzug bekomme, sind aber weitaus schwerwiegender.
Ich bin auch immer wieder am überlegen, wie ich das mit den Referenzen in Einklang mit der PEAR LIbrary bringe, aber dafür muesst ich die wohl auch "erweitern". Aber wie ich oben auch schon bemerkte, ikk hab einfach sooo wenig Zeit


Edit: Beispiele sind selten komplex
__________________
hmmm.....

Geändert von japanitrat (09-11-2007 um 13:15 Uhr)
japanitrat ist offline   Mit Zitat antworten
Alt 09-11-2007, 13:22   #11 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.147
Ich stosse mich da eigentlich nicht so sehr dran, ist ja nicht meine App. Meine Anregungen beruhen auf meinem Verständnis von Datenmodellierung - und da geht es um gerade darum Redundanzen zu vermeiden.

zu 3: Wenn man ein Array von Index 0 bis Index n ausliest und so in die XML schreibt, kann man sich die zusätzlichen Indizes in den Knoten sparen.
zu 4: <field> ist allgemeiner Platzhalter der aufgrund der Bezeichnung von Variablen einer Klasse, denn die heissen Datenfelder. Und das einheitliche Bezeichner machen das parsen auch etwas angenehmer, wenn ich das richtig in Erinnerung habe.

Als Beispiel musst du dir nur mal eine XML Schema Definition anschauen, die werden genauso erstellt.

PS: Ich mag da vielleicht etwas old school sein und diskutieren kann man darüber allemal. Aber wenn man
Omega Psi ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 19:10 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele