Portal > Foren > PHP > PHP-Programmierung > Template Engine mit XML
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 06.09.2008, 20:30 Nach oben    #1
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard Template Engine mit XML

Hi

hab mir ne Template Engine mit XML geschrieben. Per DOM erstelle ich mir dynamisch meine XML fils und transformier sie mit XSLT zu einer XHTML seite.
Soweit so gut, mein problem liegt nur darin, wenn ich zB. irgendwo ein skript habe, was kategorien hat, das er jedes mal für die gleiche kategorie den namen anzeigt. Was er aber nicht soll. Der grund dafür ist eigentlich auch klar, ich weiss nur nicht wie ich das lösen kann.

Hier der quelle code

Template.php
PHP-Code:
<?php
class XmlTemplate {

    private 
$templateDir;

    private 
$oDom;

    private 
$oXSLT;

    private 
$saveXML;

    private 
$template "";

    public function 
__construct(){
        
$this->templateDir site_path "public/template";
        
$this->oDom = new DOMDocument('1.0''UTF-8');
        
$this->oXSLT = new XsltProcessor;
    }

    public function 
load($filename){
        
$xsl = new DOMDocument;

        if(!
is_file($this->templateDirDIRSEP.$filename.'.xsl')){
            die(
"Not Found");
        }
        
$xsl->load($this->templateDirDIRSEP.$filename.'.xsl');

        
$this->oXSLT->importStylesheet($xsl);
    }

    private function 
generateXMLNode($data$root$document,$nodeName) {
        if(
is_array($data)) {
            foreach(
$data as $key => $value) {

                if(
is_int($key)){
                    
$node $document->createElement($nodeName);
                } else {
                    
$node $document->createElement($key);

                }
                
$node $root->appendChild($node);
                
$this->generateXMLNode($value$node$document,$nodeName);


            }
        }
        else {
            
$node $document->createTextNode($data);
            
$node $root->appendChild($node);
        }
    }

    public function 
assign($replace$replacement$nodeName=""){
        
$root $this->oDom->createElement($replace);
        
$root $this->oDom->appendChild($root);


        
$this->generateXMLNode($replacement$root$this->oDom$nodeName);

        
$this->saveXML $this->oDom->saveXML();

    }

    public function 
out(){
        echo 
$this->fetch();
    }

    public function 
fetch(){
        
$xml = new DOMDocument;
        
$xml->loadXML($this->saveXML);
        
$template $this->oXSLT->transformToXML($xml)
        or die(
'Transformation error!');
        return 
$template;
    }
}
der dazu gehörige Code mit der Abfrage
PHP-Code:
        $this->registry['tpl']->load('templatename/test');

        
$db = new MySQL();
        
$db->query("SELECT * FROM kat ");
        
        while (
$data $db->fetchRow()) {
             
$kat[]= $data;

             
$db1 = new MySQL();
            
$db1->query("SELECT * FROM test where kate = '".$data['kat']."'");

            while(
$dat $db1->fetchRow()){
               
$zeilen[] = $dat;
            }
        

        }

        
$db->disconnect();

        
$this->registry['tpl']->assign('test',$zeilen,'news');  
        
$this->registry['tpl']->out(); 
die xsl
PHP-Code:
<?xml version="1.0" encoding="utf-8"?> 
 
<xsl:stylesheet version="1.0" 
xmlns="http://www.w3.org/1999/xhtml" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:php="http://php.net/xsl" 
exclude-result-prefixes="php">
 
 
<xsl:output method="xml" encoding="UTF-8" indent="yes" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" omit-xml-declaration="yes" /> 
 
<xsl:include href="root.xsl" /> 
 
<xsl:template match="/test"> 
 
    <xsl:apply-templates select="news"/>
    <p><a href="index">index</a></p> 
 
</xsl:template>

<xsl:template match="news">

    <p><xsl:value-of select="name"/></p> 
</xsl:template>
 

 
</xsl:stylesheet>
Die Ausgabe sieht momentan so aus.

Kategorie 1
-bla
Kategorie 1
-
bla
Kategorie 1
-bla
Kategorie 2
-bla
Kategorie 3
-bla

Aber es soll so aus sehn.
Kategorie 1
-bla
-bla
-bla
Kategorie 2
-bla
Kategorie 3
-bla

