Aufgaben eines Codegenerators Modell einlesen Modell verifizieren Modell transformieren Quellcodegenerierung heute!! Andreas Schmidt XMI / Zugriff auf XML 1/17
XML Input Aktueller Input unseres Generators basiert auf einer Reihe von APIcalls (Metamodel API) Nächster Schritt: Input, basierend auf XML: To Do: Erstellung einer XML-Sprache für unser Modell Erstellung eines Metamodells für diese XML-Sprache (DTD, XMLscheme or relax NG schema) Erstellung eines Input-Prozessors Andreas Schmidt XMI / Zugriff auf XML 2/17
Vorschlag für ein XML-basiertes Modell <!DOCTYPE my-model SYSTEM "my-meta.dtd"> <my-model name="demo"> <class name="film"> <attribute name="title" type="string"/> <attribute name="year" type="integer"/> <relation role="director" type="person" min="1" max="1" relation_name="film_director"/> <relation role="characters" type="role" min="0" max="-1" relation_name="film_role"/> </class> <class name="person"> <attribute name="surname" type="string"/> <attribute name="date_of_birth" type="date"/> <relation role="film" type="film" min="0" max="-1" relation_name="film_director"/> <relation role="played_roles" type="role" min="0" max="-1" relation_name="person_role"/> </class> <class name="role"> <attribute name="salary" type="integer"/> <attribute name="name_of_role" type="string"/> <relation role="film" type="film" min="1" max="1" relation_name="film_role"/> <relation role="actor" type="person" min="1" max="1" relation_name="person_role"/> </class> </my-model> Andreas Schmidt XMI / Zugriff auf XML 3/17
Metamodel für dieses Modell (DTD) <!ELEMENT my-model (class+)> <!ATTLIST my-model name CDATA #REQUIRED > <!ELEMENT class (attribute+, relation*)> <!ATTLIST class name ID #REQUIRED > <!ELEMENT attribute EMPTY> <!ATTLIST attribute name NMTOKEN #REQUIRED primary-key (true false) #IMPLIED type (String date Integer) #REQUIRED length CDATA #IMPLIED > <!ELEMENT relation EMPTY> <!ATTLIST relation role CDATA #REQUIRED type IDREF #REQUIRED min CDATA "0" max CDATA "-1" relation_name CDATA #IMPLIED> Andreas Schmidt XMI / Zugriff auf XML 4/17
Einlesen von XML-Datei in Programm Zweck: Transformation der XMI/XML Daten in generatorspezifisches Metamodell Werkzeuge: DOM SAX XPath PHP & XML sehr gute Unterstützung seit Version 5.x XPath mit Namespace Support Vorgehensweise: Einlesen der XMI-Informationen Generierung des Metamodells aus diesen Informationen Alternative: Direkte Transformation in Quellcode mittels XSLT (Vor-/Nachteile) Andreas Schmidt XMI / Zugriff auf XML 5/17
Zugriff auf XML mittels PHP Erstellen eines DOM-Baums $dom = new DomDocument(); $dom->load($file); Validierung eines XML Dokuments (einschließlich Setzen von Default-Werten) $dom->validate(); Erstellung eines DOM-Baums für XPATH-Anfragen $dom_xpath = new domxpath($dom); XPATH-Anfrage stellen $element_list = $dom_xpath->query($xpath) Andreas Schmidt XMI / Zugriff auf XML 6/17
Extraktion von Kind-Elementen mit vorgegebenem Namen $element_list = $element->getelementsbytagname($name); Gib das n-te Element einer Elementliste zurück (start with 0) $element = $element_list->item($idx); Lese den Wert des Attributs mit dem gegebenen Namen aus $value = $element->getattribute($name); Andreas Schmidt XMI / Zugriff auf XML 7/17
Beispiel: Einlesen der Modelldatei aus Folie 12 <?php if (count($argv) < 2) die("usage:./$argv[0] <xml-file>\n"); $file = $argv[1]; if (! file_exists($file)) die("konnte Datei '$file' nicht laden."); $dom = new DomDocument(); $dom->load($file); if (! $dom->validate()) // setzt Defaultwerte bei XML-Attributen, die("'$file' ungültig"); // sofern nicht spezifiziert (siehe min, max) $xp = new domxpath($dom); Andreas Schmidt XMI / Zugriff auf XML 8/17
... foreach ($xp->query('//class') as $c) { $class_name = $c->getattribute('name'); print "-$class_name\n"; print " Attribute:\n"; foreach ($xp->query("//class[@name='$class_name']/attribute") as $att) { $name = $att->getattribute('name'); $type = $att->getattribute('type'); print " $name $type\n"; } print " Beziehungen:\n"; foreach ($xp->query("//class[@name='$class_name']/relation") as $association_end) { $association_name = $association_end->getattribute('relation_name'); $role_name = $association_end->getattribute('role'); $target_class = $association_end->getattribute('type'); $min = $association_end->getattribute('min'); $max = $association_end->getattribute('max'); $max = $max==-1? "*":$max; print " [$role_name] --($min/$max)--> $target_class ($association_name)\n"; } } Andreas Schmidt XMI / Zugriff auf XML 9/17
Ausgabe $ php read-model.php model.xml -Film Attribute: title String year Integer Beziehungen: [director] --(1/1)--> Person (film_director) [characters] --(0/*)--> Role (film_role) -Person Attribute: surname String date_of_birth date Beziehungen: [film] --(0/*)--> Film (film_director) [played_roles] --(0/*)--> Role (person_role) -Role Attribute: salary Integer name_of_role String Beziehungen: [film] --(1/1)--> Film (film_role) [actor] --(1/1)--> Person (person_role) Andreas Schmidt XMI / Zugriff auf XML 10/17
Aufbau eines einfachen PHP-Generators Templates XML Transformation Metamodell Generator generierter Quellcode Aufgaben: Parsen XML-Datei (DOM, XPath,...) Transformation in internes Modell (meta-model.php) Einlesen und Füllen der Templates Andreas Schmidt XMI / Zugriff auf XML 11/17
Aufbau PHP-Generator <? include 'meta-model.php'; if (count($argv) < 3) die ("usage: $argv[0] <xml-file> <template-file>"); $file = $argv[1]; $template = $argv[2]; if (file_exists($file)) { $dom = new DomDocument(); $dom->load($file); $dom->validate(); // setzt Defaultwerte bei attributen, // sofern nicht spezifiziert (siehe min, max) // hier erfolgt die Transformation ins interne Metamodell (siehe meta-model.php) // z.b. $c = new MetaClass(...);... $c->addattribute(...); $c->addrelation(...); include "$template"; } else { exit('konnte Datei nicht laden.'); } siehe nächste Folie Andreas Schmidt XMI / Zugriff auf XML 12/17
Aufbau Template ddl.tpl <?php foreach ($classes as $class) {?> create table <?php $class->name?> ( <? foreach ($class->attributes as $att) {?> <?php $att->name?> <?= $att->type?><?php $att->length>0?"($att->length)":""?>, <? }?> primary key(<?php $class->primary_key->name?>) ) Type=InnoDB; <? }?> -- Jetzt kommen die Beziehungen... Andreas Schmidt XMI / Zugriff auf XML 13/17
Ergebnis: XML -> DDL <?xml version="1.0"?> <!DOCTYPE my-model SYSTEM "my-meta.dtd"> <my-model> <class name="person"> <attribute name="p_id" primary-key="true" type="integer" length="10"/> <attribute name="name" type="varchar" length="30"/> <attribute name="vorname" type="varchar" length="30"/> </class> <class name="film"> <attribute name="f_id" primary-key="true" type="integer"/> <attribute name="titel" type="varchar" length="120"/> <attribute name="jahr" type="date"/> </class> <association name="regisseur"> <association-end class="person" role="regisseur" min="0"/> <association-end class="film" role="directed_film" min="1" max="1"/> </association> <association name="spielt_mit"> <association-end class="person" role="schauspieler" min="0"/> <association-end class="film" role="film" min="0"/> </association> </my-model> create table Person ( p_id int(10), name varchar(50), vorname varchar(50), primary key(p_id) ) Type=InnoDB; create table Film ( f_id int(10), titel varchar(80), primary key(f_id) ) Type=InnoDB; alter table Film add column regisseur_fk int references Person(p_id) create table spielt_mit ( schauspieler_fk int references Person(p_id), film_fk int references Film(f_id), primary key(film_fk, schauspieler_fk) ) Type=InnoDB; Andreas Schmidt XMI / Zugriff auf XML 14/17
Aufbau Template php-code.tpl <?php echo "<? "?> include 'DB_Util.php'; <?php foreach ($classes as $class) {?> class <?php echo $class->name?> { <?php foreach ($class->attributes as $att) {?> private $<?php echo $att->name?>; <?php }?> function construct($dic) { <?php foreach ($class->attributes as $att) {?>... Andreas Schmidt XMI / Zugriff auf XML 15/17
Ergebnis: XML -> DDL <?xml version="1.0"?> <!DOCTYPE my-model SYSTEM <my-model> <class <attribute name="p_i <attribute name="nam <attribute name="vor </class> <class name="film"> <attribute name=" <attribute name=" <attribute name=" </class> <association name=" <association-end <association-end </association> <association name=" <association-end <association-end </association> </my-model> <? include 'DB_Util.php'; class Person { private $p_id; private $name; private $vorname; function construct($dic) { $this->p_id = array_key_exists('p_id', $dic)?$dic['p_id']:null; $this->name = array_key_exists('name', $dic)?$dic['name']:null; $this->vorname = array_key_exists('vorname', $dic)?$dic['vorname']:null; } function get_p_id() { return $this->p_id; } // und so weiter und so fort... Andreas Schmidt XMI / Zugriff auf XML 16/17
Ressourcen Zugriff von PHP (Version 5) auf XML http://trash.chregu.tv/phpconf2003/examples XML in PHP 5 - What's New? http://devzone.zend.com/article/2387-xml-and-php-5 Manual Page: DomElement: http://www.dynamicwebpages.de/php/ref.dom.php Manual page: DomXPath http://www.dynamicwebpages.de/php/function.dom-domxpath-construct.php Andreas Schmidt XMI / Zugriff auf XML 17/17