Mailinglisten-Archive |
Hallo Sacha, Peter und Yannik, erstmal vielen Dank für eure Antworten und Entschuldigung, dass ich mich erst jetzt wieder dazu melde. Ich antworte mal in einer Mail, damit ich nicht alles nochmal schreiben muss. Zu Peter: Danke dass du sogar ein konkretes Beispiel für das Problem erstellt hast http://www.media-palette.de/test/xmltable.zip Letztendlich habe ich es jetzt vom Prinzip her gleich gemacht wie du, nur dass ich direkt DOM verwendet habe mit ein klein wenig str_replace, anstatt DOMCharacterData. Details dazu sind weiter unten. Deine Klasse habe ich mir noch nicht genauer angesehen, habe nur mal die Beschreibung dazu auf deiner Seite durchgelesen. In meinem konkreten Fall würde deine XML-Line Klasse wohl vollkommen ausreichen, wobei mir die Verwendung von DOM im Prinzip sehr zusagt. Ich muss mich diesbezüglich nur noch ein wenig mehr einarbeiten. Trotzdem vielen Dank nochmal, dass du dir die Mühe gemacht hast, das zu demonstrieren. Mit deiner Klasse könnten ja prinzipiell auch mehrere XML-Dateien bearbeitet werden - oder? Eine .odt Datei besteht ja aus mehreren XML-Dateien, die evtl. zu bearbeiten wären. Ich werde mir deine Klasse auf jedenfall nochmal genauer anschauen. Sascha Grossenbacher wrote: > Meiner Meinung nach solltest du nicht verschiedene Technologien > miteinander vermischen. Entweder machst du ein Template, dann kannst du > mit einer Template-Klasse auch direkt in der Vorlage eine Schleife > machen, die ist nämlich genau für solche Sachen gedacht. Das hat > allerdings den Nachteil das die Vorlage nicht mehr mit OO bearbeitet > werden, weil es dann nicht mehr valides XML ist. > > Oder, du machst es mit DOM bzw. allgemein mit XML, dann kannst du, > genauso wie du Nodes kopieren etc. kannst, auch den Inhalt und Attribute > von denen verändern und schreiben. Dann kannst du auch genau angeben, > welche Zeile du bearbeiten willst. genau das habe ich versucht - alles mit DOM zu machen, aber hier gab es halt die Probleme die ich nicht gelöst bekommen habe, daher bin ich auf str_replace ausgewichen und habe die Technologien vermischt. Ich hatte das hier probiert: ... if ( strstr( $node_list->item($i)->nodeValue, '{NO. RECEIPTS}' ) ) { $parent_node = $node_list->item($i)->parentNode; $actual = $node_list->item($i); } for ( $r = 0; $r < count( $focus->receipts ) - 1; $r++ ) { $actual->nodeValue = str_replace( '{NO. RECEIPTS}', $focus->number ); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // das dann für jeden Platzhalter // clone actual node and append it to his parent $cloned_node[$r] = $actual->cloneNode( true ); $appended_node[$r] = $parent_node->appendChild( $cloned_node[$r] ); } ... Das Ersetzen hat an sich schon geklappt, aber leider/komischerweise werden dann z.B. Formatierungen der Childs (auch komplette table-cells) in dem aktuellen Knoten gelöscht und der korrekt ersetzte Inhalt eingetragen. Das führt natürlich dazu, dass in OO nix mehr geht. Da gibts ja eigentlich DOMCharacterData->replaceData() dafür - eigentlich genau das was ich für mein Vorhaben brauche, aber ich habe es nicht geschafft es korrekt zu benutzen... :( Wo und wie könnte ich das in meinem Beispiel oben einsetzen?). Ansonsten habe ich erst die Knoten vervielfältigt und dann die Vorkommen der Platzhalter im gesamten XML-String geparst und gefüllt. Das hab ich jetzt so gelöst: // define all non-table fields to replace $odt_expenses_data = array( '{NO}' => $focus->number, '{USERNAME}' => $user->last_name . ", " . $user->first_name, '{DATE FROM}' => $focus->date_start, '{DATE TO}' => $focus->date_end, '{DESTINATION}' => $focus->destination, '{DESCRIPTION}' => $focus->description, '{TIME FROM}' => $focus->time_start, '{TIME TO}' => $focus->time_end, '{COUNTRY}' => $focus->country, '{AMOUNT}' => $focus->amount ); // define all table fields to replace // retrieve all receipts for an expense for ( $s = 0; $s < count( $focus->receipts ); $s += 1 ) { $odt_receipts_data[] = array( '{NO. RECEIPTS}' => $s + 1, '{RECEIPT CATEGORY}' => $focus->receipts[$s]->category, '{RECEIPT AMOUNT}' => $focus->receipts[$s]->amount, '{RECEIPT DESCRIPTION}' => $focus->receipts[$s]->name ); } // normal replacement // replace from $odt_expenses_data each entry with the belonging data foreach ( $odt_expenses_data as $odt_key => $odt_value ) { $odt_content = $odt->replaceOdtContent( $odt_key, $odt_value, $odt_content ); } // Table replacement // replace from $odt_receipts_data[] each entry for ( $s = 0; $s < count( $focus->receipts ); $s++ ) { foreach ( $odt_receipts_data[$s] as $receipt_key => $receipt_value ) { $pos = strpos( $odt_content, $receipt_key ); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $odt_content = substr_replace( $odt_content, $receipt_value, $pos, strlen( $receipt_key ) ); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } } also Stück für Stück vorangeschritten und ersetzt. > > Ode, als dritte Alternative, du verwendest eine OpenDocument-Klasse [1], > [2]. Scheinen aber beide noch in einem sehr frühen Stadium zu sein, ich > bezweifle das man sie schon für produktive Sachen einsetzen kann. Die habe ich lange getestet und lange dran rumgeschraubt, aber die sind noch in einem so frühen Stadium, dass das echt momentan keine Alternative war. End-User Dokumentation hab ich zu beiden auch nicht gefunden, nur die API Doku. Die Beispiele habe ich bei beiden nach echt langem Probieren auch nicht zum Laufen gebracht (vielleicht lags auch an mir...), daher hab ich mir "schnell" eine eigene Klasse gebastelt, die im Prinzip genau das gleiche macht wie die beiden, aber natürlich erstmal auf mein Problem beschränkte Funktionalität bietet. > > Gruss Sascha > > [1] http://pear.php.net/package/OpenDocument > [2] http://opendocumentphp.org/ Danke für eure Antworten und sorry für meine lange Antwort. Gruss Andi
php::bar PHP Wiki - Listenarchive