Auf Kommentare habe ich erstmal verzichtet in der Template.php sonst würde das hier zu lange. Hoffe das der code klar ist, sonst erklär ich es noch mal.


Gruß
Alex
Victorious ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 08.09.2008, 01:20 Nach oben    #2
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard

hm keiner ne idee?
Victorious ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 08.09.2008, 11:15 Nach oben    #3
Verplanter Benutzer
 
Registriert seit: 14.12.2004
Beiträge: 238
Standard

meinst Du sowas in die Richtung evtl. ?

PHP-Code:
            foreach($data as $key => $value) {

                if(
is_int($key) AND $lastkey == $key ){
                    
$node $document->createElement($nodeName);
                } else {
                    
$node $document->createElement($key);

                }
                
$node $root->appendChild($node);
                
$this->generateXMLNode($value$node$document,$nodeName);

                
$lastkey $key;
            } 
__________________
Das Leben ist zwar bloß ein Adventure-Game, aber die Grafik ist verdammt gut.
Ich such immer noch den Cheat für unlimited money!
DasMööp ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 08.09.2008, 12:04 Nach oben    #4
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard

Das funktinoiert leider nicht. Da kommt der fehler

Code:
Undefined variable: lastkey 
So sollte das XML file aussehn

Code:
<test>
    <news>
        <kat>test</kat>
        <content>
            <name>blabla</name>
        </content>
        <content>
            <name>blabla</name>
        </content>
        <content>
            <name>blabla</name>
        </content>
    </news>
    <news>
        <kat>bla2</kat>
        <content>
            <name>blabla</name>
        </content>
    </news>
    <news>
        <kat>bla3</kat>
        <content>
            <name>blabla</name>
        </content>
    </news>
</test>
Hab nun auch bissel was an der Abfrage geändert das sieht nun so aus.

PHP-Code:
        $this->registry['tpl']->load('koosai/test');
        
$db = new MySQL();
        
$db->query("SELECT * FROM kat ");
        
        while (
$data $db->fetchRow()) {
            
$kat[] = $data;
            
$db1 = new MySQL();
            
$db1->query("SELECT * FROM test where kate = '".$data['kat']."'");
                while(
$dat $db1->fetchRow()){
                    
$zeilen[] = $dat;
                }
    
            
$test[] = array_merge($data ,$zeilen);
            unset(
$zeilen);
        }
  
        
$this->registry['tpl']->assign('test',$test,'news');
        
$this->registry['tpl']->out(); 
Und das jetztig XML file sieht so aus wo "content" steht, steht auch news. Ist auch klar weil der key dazu auch nen int ist und das wird dann mit dem $nodeName versehn.

Geändert von Victorious (08.09.2008 um 12:08 Uhr)
Victorious ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 09.09.2008, 06:12 Nach oben    #5
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard

So nach stunden langer probiererei habe ich doch noch ne lösung gefunden. Ich weiss nur nicht ob die so wirklich elegant ist. Das ganze sieht nun so aus.

In der Template.php habe ich nun das hinzugefügt.

PHP-Code:
    public function createRoot($rootname){
        return  
$this->oDom->appendChild($this->oDom->createElement($rootname));
    }



    public function 
appendChild($parent,$nodeName,$nodeText=""){
        if(
$nodeText != ""){
            
$this->node   =    $parent->appendChild($this->oDom->createElement($nodeName,$nodeText));

        } else {
            
$this->node $parent->appendChild($this->oDom->createElement($nodeName));
        }
        return 
$this->node;
    } 
Die erste Methode erzeugt wie schon der Name sagt das Root Element und die zeite die ChildNodes.

Weiter hin habe ich noch die beiden methoden drin.
PHP-Code:
    private function generateXMLNode($data$root$document) {
        if(
is_array($data)) {
            foreach(
$data as $key => $value ) {
                
$node $document->createElement($key);
                
$node $root->appendChild($node);
                
                
$this->generateXMLNode($value$node$document);

            }

        } else {
            
$node $document->createTextNode($data);
            
$node $root->appendChild($node);
        }
    }

    public function 
createXmlOfAssoArray($replace$replacement){
        
$root $this->oDom->createElement($replace);
        
$root $this->oDom->appendChild($root);

        
$this->generateXMLNode($replacement$root$this->oDom);
    } 
Falls ein Assoziatives array vor liegt.

Und der code der das ausführt sieht so aus.
PHP-Code:
        $this->registry['tpl']->load('koosai/test');
        
        
$db = new MySQL();
        
$db->query("SELECT * FROM kat ");

        
$root $this->registry['tpl']->createRoot('links');

        while (
$data $db->fetchRow()) {

            
$kategorie $this->registry['tpl']->appendChild($root,'kategorie');
            
            foreach(
$data as $k => $v){
                
$this->registry['tpl']->appendChild($kategorie,$k,$v);
                
$link $this->registry['tpl']->appendChild($kategorie,'link');
            
            }

                
$db1 = new MySQL();
                
$db1->query("SELECT * FROM test where kate = '".$data['kat']."'");
                
                while(
$dat $db1->fetchRow()){
                    
                    foreach(
$dat as $key => $value){
                        
$this->registry['tpl']->appendChild($link,$key,$value);
                    }
                }
        }
        
$this->registry['tpl']->out();
        
$db->disconnect(); 
Victorious ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 10.09.2008, 00:02 Nach oben    #6
Verplanter Benutzer
 
Registriert seit: 14.12.2004
Beiträge: 238
Standard

Naja, der Fehler kommt daher das die Variable nicht dekl. wurde.

PHP-Code:
            $lastkey null# hier wird sie festgelegt

            
foreach($data as $key => $value) { 

                if(
is_int($key) AND $lastkey == $key ){ 
                    
$node $document->createElement($nodeName); 
                } else { 
                    
$node $document->createElement($key); 

                } 
                
$node $root->appendChild($node); 
                
$this->generateXMLNode($value$node$document,$nodeName); 

                
$lastkey $key
            } 
__________________
Das Leben ist zwar bloß ein Adventure-Game, aber die Grafik ist verdammt gut.
Ich such immer noch den Cheat für unlimited money!
DasMööp ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 10.09.2008, 19:06 Nach oben    #7
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard

selbst wenn ich sie deklariere gehts nicht.
Victorious ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 11.09.2008, 02:45 Nach oben    #8
Verplanter Benutzer
 
Registriert seit: 14.12.2004
Beiträge: 238
Standard

Hast es ja gelöst, aber nur aus Intersse ... diese Schleife soll doch unterscheiden ob das ein Titel oder ein Untertitel wird.


Zu meinem Beispiel ist glaube ich auch das Array falsch aufgebaut. (Geschmacksache)
Ich bin davon ausgegangen das

array[titel][untertitel]

und daher die Schleife eben in der Art, wenn der letzte Titel gleich ist für nur
Untertitel hinzu ist er anders mache beides, erst Titel dann Untertitel.

abgespeckt:
PHP-Code:
            $lastkey null

            foreach(
$data as $key => $value) {  

                if(empty(
$lastkey)) OR $lastkey != $key){  #empty für den ersten

                    #erstelle Titel -> $key

                
} else {                

                    
#erstelle Untertitel -> $unit

                
}

                
$lastkey $key;  
            } 
oder wegen mit auch mit array([i]array([titel][untertitel]))
nur mal so als Beispiel ...

PHP-Code:
            $lastkey null

            foreach(
$data as $key => $value) {  

                if(empty(
$lastkey)) OR $lastkey != $value[0]){  #empty für den ersten

                    #erstelle Titel -> $value[0]

                
} else {                

                    
#erstelle Untertitel -> $value[1]

                
}

                
$lastkey $value[0];  
            } 
__________________
Das Leben ist zwar bloß ein Adventure-Game, aber die Grafik ist verdammt gut.
Ich such immer noch den Cheat für unlimited money!

Geändert von DasMööp (11.09.2008 um 02:56 Uhr)
DasMööp ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 11.09.2008, 03:08 Nach oben    #9
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard

Das problem ist das die daten aus der Datenbank kommen. Wenn man nun die daten so abfängt.

PHP-Code:
while($data=$db->fetch()){
    
$kategorie $data;
    
    while(
$dat$db2->fetch()){
        
$content[] = $dat;
   
     }
 
     
$all[] = array_merge($kategorie,$content);
     unset(
$content);

sieht da array so aus
Code:
array
  0 => 
    array
      'kategorie' => string 'bla' 
      0 => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla' 
      1 => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla' 
      2 => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla' 
  1 => 
    array
      'kategorie' => string 'bla2' 
      0 => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla2' 
  2 => 
    array
      'kategorie' => string 'bla3' 
      0 => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla3' 
aber ich hätte das ganze gerne so
Code:
array
  ' kategories '=> 
    array
      'kategorie' => string 'bla' 
      links => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla' 

        array
          'name' => string 'blabla' 
          'kate' => string 'bla' 
 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla' 
  
      'kategorie' => string 'bla2' 
      links => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla2' 
  
      'kategorie' => string 'bla3' 
      links => 
        array
          'name' => string 'blabla' 
          'kate' => string 'bla3' 
Aber das geht wohl nicht, wegen den gleichen keys. Und ich hab auch keine Ahnung wie man die Daten aus der Datenbank anders raus bekommen könnte.
Victorious ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 11.09.2008, 14:09 Nach oben    #10
Verplanter Benutzer
 
Registriert seit: 14.12.2004
Beiträge: 238
Standard

ähm ... jetzt komm ich ned mit. Das Array aus der Datenbank gib das mal per print_r() aus ... bzw. da hätte ich es schon anders gemacht bei der Abfrage.

PHP-Code:

        $this
->registry['tpl']->load('koosai/test');
        
$db = new MySQL();
        
$db->query("SELECT kat FROM kat ");
        
        while (
$data $db->fetchRow()) {

#            $db1 = new MySQL(); #warum nochmal eine Verbindung ???
            
$db->query("SELECT id,name,link FROM test where kate = '".$data['kat']."'"); 
            while(
$dat $db->fetchRow()){
                    
$subLink['name'] = $dat['link'];
                }
            
            
# hier das array subLink sortieren zB.

            
$test[$data['kat']][] = $subLink;

    
        }
  
        
$this->registry['tpl']->assign('test',$test,'news');
        
$this->registry['tpl']->out(); 
Damit müsste das Array wie folgt aussehen:

Code:
array 'kategorie1' =>
            array 0 =>
                array 'name', 'link'
            array 1 =>
                array 'name', 'link'
            array 2 =>
                array 'name', 'link'

array 'kategorie2' =>
            array 0 =>
                array 'name', 'link'
            array 1 =>
                array 'name', 'link'

PHP-Code:

foreach($data as $dataKey => $dataValue) { 

    
#erstelle Titel -> $dataKey

    
foreach($dataValue as $key => $value) {   

        
#erstelle SubTitel $value[0] als Name mit $value[1] als Link

    
}


ungetestet ... keine Zeit
__________________
Das Leben ist zwar bloß ein Adventure-Game, aber die Grafik ist verdammt gut.
Ich such immer noch den Cheat für unlimited money!

Geändert von DasMööp (11.09.2008 um 14:13 Uhr)
DasMööp ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 11.09.2008, 17:16 Nach oben    #11
Benutzer
 
Registriert seit: 16.09.2007
Beiträge: 65
Standard

Grml das macht langsam keinen spass mehr ^^.

Also dein code hat ned ganz geklappt musste es ein wenig umstellen sieht nun so aus.
PHP-Code:
        $this->registry['tpl']->load('koosai/test');
        
$db = new MySQL();
        
$db->query("SELECT * FROM kat ");

        while (
$data $db->fetchRow()) {

            
$db1 = new MySQL(); //Weil mir sonst das query überschrieben wird.
            
$db1->query("SELECT * FROM test where kate = '".$data['kat']."'");
            while(
$dat $db1->fetchRow()){
                
$subLink[]['name'] = $dat['name'];

            }

            
$test[$data['kat']]=$subLink;
            unset(
$subLink);

        }

        
$this->registry['tpl']->assign('test',$test);
        
$this->registry['tpl']->out(); 
PHP-Code:
            foreach($data as $dataKey => $dataValue) {


                if(
is_int($dataKey)){
                    foreach(
$dataValue as $key => $value){
                        
$root->appendChild($document->createElement($key,$value));
                    }
                } else{
                    
$node $root->appendChild($document->createElement('kategorie',$dataKey));
                    
$node $root->appendChild($document->createElement('content'));
                    foreach(
$dataValue as $key => $value) {


                        foreach(
$value as $k => $v){

                            
$node->