XML Einführung KAPITEL. Max. Linie. Max. Linie 516 Kapitel 14: XML. irstleft. Kapitel

Größe: px
Ab Seite anzeigen:

Download "XML. 14.0 Einführung KAPITEL. Max. Linie. Max. Linie 516 Kapitel 14: XML. irstleft. Kapitel"

Transkript

1 irstleft Kapitel KAPITEL XML 14.0 Einführung XML ist in vielen Bereichen wichtig, so für das Speichern, Verarbeiten und Veröffentlichen von Informationen und in der Netzwerkkommunikation. In diesem Kapitel werden Sie lernen, wie Sie mit XML in C++ arbeiten können. Da sich dieses Buch eher um C++ als um XML dreht, werde ich davon ausgehen, dass Sie schon etwas Erfahrung mit den verschiedenen XML-Technologien haben, die ich behandle. Dazu gehören SAX, DOM, XML Schema, XPath und XSLT. Machen Sie sich keine Sorgen, wenn Sie nicht in all diesen Gebieten ein Experte sind; die Rezepte in diesem Kapitel sind mehr oder weniger unabhängig voneinander, so dass Sie durchaus manche der Rezepte überspringen und trotzdem den Rest verstehen können. Auf jeden Fall bietet jedes Rezept eine kurze Erläuterung des entsprechenden XML-Konzepts und stellt die Tools vor, die es verwendet. Wenn Sie bisher mit einer anderen Programmiersprache, wie zum Beispiel Java, gearbeitet haben, gehen Sie vielleicht davon aus, dass sich die Tools zum Verarbeiten von XML in C++ in der Standardbibliothek befinden. Leider befand sich XML noch in seinen Kinderschuhen, als der C++-Standard abgesegnet wurde. Auch wenn es ein starkes Interesse daran gibt, XML-Verarbeitung in zukünftigen Versionen der C++-Standardbibliothek hinzuzufügen, müssen Sie derzeit auf die Reihe exzellenter XML-Bibliotheken von anderen Firmen zurückgreifen. Bevor Sie damit beginnen, die Rezepte zu lesen, wollen Sie vielleicht die Bibliotheken herunterladen und installieren, die ich in diesem Kapitel behandele. Tabelle 14-1 zeigt die Homepage jeder Bibliothek; Tabelle 14-2 führt die Features auf und die Rezepte, die die Bibliotheken nutzen. Die Tabelle zeigt nicht den genauen Umfang, in dem eine Bibliothek die verschiedenen XML-Spezifikationen und Empfehlungen erfüllt, da sich diese Information vermutlich schnell wieder ändern wird. 516 Kapitel 14: XML

2 echts Tabelle 14-1: C++-Bibliotheken für XML Bibliotheksname TinyXml Xerxes Xalan Pathan 1 Boost.Serialization Homepage xml.apache.org/xerces-c xml.apache.org/xalan-c software.decisionsoft.com/pathanintro.html Tabelle 14-2: Wo jede Bibliothek verwendet wird Bibliotheksname Features Rezepte TinyXml DOM (kein vollständiger Standard) 14.1 Xerxes SAX2, DOM, XML Schema Xalan XSLT, XPath Pathan XPath 14.8 Boost.Serialization XML Serialization Ein einfaches XML-Dokument parsen Problem Sie haben Daten, die in einem XML-Dokument abgelegt sind. Sie wollen das Dokument parsen und die enthaltenen Daten in C++-Objekten ablegen. Ihr XML-Dokument ist klein genug, um komplett in den Speicher zu passen, und es verwendet auch keine interne Document Type Definition (DTD) oder XML-Namespaces. Lösung Verwenden Sie die Bibliothek TinyXml. Definieren Sie zunächst ein Objekt des Typs TiXmlDocument, und rufen Sie dessen Methode LoadFile() auf, wobei Sie den Pfad auf Ihr XML-Dokument als Argument übergeben. Wenn LoadFile() true zurückgibt, wurde Ihr Dokument erfolgreich geparst. Wenn das Parsen erfolgreich war, rufen Sie die Methode RootElement() auf, um einen Zeiger auf ein Objekt des Typs TiXmlElement zu erhalten, das die Wurzel des Dokuments darstellt. Dieses Objekt hat eine hierarchische Struktur, die die Struktur Ihres XML-Dokuments widerspiegelt. Indem Sie diese Struktur durchlaufen, können Sie Informationen über das Dokument extrahieren und diese nutzen, um die gewünschten C++-Objekte zu erstellen. Stellen Sie sich zum Beispiel vor, dass Sie ein XML-Dokument animals.xml haben, das eine Kollektion von Zirkus-Tieren enthält, wie in Beispiel 14-1 gezeigt. Die Wurzel des Dokuments hat den Namen animallist und enthält eine Reihe von Kind-Elementen animal, die jeweils ein Tier darstellen, das dem Zirkus der Familie Feldmann gehört. Stel Ein einfaches XML-Dokument parsen 517

3 len Sie sich auch vor, dass Sie eine C++-Klasse Animal haben und nun einen std::vector mit dieser Klasse erstellen wollen, in dem die im Dokument aufgeführten Tiere abgelegt werden. Links Beispiel 14-1: Ein XML-Dokument mit einer Liste von Zirkus-Tieren <?xml version="1.0" encoding="utf-8"?> <!-- Tiere des Zirkus Familie Feldmann --> <animallist> <animal> <name>herbert</name> <species>elefant</species> <dateofbirth> </dateofbirth> <veterinarian name="dr. Harry Braun" phone="(01234) "/> <trainer name="bob Fischer" phone="(01234) "/> </animal> <animal> <name>sheila</name> <species>papagei</species> <dateofbirth> </dateofbirth> <veterinarian name="dr. Kevin Winters" phone="(01234) "/> <trainer name="eli Wendel" phone="(01234) "/> </animal> <animal> <name>dippy</name> <species>pinguin</species> <dateofbirth> </dateofbirth> <veterinarian name="dr. Barbara Schwan" phone="(01234) "/> <trainer name="ben Waxmann" phone="(01234) "/> </animal> </animallist> Beispiel 14-2 zeigt, wie die Definition der Klasse Animal aussehen kann. Animal hat fünf Datenelemente, jeweils eines für den Namen des Tiers, die Spezies, das Geburtsdatum, den Tierarzt und den Trainer. Der Name und die Spezies eines Tiers sind durch std:: string dargestellt, das Geburtsdatum durch ein boost::gregorian::date aus Boost.Date_ Time, und Tierarzt und Trainer sind Instanzen der Klasse Contact, die auch in Beispiel 14-2 definiert ist. Beispiel 14-3 zeigt, wie Sie TinyXml nutzen können, um das Dokument animals.xml zu parsen, durch das geparste Dokument zu laufen und einen std::vector der Klasse Animal mit den Daten zu füllen, die aus dem Dokument gelesen wurden. Beispiel 14-2: Der Header animal.hpp #ifndef ANIMALS_HPP_INCLUDED #define ANIMALS_HPP_INCLUDED #include <ostream> #include <string> 518 Kapitel 14: XML

4 echts Beispiel 14-2: Der Header animal.hpp (Fortsetzung) #include <stdexcept> // runtime_error #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/regex.hpp> // Einen Tierarzt oder Trainer darstellen class Contact public: Contact( ) Contact(const std::string& name, const std::string& phone) : name_(name) setphone(phone); std::string name( ) const return name_; std::string phone( ) const return phone_; void setname(const std::string& name) name_ = name; void setphone(const std::string& phone) using namespace std; using namespace boost; // Mit Boost.Regex prüfen, ob die Telefonnummer // die Form (0ddd[d])dddd[dddd] hat. static regex pattern("\\(0[1-9][0-9]2[0-9]*\\)[1-9][0-9]3[0-9]*"); if (!regex_match(phone, pattern)) throw runtime_error(string("ungültige Telefonnummer:") + phone); phone_ = phone; private: std::string name_; std::string phone_; ; // Zwei Kontakte auf Gleichheit prüfen; wird in Rezept 14.9 genutzt // (der Vollständigkeit halber sollten Sie auch operator!= definieren) bool operator==(const Contact& lhs, const Contact& rhs) return lhs.name() == rhs.name() && lhs.phone() == rhs.phone(); // Einen Kontakt in einen ostream schreiben std::ostream& operator<<(std::ostream& out, const Contact& contact) out << contact.name( ) << " " << contact.phone( ); return out; // Ein Tier darstellen class Animal public: // Default-Konstruktor erstellt ein Animal, dies ist der // Konstruktor, den Sie am häufigsten nutzen werden Ein einfaches XML-Dokument parsen 519

5 Beispiel 14-2: Der Header animal.hpp (Fortsetzung) Animal( ) Links // Ein Animal mit den gegebenen Eigenschaften erstellen; // dieser Konstruktor wird in Rezept 14.9 genutzt. Animal( const std::string& name, const std::string& species, const std::string& dob, const Contact& vet, const Contact& trainer ) : name_(name), species_(species), vet_(vet), trainer_(trainer) setdateofbirth(dob); // Getter std::string name( ) const return name_; std::string species( ) const return species_; boost::gregorian::date dateofbirth( ) const return dob_; Contact veterinarian( ) const return vet_; Contact trainer( ) const return trainer_; // Setter void setname(const std::string& name) name_ = name; void setspecies(const std::string& species) species_ = species; void setdateofbirth(const std::string& dob) dob_ = boost::gregorian::from_string(dob); void setveterinarian(const Contact& vet) vet_ = vet; void settrainer(const Contact& trainer) trainer_ = trainer; private: std::string name_; std::string species_; boost::gregorian::date dob_; Contact vet_; Contact trainer_; ; // Zwei Animals auf Gleichheit prüfen, wird in Rezept 14.9 genutzt. // (Zum Komplettieren sollten Sie auch operator!= definieren.) bool operator==(const Animal& lhs, const Animal& rhs) return lhs.name() == rhs.name() && lhs.species() == rhs.species() && lhs.dateofbirth() == rhs.dateofbirth() && lhs.veterinarian() == rhs.veterinarian() && lhs.trainer() == rhs.trainer(); 520 Kapitel 14: XML

6 echts Beispiel 14-2: Der Header animal.hpp (Fortsetzung) // Ein Animal in einen ostream schreiben std::ostream& operator<<(std::ostream& out, const Animal& animal) out << "Tier \n" << " Name=" << animal.name( ) << ";\n" << " Spezies=" << animal.species( ) << ";\n" << " Geburtsdatum=" << animal.dateofbirth( ) << ";\n" << " Tierarzt=" << animal.veterinarian( ) << ";\n" << " Trainer=" << animal.trainer( ) << ";\n" << ""; return out; #endif // #ifndef ANIMALS_HPP_INCLUDED Beispiel 14-3: animals.xml mit TinyXml parsen #include <exception> #include <iostream> #include <stdexcept> #include <cstdlib> #include <cstring> #include <vector> #include <tinyxml.h> #include "animal.hpp" // cout // runtime_error // EXIT_FAILURE // strcmp using namespace std; // Den Inhalt eines XML-Elements auslesen, das nur Text enthält const char* textvalue(tixmlelement* e) TiXmlNode* first = e->firstchild( ); if ( first!= 0 && first == e->lastchild( ) && first->type( ) == TiXmlNode::TEXT ) // Das Element e hat ein einzelnes Kind vom Typ TEXT; // Inhalt zurückgeben. return first->value( ); else throw runtime_error(string("falsches Element ") + e->value( )); // Einen Contact aus den Elementen "veterinarian" oder "trainer" erstellen Contact nodetocontact(tixmlelement* contact) using namespace std; const char *name, *phone; if ( contact->firstchild( ) == 0 && (name = contact->attribute("name")) && (phone = contact->attribute("phone")) ) 14.1 Ein einfaches XML-Dokument parsen 521

7 Beispiel 14-3: animals.xml mit TinyXml parsen (Fortsetzung) // Das Element contact hat keine Kinder, aber "name" und // "phone" als Attribute; nutze diese Werte, um einen // Contact zu erstellen return Contact(name, phone); else throw runtime_error(string("falsches Element ") + contact->value( )); Links // Ein Animal aus einem Element "animal" erstellen Animal nodetoanimal(tixmlelement* animal) using namespace std; // Prüfen, ob animal zu einem Element "animal" gehört if (strcmp(animal->value( ), "animal")!= 0) throw runtime_error(string("falsches animal: ") + animal ->Value( )); Animal result; // Rückgabewert TiXmlElement* element = animal->firstchildelement( ); // Name lesen if (element && strcmp(element->value( ), "name") == 0) // Das erste Kindelement von animal ist ein Element "name"; // mit dessen Textwert wird der Name von result gesetzt. result.setname(textvalue(element)); else throw runtime_error("kein Namens-Attribut"); // Spezies lesen element = element->nextsiblingelement( ); if (element && strcmp(element->value( ), "species") == 0) // Das zweite Kindelement von animal ist ein Element "species"; // mit ihm wird die Spezies von result gesetzt. result.setspecies(textvalue(element)); else throw runtime_error("kein Attribut für Spezies"); // Geburtsdatum lesen element = element->nextsiblingelement( ); if (element && strcmp(element->value( ), "dateofbirth") == 0) // Das dritte Kindelement von animal ist ein Element "dateofbirth"; // damit das Geburtsdatum von result setzen. result.setdateofbirth(textvalue(element)); else throw runtime_error("kein Attribut für Geburtsdatum"); 522 Kapitel 14: XML

8 echts Beispiel 14-3: animals.xml mit TinyXml parsen (Fortsetzung) // Tierarzt einlesen element = element->nextsiblingelement( ); if (strcmp(element->value( ), "veterinarian") == 0) // Das vierte Kindelement von animal ist ein Element "veterinarian"; // damit ein Contact-Objekt erstellen und den Tierarzt von // result setzen result.setveterinarian(nodetocontact(element)); else throw runtime_error("kein Tierarzt-Attribut"); // Trainer einlesen element = element->nextsiblingelement( ); if (strcmp(element->value( ), "trainer") == 0) // Das fünfte Element von animal ist ein "trainer"; // damit ein Contact-Objekt erstellen und den Trainer von // result setzen result.settrainer(nodetocontact(element)); else throw runtime_error("kein Trainer-Attribut"); // Prüfen, dass es keine weiteren Elemente gibt element = element->nextsiblingelement( ); if (element!= 0) throw runtime_error( string("unerwartetes Element:") + element->value( ) ); return result; int main( ) using namespace std; try vector<animal> animallist; // "animals.xml" parsen TiXmlDocument doc("animals.xml"); if (!doc.loadfile( )) throw runtime_error("parsen misslungen"); // Prüfen, dass die Wurzel eine animallist ist TiXmlElement* root = doc.rootelement( ); if (strcmp(root->value( ), "animallist")!= 0) throw runtime_error(string("falsche Wurzel: ") + root->value( )); 14.1 Ein einfaches XML-Dokument parsen 523

9 Beispiel 14-3: animals.xml mit TinyXml parsen (Fortsetzung) Diskussion // Über die Kinder von Root laufen und die Liste mit // Tieren füllen for ( TiXmlElement* animal = root->firstchildelement( ); animal; animal = animal->nextsiblingelement( ) ) animallist.push_back(nodetoanimal(animal)); // Ausgeben der Namen der Tiere for ( vector<animal>::size_type i = 0, n = animallist.size( ); i < n; ++i ) cout << animallist[i] << "\n"; catch (const exception& e) cout << e.what( ) << "\n"; TinyXml ist eine ausgezeichnete Wahl für Anwendungen, die nur ein wenig mit XML arbeiten müssen. Die Source-Distribution ist klein, es lässt sich leicht bauen und in andere Projekte integrieren, und es hat eine sehr einfache Schnittstelle. Zudem ist die Lizenz sehr freizügig. Der Hauptnachteil ist, dass keine XML-Namespaces verstanden werden, dass nicht gegen eine DTD oder ein Schema validiert werden kann und dass keine XML-Dokumente geparst werden können, die eine interne DTD enthalten. Wenn Sie eines dieser Features brauchen oder eine der XML-Technologien wie XPath oder XSLT notwendig ist, sollten Sie eine der anderen in diesem Kapitel behandelten Bibliotheken nutzen. Der TinyXml-Parser erstellt eine Repräsentation eines XML-Dokuments als Baum, dessen Knoten die Elemente, Texte, Kommentare und anderen Komponenten eines XML- Dokuments darstellen. Die Wurzel des Baumes repräsentiert das XML-Dokument selbst. Diese Art von Darstellung eines hierarchischen Dokuments als Baum ist als Document Object Model (DOM) bekannt. Das TinyXml-DOM ist dem ähnlich, das vom World Wide Web-Consortium (W3C) entworfen wurde, auch wenn es nicht den W3C-Spezifikationen entspricht. Aufgrund des minimalistischen Ansatzes von TinyXml ist dessen DOM einfacher als das des W3C, aber auch weniger mächtig. Die Knoten im Baum können über die Schnittstelle TiXmlNode angesprochen werden, die Methoden für den Zugriff auf das Elternelement eines Knotens und eine Aufreihung der Kind-Knoten bietet sowie die Möglichkeit, Kind-Knoten zu löschen oder neu einzufügen. Jeder Knoten ist eigentlich eine Instanz eines weiter abgeleiteten Typs. So ist die Wurzel Links 524 Kapitel 14: XML

10 echts des Baumes zum Beispiel eine Instanz von TiXmlDocument, Knoten, die Elemente darstellen, sind Instanzen von TiXmlElement, und Knoten, die Text darstellen, sind Instanzen von TiXmlText. Der Typ eines TiXmlNode kann über dessen Methode Type() ermittelt werden. Wenn Sie einmal den Typ eines Knotens kennen, können Sie eine Darstellung des Knotens als weiter abgeleiteten Typ erhalten, indem Sie eine der sehr praktischen Methoden todocument(), toelement() und totext() aufrufen. Diese abgeleiteten Typen enthalten zusätzliche Methoden, die zum Typ des dargestellten Knotens passen. Jetzt ist es leicht, Beispiel 14-3 zu verstehen. Die Funktion textvalue() extrahiert den Textinhalt eines Elements, das nur Text enthält, wie zum Beispiel name, species oder dateofbirth. Dazu prüft es zunächst, dass ein Element nur ein Kind hat und dass dieses Kind ein Textknoten ist. Dann liest es den Text des Kind-Knotens aus, indem es die Methode Value() aufruft, die den Textinhalt eines Text- oder Kommentar-Knotens, den Tag-Namen eines Element-Knotens und den Dateinamen eines Wurzel-Knotens zurückgibt. Die Funktion nodetocontact( ) nimmt einen Knoten, der einem Element veterinarian oder trainer entspricht, und erstellt ein Objekt vom Typ Contact aus den Werten der Attribute name und phone, die es über die Methode Attribute() ausliest. Genauso erwartet die Funktion nodetoanimal() einen Knoten, der einem Element animal entspricht, und erzeugt ein Objekt vom Typ Animal. Dazu iteriert sie mit der Methode NextSiblingElement() über die Kind-Knoten, extrahiert die darin enthaltenen Daten und setzt die korrespondierenden Eigenschaften des Animal-Objekts. Die Daten werden für die Elemente name, species und dateofbirth über die Funktion textvalue() ausgelesen, während für die Elemente veterinarian und trainer die Funktion nodetocontact() zum Tragen kommt. In der Funktion main erstelle ich zunächst ein Objekt vom Typ TiXmlDocument, das zur Datei animals.xml gehört, und parse es mit der Methode LoadFile(). Dann erhalte ich ein TiXmlElement, das der Wurzel des Dokuments entspricht, indem ich die Methode RootElement() aufrufe. Nun iteriere ich über die Kind-Knoten des Wurzelelements und erstelle mit nodetoanimal() aus jedem Element animal ein Objekt Animal. Schließlich iteriere ich über die Collection mit Objekten des Typs Animal und schreibe sie in die Standardausgabe. Ein Feature von TinyXml, das nicht in Beispiel 14-3 verwendet wurde, ist die Methode SaveFile( ) von TiXmlDocument, die das durch ein TiXmlDocument dargestellte Dokument in einer Datei speichert. Damit können Sie ein XML-Dokument parsen, es über die DOM-Schnittstelle verändern und das geänderte Dokument wieder abspeichern. Sie können sogar ein TiXmlDocument komplett neu erstellen und es auf der Festplatte speichern: // Ein Dokument hello.xml erstellen, das // nur aus einem einzelnen Element "hello" besteht TiXmlDocument doc; TiXmlElement root("hello"); doc.insertendchild(root); doc.savefile("hello.xml"); 14.1 Ein einfaches XML-Dokument parsen 525

11 Siehe auch Rezepte 14.3 und 14.4 Links 14.2 Mit Xerces-Strings arbeiten Problem Sie wollen mit den von der Xerces-Bibliothek verwendeten Wide-Character-Strings arbeiten. Insbesondere wollen Sie in der Lage sein, von Xerces-Funktionen zurückgegebene Strings auszulesen, aber auch Xerces-Strings und Strings aus der Standardbibliothek von C++ ineinander zu konvertieren. Lösung Sie können die von Funktionen der Xerces-Bibliothek zurückgegebenen Wide-Character- Strings mit dem Template std::basic_string nutzen, das für den Wide-Character-Typ XMLCh von Xerces spezialisiert wurde: typedef std::basic_string<xmlch> XercesString; Um zwischen Xerces-Strings und normalen Strings zu konvertieren, verwenden Sie die überladene statische Methode transcode() aus der Klasse xerces::xmlstring, die im Header xercesc/util/xmlstring.hpp definiert ist. Beispiel 14-4 definiert zwei überladene Hilfsfunktionen tonative und fromnative, die mit Hilfe von transcode Umwandlungen zwischen normalen Strings und Xerces-Strings durchführen. Jede Funktion hat zwei Varianten, eine für einen String im C-Stil und eine für Strings aus der Standardbibliothek von C++. Diese Funktionen sind alles, was Sie brauchen, um Umwandlungen zwischen Xerces- Strings und normalen Strings vorzunehmen. Nachdem Sie sie einmal definiert haben, müssen Sie transcode nie wieder direkt aufrufen. Beispiel 14-4: Der Header xerces_strings.hpp zum Konvertieren zwischen Xerces-Strings und normalen Strings. #ifndef XERCES_STRINGS_HPP_INCLUDED #define XERCES_STRINGS_HPP_INCLUDED #include <string> #include <boost/scoped_array.hpp> #include <xercesc/util/xmlstring.hpp> typedef std::basic_string<xmlch> XercesString; // Aus einem normalen String in einen Wide-Character-String konvertieren. inline XercesString fromnative(const char* str) boost::scoped_array<xmlch> ptr(xercesc::xmlstring::transcode(str)); return XercesString(ptr.get( )); 526 Kapitel 14: XML

12 echts Beispiel 14-4: Der Header xerces_strings.hpp zum Konvertieren zwischen Xerces-Strings und normalen Strings. (Fortsetzung) // Aus einem normalen String in einen Wide-Character-String konvertieren. inline XercesString fromnative(const std::string& str) return fromnative(str.c_str( )); // Aus einem Wide-Character-String in einen normalen String konvertieren. inline std::string tonative(const XMLCh* str) boost::scoped_array<char> ptr(xercesc::xmlstring::transcode(str)); return std::string(ptr.get( )); // Aus einem Wide-Character-String in einen normalen String konvertieren. inline std::string tonative(const XercesString& str) return tonative(str.c_str( )); #endif // #ifndef XERCES_STRINGS_HPP_INCLUDED Um zwischen Xerces-Strings und dem std::wstring zu konvertieren, verwenden Sie einfach den Konstruktor von std::basic_string, der ein Paar von Iteratoren erwartet. Sie können zum Beispiel die folgenden beiden Funktionen definieren: // Aus einem Xerces-String in einen std::wstring konvertieren std::wstring xercestowstring(const XercesString& str) return std::wstring(str.begin(), str.end()); // Aus einem std::wstring in einen XercesString konvertieren XercesString wstringtoxerces(const std::wstring& str) return XercesString(str.begin(), str.end()); Diese Funktionen setzen voraus, dass sowohl wchar_t als auch XMLCh integrale Typen sind, die implizit ineinander konvertiert werden können. Das Ganze sollte unabhängig von der Größe von wchar_t funktionieren, solange keine Werte außerhalb des von XMLCh verwendeten Bereichs vorhanden sind. Sie können ähnliche Funktionen für Strings im C- Stil als Argumente definieren und dabei den Konstruktor von std::basic_string verwenden, der ein Character-Array und eine Länge als Argumente erwartet. Diskussion Xerces verwendet eine null-terminierte Sequenz von Zeichen des Typs XMLCh, um Unicode-Strings darzustellen. XMLCh ist ein typedef für einen implementierungsabhängigen integralen Typ mit einer Größe von mindestens 16 Bit groß genug, um nahezu alle 14.2 Mit Xerces-Strings arbeiten 527

13 bekannten Zeichen in jeder Sprache darzustellen, die einzelne Zeichen verwendet. Xerces nutzt die Zeichenkodierung UTF-16, was bedeutet, dass theoretisch ein paar Unicode- Zeichen durch eine Sequenz von mehr als einem XMLCh dargestellt werden müssen. In der Praxis können Sie allerdings ein XMLCh als eine direkte Darstellung eines Unicode-Zeichens ansehen. Früher war XMLCh als ein typedef für wchar_t definiert, Sie konnten also eine Kopie eines Xerces-Strings einfach in einem std::wstring unterbringen. Momentan definiert Xerces allerdings XMLCh auf allen Plattformen als typedef für unsigned short. Das hat unter anderem zur Folge, dass auf manchen Plattformen XMLCh und wchar_t nicht einmal die gleiche Größe haben. Da Xerces die Definition von XMLCh in Zukunft wieder ändern könnte, dürfen Sie nicht davon ausgehen, dass es zu einem bestimmten Typ identisch ist. Wenn Sie also eine Kopie eines Xerces-Strings speichern wollen, sollten Sie std::basic_string<xmlch> nutzen. Wenn Sie Xerces verwenden, werden Sie häufig zwischen normalen Strings und Xerces- Strings umwandeln müssen. Dazu stellt Xerces die überladene Funktion transcode() bereit. Diese Funktion kann einen Unicode-String in einen normalen String in»nativer«zeichenkodierung oder umgekehrt umwandeln. Was die native Kodierung ausmacht, ist allerdings nicht genau definiert. Wenn Sie also in einer Umgebung entwickeln, in der verschiedene Zeichenkodierungen verwendet werden, müssen Sie eventuell die Dinge selbst in die Hand nehmen und eigene Konvertierungsfunktionen schreiben. Dazu können Sie entweder auf eine Facette std::codecvt zurückgreifen oder die Pluggable Transcoding Services von Xerces nutzen, die in der Dokumentation zu Xerces beschrieben sind. In vielen Fällen ist allerdings transcode() völlig ausreichend. Der von transcode() zurückgelieferte null-terminierte String wird dynamisch mit der Arrayform von operator new alloziert. Es liegt an Ihnen, ihn mit delete [] zu löschen. Das kann Sie allerdings vor ein kleines Speicherverwaltungsproblem stellen, da Sie meist eine Kopie des Strings machen oder ihn in einen Stream schreiben wollen, bevor Sie ihn löschen, wobei Ausnahmen ausgelöst werden können. Ich habe dieses Problem in Beispiel 14-4 behandelt, indem ich das Template boost::scoped_array nutze, das sich zum Eigentümer eines dynamisch angeforderten Arrays macht und es automatisch löscht, wenn der Gültigkeitsbereich verlassen wird selbst dann, wenn eine Ausnahme daran schuld ist. Schauen Sie sich zum Beispiel die Implementierung von fromnative an: inline XercesString fromnative(const char* str) boost::scoped_array<xmlch> ptr(xercesc::xmlstring::transcode(str)); return XercesString(ptr.get( )); Hier übernimmt ptr das Eigentum am null-terminierten String, der von transcode() zurückgegeben wird, und gibt ihn frei, auch wenn der Konstruktor von XercesString eine Ausnahme std::bad_alloc auslöst. Links 528 Kapitel 14: XML

14 echts 14.3 Ein komplexes XML-Dokument parsen Problem Sie haben Daten, die in einem XML-Dokument abgelegt sind, das eine interne DTD oder XML-Namespaces verwendet. Sie wollen das Dokument parsen und die darin enthaltenen Daten in einer Collection von C++-Objekten ablegen. Lösung Nutzen Sie die Xerces-Implementierung der SAX2-API (die Simple API for XML, Version 2.0). Zunächst leiten Sie eine Klasse von xercesc::contenthandler ab. Diese Klasse wird über die Struktur und den Inhalt Ihres XML-Dokuments benachrichtigt, wenn es geparst wird. Danach können Sie bei Bedarf eine Klasse von xercesc::errorhandler ableiten, um auch Warnungen und Fehler zu erhalten. Erstellen Sie einen Parser des Typs xercesc:: SAX2XMLReader, und registrieren Sie Instanzen Ihrer Handler-Klassen mit setcontent- Handler() und seterrorhandler(). Schließlich rufen Sie die Methode parse() der Parser- Klasse auf und übergeben den Dateinamen Ihres Dokuments als Argument. Stellen Sie sich zum Beispiel vor, dass Sie das XML-Dokument animals.xml aus Beispiel 14-1 parsen und einen std::vector mit Animal-Elementen erstellen wollen, der die im Dokument aufgeführten Tiere enthält (siehe Beispiel 14-2 für die Definition der Klasse Animal). In Beispiel 14-3 habe ich gezeigt, wie man das mit TinyXml erreicht. Um das Problem etwas herausfordernder zu machen, wollen wir jetzt dem Dokument Namespaces hinzufügen, wie in Beispiel 14-5 zu sehen ist. Beispiel 14-5: Eine Liste mit Zirkustieren als XML, diesmal mit Namespace <?xml version="1.0" encoding="utf-8"?> <!-- Tiere des Zirkus Familie Feldmann mit Namespaces --> <ffc:animallist xmlns:ffc=" <ffc:animal> <ffc:name>herbert</ffc:name> <ffc:species>elefant</ffc:species> <ffc:dateofbirth> </ffc:dateofbirth> <ffc:veterinarian name="dr. Harry Braun" phone="(01234) "/> <ffc:trainer name="bob Fischer" phone="(01234) "/> </ffc:animal> <!-- etc. --> </ffc:animallist> Um dieses Dokument mit SAX2 zu parsen, definieren Sie einen ContentHandler (wie in Beispiel 14-6 gezeigt) und einen ErrorHandler (siehe Beispiel 14-7). Dann erstellen Sie einen SAX2XMLReader, registrieren Ihre Handler und lassen den Parser laufen. Das ist in Beispiel 14-8 zu sehen Ein komplexes XML-Dokument parsen 529

15 Beispiel 14-6: Ein SAX2-ContentHandler zum Parsen des Dokuments animals_ns.xml #include <stdexcept> // runtime_error #include <vector> #include <xercesc/sax2/attributes.hpp> #include <xercesc/sax2/defaulthandler.hpp> // Enthält leere // Implementierungen der // verschiedenen Handler #include "xerces_strings.hpp" // Beispiel 14-4 #include "animal.hpp" Links using namespace std; using namespace xercesc; // Eine Instanz von Contact basierend auf der gegebenen Collection // von Attributen zurückgeben Contact contactfromattributes(const Attributes &attrs) // Aus Effizienzgründen häufig genutzte Strings in // statischen Variablen speichern static XercesString name = fromnative("name"); static XercesString phone = fromnative("phone"); Contact result; // Kontakt, der zurückgegeben wird. const XMLCh* val; // Wert des Attributs name oder phone. // Name des Kontakts setzen. if ((val = attrs.getvalue(name.c_str( )))!= 0) result.setname(tonative(val)); else throw runtime_error("kontakt ohne Attribute name"); // Telefonnummer des Kontakts setzen. if ((val = attrs.getvalue(phone.c_str( )))!= 0) result.setphone(tonative(val)); else throw runtime_error("kontakt ohne Attribute phone"); return result; // Callbacks implementieren, die Daten und Benachrichtigungen // über den Anfang und das Ende von Elementen liefern class CircusContentHandler : public DefaultHandler public: CircusContentHandler(vector<Animal>& animallist) : animallist_(animallist) // Wenn das aktuelle Element einen Tierarzt oder Trainer darstellt, // attrs zum Erstellen eines Contact-Objekts für das aktuelle Animal // nutzen; sonst currenttext_ leeren, um für den Callback gerüstet // zu sein. 530 Kapitel 14: XML

16 echts Beispiel 14-6: Ein SAX2-ContentHandler zum Parsen des Dokuments animals_ns.xml (Fortsetzung) void startelement( const XMLCh *const uri, // Namespace URI const XMLCh *const localname, // Tagname ohne Namespace const XMLCh *const qname, // Tagname mit Namespace const Attributes &attrs ) // Attribute des Elements static XercesString animallist = fromnative("animallist"); static XercesString animal = fromnative("animal"); static XercesString vet = fromnative("veterinarian"); static XercesString trainer = fromnative("trainer"); static XercesString xmlns = fromnative(" // Namespace-URI prüfen if (uri!= xmlns) throw runtime_error( string("falsche Namespace-URI: ") + tonative(uri) ); if (localname == animal) // Der Liste ein Animal hinzufügen, das ist das neue // "aktuelle Animal" animallist_.push_back(animal( )); else if (localname!= animallist) Animal& animal = animallist_.back( ); if (localname == vet) // Es handelt sich um ein Tierarzt-Element. animal.setveterinarian(contactfromattributes(attrs)); else if (localname == trainer) // Es handelt sich um einen Trainer. animal.settrainer(contactfromattributes(attrs)); else // name, species oder dateofbirth gefunden. // Der Inhalt wird durch die Callback-Funktion // characters( ) bereitgestellt. currenttext_.clear( ); // Wenn das aktuelle Element den Namen, die Spezies oder das // Geburtsdatum darstellt, nutze currenttext_, um die entsprechende // Eigenschaft von Animal zu setzen. void endelement( const XMLCh *const uri, // Namespace-URI const XMLCh *const localname, // Tagname ohne Namespace const XMLCh *const qname ) // Tagname mit Namespace static XercesString animallist = fromnative("animal-list"); static XercesString animal = fromnative("animal"); static XercesString name = fromnative("name"); static XercesString species = fromnative("species"); static XercesString dob = fromnative("dateofbirth"); 14.3 Ein komplexes XML-Dokument parsen 531

17 Beispiel 14-6: Ein SAX2-ContentHandler zum Parsen des Dokuments animals_ns.xml (Fortsetzung) if (localname!= animal && localname!= animallist) // currenttext_ enthält den Inhalt des Elements, das // zu Ende ist. Damit wird die entsprechende // Eigenschaft von Animal gesetzt. Animal& animal = animallist_.back( ); if (localname == name) animal.setname(tonative(currenttext_)); else if (localname == species) animal.setspecies(tonative(currenttext_)); else if (localname == dob) animal.setdateofbirth(tonative(currenttext_)); // Benachrichtigungen erhalten, wenn Zeichendaten auftreten void characters( const XMLCh* const chars, const unsigned int length ) // currenttext_ die Zeichen hinzufügen, damit sie von // endelement( ) verarbeitet werden currenttext_.append(chars, length); private: vector<animal>& animallist_; XercesString currenttext_; ; Links Beispiel 14-7: Ein ErrorHandler für SAX2 #include <stdexcept> // runtime_error #include <xercesc/sax2/defaulthandler.hpp> // Fehlerbenachrichtigungen erhalten. class CircusErrorHandler : public DefaultHandler public: void warning(const SAXParseException& e) /* nichts tun */ void error(const SAXParseException& e) throw runtime_error(tonative(e.getmessage( ))); void fatalerror(const SAXParseException& e) error(e); ; Beispiel 14-8: Das Dokument animals_ns.xml mit der SAX2-API parsen #include <exception> #include <iostream> // cout #include <memory> // auto_ptr #include <vector> #include <xercesc/sax2/sax2xmlreader.hpp> 532 Kapitel 14: XML

18 echts Beispiel 14-8: Das Dokument animals_ns.xml mit der SAX2-API parsen (Fortsetzung) #include <xercesc/sax2/xmlreaderfactory.hpp> #include <xercesc/util/platformutils.hpp> #include "animal.hpp" #include "xerces_strings.hpp" // Beispiel 14-4 using namespace std; using namespace xercesc; // RAII-Tool, das den Parser initialisiert und Ressourcen freigibt, // wenn der Gültigkeitsbereich verlassen wird. class XercesInitializer public: XercesInitializer( ) XMLPlatformUtils::Initialize( ); ~XercesInitializer( ) XMLPlatformUtils::Terminate( ); private: // Kopieren und Zuweisen unterbinden XercesInitializer(const XercesInitializer&); XercesInitializer& operator=(const XercesInitializer&); ; int main( ) try vector<animal> animallist; // Xerces initialisieren und den Parser erhalten XercesInitializer init; auto_ptr<sax2xmlreader> ] parser(xmlreaderfactory::createxmlreader( )); // Handler registrieren CircusContentHandler content(animallist); CircusErrorHandler error; parser->setcontenthandler(&content); parser->seterrorhandler(&error); // Das XML-Dokument parsen parser->parse("animals_ns.xml"); // Namen der Tiere ausgeben for ( vector<animal>::size_type i = 0, n = animallist.size( ); i < n; ++i ) cout << animallist[i] << "\n"; catch (const SAXException& e) cout << "XML-Fehler: " << tonative(e.getmessage( )) << "\n"; catch (const XMLException& e) cout << "XML-Fehler: " << tonative(e.getmessage( )) << "\n"; 14.3 Ein komplexes XML-Dokument parsen 533

19 Beispiel 14-8: Das Dokument animals_ns.xml mit der SAX2-API parsen (Fortsetzung) catch (const exception& e) cout << e.what( ) << "\n"; Diskussion Manche XML-Parser parsen ein XML-Dokument und übergeben es als ein komplexes C++-Objekt an den Benutzer. Der TinyXml-Parser und der W3C-DOM-Parser, den Sie im nächsten Rezept kennen lernen, arbeiten beide auf diese Weise. Der SAX2-Parser nutzt dagegen eine Reihe von Callback-Funktionen, um Informationen über ein XML- Dokument beim Parsen an den Benutzer zu übergeben. Die Callback-Funktionen sind in verschiedene Handler-Schnittstellen unterteilt: ein ContentHandler erhält Benachrichtigungen über die Elemente, Attribute und Texte eines XML-Dokuments, ein ErrorHandler bekommt Warnungen und Fehlermeldungen, und ein DTDHandler erfährt alles über die DTD eines XML-Dokuments. Das Design eines Parsers, der eine Reihe von Callback-Funktionen nutzt, hat viele wichtige Vorteile. So ist es zum Beispiel möglich, Dokumente zu parsen, die so groß sind, dass sie nicht komplett in den Speicher passen würden. Zusätzlich kann Prozesszeit gespart werden, indem man die vielen dynamischen Allozierungen vermeidet, die notwendig sind, um eine interne Darstellung eines XML-Dokuments zu erstellen. Der Benutzer hat zudem die Möglichkeit, seine eigene Darstellung der Daten eines Dokuments anzulegen und muss sich nicht durch den Dokumentenbaum durcharbeiten, wie ich es in Beispiel 14-3 getan habe. Beispiel 14-8 ist ziemlich einfach: Ich beschaffe mir einen SAX2-Parser, registriere einen ContentHandler und einen ErrorHandler, parse das Dokument animals_ns.xml und gebe die Liste aus, die vom ContentHandler mit Objekten des Typs Animal gefüllt wurde. Dabei gibt es zwei interessante Punkte: Zum einen liefert die Funktion XMLReaderFactory:: createxmlreader() eine dynamisch angeforderte Instanz von SAX2XMLReader, die explizit vom Benutzer wieder freigegeben werden muss dafür habe ich einen std::auto_ptr verwendet, um sicherzustellen, dass der Parser gelöscht wird, auch wenn eine Ausnahme auftritt. Zweitens muss das Xerces-Framework mittels xercesc::xmlplatformutils:: Initialize() initialisiert und mit xercesc::xmlplatformutils::terminate() aufgeräumt werden. Ich habe diese Initialisierung und das Aufräumen in einer Klasse namens XercesInitializer gekapselt, die im Konstruktor xercesc::xmlplatformutils::initialize() aufruft und im Destruktor xercesc::xmlplatformutils::terminate(). Damit ist sicher, dass Terminate() aufgerufen wird, auch wenn eine Ausnahme auftritt. Dies ist ein Beispiel der Technik Resource Acquisition Is Initialization (RAII), die in Beispiel 8-3 vorgeführt wurde. Links 534 Kapitel 14: XML

20 echts Sehen wir uns an, wie die Klasse CircusContentHandler aus Beispiel 14-6 die Schnittstelle ContentHandler von SAX2 implementiert. Der SAX2-Parser ruft die Methode startelement() jedes Mal auf, wenn er ein öffnendes Tag eines Elements erreicht. Wenn das Element einen zugehörigen Namespace hat, enthält das erste Argument uri die URI des Namespaces und das zweite Element localname den Teil des Tag-Namens des Elements, der auf dessen Namespace-Präfix folgt. Wenn das Element keinen zugewiesenen Namespace hat, sind in beiden Argumenten leere Strings. Das dritte Argument enthält den Tag- Namen des Elements, wenn es keinen assoziierten Namespace hat, ansonsten steht dort entweder der Tag-Name, wie er im geparsten Dokument auftaucht, oder ein leerer String. Das vierte Argument ist eine Instanz der Klasse Attributes, die die Sammlung der Attribute eines Elements darstellt. In der Implementierung von startelement() aus Beispiel 14-6 habe ich das Element animallist ignoriert. Wenn ich ein Element animal erhalte, füge ich der Liste von Tieren ein neues Animal hinzu lassen Sie uns dies das aktuelle Animal nennen und übergebe das Setzen der Eigenschaften des Animal an den Handler für andere Elemente. Wenn mir ein Element veterinarian oder trainer über den Weg läuft, rufe ich die Funktion contactfromattributes auf, um eine Instanz von Contact aus den Attributen des Elements zu erstellen und dann diesen Contact zu nutzen, um den Tierarzt oder Trainer des aktuellen Animal zu setzen. Wenn ich ein Element name, species oder dateofbirth erhalte, leere ich das Datenelement currenttext_, das genutzt wird, um den Text des Elements zu speichern. Der SAX2-Parser ruft die Methode characters() auf, um die in einem Element enthaltenen Textdaten auszugeben. Der Parser kann die Zeichen eines Elements in einer Reihe von Aufrufen von characters() ermitteln, und solange das schließende Tag eines Elements noch nicht erreicht ist, gibt es keine Garantie, dass alle seine Zeichen schon übermittelt wurden. Konsequenterweise habe ich in der Implementierung von characters() einfach die übergebenen Zeichen an das Datenelement currenttext_ angefügt, über das ich den Namen, die Spezies und das Geburtsdatum des aktuellen Animal setze, sobald das schließende Tag von name, species oder dateofbirth erreicht ist. Der SAX2-Parser ruft die Methode endelement() jedes Mal auf, wenn er ein Element verlässt. Die Argumente haben die gleiche Bedeutung wie die ersten drei Argumente von startelement(). In der Implementierung von endelement() in Beispiel 14-6 ignoriere ich alle Elemente, die nicht name, species oder dateofbirth sind. Wenn ein Callback zu einem dieser Elemente auftaucht und der Parser damit signalisiert, dass er das Element gerade verlässt, verwende ich die in currenttext_ gespeicherten Daten, um den Namen, die Spezies oder das Geburtsdatum des aktuellen Animal zu setzen. Viele wichtige Funktionen von SAX2 tauchen in den Beispielen 14-6, 14-7 und 14-8 gar nicht auf. So bietet die Klasse SAX2XMLReader zum Beispiel eine überladene Variante der Methode parse() an, die eine Instanz von xercesc::inputsource statt eines C-Strings als Argument übernimmt. InputSource ist eine abstrakte Klasse, die eine Quelle mit Zeichendaten kapselt. Die konkreten Unterklassen, zum Beispiel xercesc::membufinputsource 14.3 Ein komplexes XML-Dokument parsen 535

21 und xercesc::urlinputsource, ermöglichen es dem SAX2-Parser, XML-Dokumente zu parsen, die nicht im Dateisystem abgelegt sind. Weiterhin enthält die Schnittstelle ContentHandler viele zusätzliche Methoden, wie zum Beispiel startdocument() und enddocument(), die den Anfang und das Ende des XML- Dokuments signalisieren, sowie setlocator(), mit dem Sie ein Objekt vom Typ Locator angeben können, das sich die aktuelle Position in der gerade zu parsenden Datei merkt. Es gibt noch weitere Handler-Schnittstellen, so zum Beispiel DTDHandler und EntityResolver (aus der eigentlichen SAX 2.0-Spezifikation) und DeclarationHandler und LexicalHandler (aus den standardisierten Erweiterungen zu SAX 2.0). Es ist auch möglich, dass eine einzelne Klasse verschiedene Handler-Schnittstellen implementiert. Die Klasse xercesc::defaulthandler erleichtert das, da sie von allen Handler- Schnittstellen abgeleitet ist und leere Implementierungen ihrer virtuellen Funktionen bereitstellt. Konsequenterweise hätte ich die Methoden aus CircusErrorHandler auch zu CircusContentHandler hinzufügen und Beispiel 14-8 wie folgt anpassen können: // Handler registrieren CircusContentHandler handler(animallist); parser->setcontenthandler(&handler); parser->seterrorhandler(&handler); Es gibt ein letztes Feature von Beispiel 14-8, auf das Sie Ihre Aufmerksamkeit richten sollten: CircusContentHandler prüft nicht, ob das geparste Dokument die korrekte Struktur hat so prüft es zum Beispiel nicht, dass das Wurzelelement eine animallist ist oder dass alle Kinder des Wurzelelements ein animal sind. Das steht im direkten Gegensatz zu Beispiel So prüft zum Beispiel die Funktion main() aus Beispiel 14-3, dass das Wurzelelement eine animallist ist, und die Funktion nodetoanimal() kontrolliert, dass dessen Argument ein Element animal mit genau fünf Kind-Elementen des Typs name, species, dateofbirth, veterinarian und trainer ist. Man kann Beispiel 14-6 so anpassen, dass es diese Prüfungen durchführt. Der Content- Handler aus Beispiel 14-9 kontrolliert zum Beispiel, dass das Wurzelelement eine animallist ist, dass dessen Kinder vom Typ animal sind und dass die Kinder eines Elements animal keine weiteren Elemente enthalten. Dazu verwaltet es drei Boolesche Werte, parsinganimallist_, parsinganimal_ und parsinganimalchild_, die die Region des Dokuments markieren, die gerade geparst wird. Die Methoden startelement() und endelement() aktualisieren einfach diese Flags und kontrollieren die Konsistenz, während sie das Aktualisieren des aktuellen Animal an die Hilfsmethoden startanimalchild() und endanimalchild() delegieren, deren Implementierungen denen von startelement() und endelement() aus Beispiel 14-6 sehr ähneln. Beispiel 14-9: Ein SAX2-ContentHandler für animals_ns.xml, der die Struktur des Dokuments prüft // Implementiert Callbacks, die Zeichendaten und Benachrichtigungen // über den Anfang und das Ende von Elementen erhalten class CircusContentHandler : public DefaultHandler Links 536 Kapitel 14: XML

22 echts Beispiel 14-9: Ein SAX2-ContentHandler für animals_ns.xml, der die Struktur des Dokuments prüft (Fortsetzung) public: CircusContentHandler(vector<Animal>& animallist) : animallist_(animallist), // zu füllende Liste parsinganimallist_(false), // Parsing-Status parsinganimal_(false), // Parsing-Status parsinganimalchild_(false) // Parsing-Status // Benachrichtigungen vom Parser, wenn der Anfang eines Elements // erreicht wird void startelement( const XMLCh *const uri, // Namespace-URI const XMLCh *const localname, // einfacher Tag-Name const XMLCh *const qname, // qualifizierter Tag-Name const Attributes &attrs ) // Collection mit Attributen static XercesString animallist = fromnative("animallist"); static XercesString animal = fromnative("animal"); static XercesString xmlns = fromnative(" // Namespace-URI prüfen if (uri!= xmlns) throw runtime_error( string("falscher Namespace-URI: ") + tonative(uri) ); // (i) Aktualisiert die Flags parsinganimallist_, parsinganimal_ // und parsinganimalchild_, die angeben, wo wir uns // im Dokument befinden // (ii) Prüft, dass die Elemente korrekt // verschachtelt sind // (iii) Delegiert die meiste Arbeit an // startanimalchild( ) if (!parsinganimallist_) // Wir sind an der Wurzel if (localname == animallist) parsinganimallist_ = true; // Parsing-Status anpassen. else // Falsches Einbetten throw runtime_error( string("'animallist' erwartet, ") + tonative(localname) + string(" erhalten") ); else if (!parsinganimal_) // Ein neues Tier if (localname == animal) parsinganimal_ = true; // Parsing-Status. animallist_.push_back(animal( )); // Der Liste ein Tier hinzufügen. else 14.3 Ein komplexes XML-Dokument parsen 537

23 Beispiel 14-9: Ein SAX2-ContentHandler für animals_ns.xml, der die Struktur des Dokuments prüft (Fortsetzung) // Falsches Einbetten throw runtime_error( string("'animal' erwartet, ") + tonative(localname) + string(" erhalten") ); else // Wir sind mitten im Parsen eines Animal-Elements. if (parsinganimalchild_) // Falsches Einbetten throw runtime_error("falsches Element animal"); // Parsing-Status anpassen. parsinganimalchild_ = true; Links // startanimalchild( ) die eigentliche Arbeit machen lassen startanimalchild(uri, localname, qname, attrs); void endelement( const XMLCh *const uri, // Namespace-URI const XMLCh *const localname, // einfacher Tag-Name const XMLCh *const qname ) // qualifizierter Tag-Name static XercesString animallist = fromnative("animal-list"); static XercesString animal = fromnative("animal"); // Die Flags parsinganimallist, parsinganimal_ // und parsinganimalchild_ anpassen; die meiste Arbeit an // endanimalchild( ) delegieren if (localname == animal) parsinganimal_ = false; else if (localname == animallist) parsinganimallist_ = false; else endanimalchild(uri, localname, qname); parsinganimalchild_ = false; // Benachrichtigungen über Zeichendaten erhalten void characters(const XMLCh* const chars, const unsigned int length) // Zeichen an currenttext_ anfügen, das von // endanimalchild( ) verarbeitet wird currenttext_.append(chars, length); 538 Kapitel 14: XML

24 echts Beispiel 14-9: Ein SAX2-ContentHandler für animals_ns.xml, der die Struktur des Dokuments prüft (Fortsetzung) private: // Wenn das aktuelle Element einen Tierarzt oder Trainer darstellt, // mit attrs ein Objekt Contact für das aktuelle Animal erstellen, // sonst currenttext_ für den Callback character() leeren void startanimalchild( const XMLCh *const uri, // Namespace-URI const XMLCh *const localname, // einfacher Tag-Name const XMLCh *const qname, // qualifizierter Tag-Name const Attributes &attrs ) // Collection mit Attributen static XercesString vet = fromnative("veterinarian"); static XercesString trainer = fromnative("trainer"); Animal& animal = animallist_.back( ); if (localname == vet) // Wir haben einen Tierarzt erreicht animal.setveterinarian(contactfromattributes(attrs)); else if (localname == trainer) // Wir haben einen Trainer erreicht animal.settrainer(contactfromattributes(attrs)); else // Wir haben ein Element "name", "species" oder // "dateofbirth" erreicht. Dessen Inhalt wird von // der Callback-Funktion characters() bereitgestellt. currenttext_.clear( ); // Wenn das aktuelle Element einen Namen, eine Spezies oder ein // Geburtsdatum darstellt, verwende den in currenttext_ gespeicherten // Text, um die entsprechende Eigenschaft von Animal zu setzen. void endanimalchild( const XMLCh *const uri, // Namespace-URI const XMLCh *const localname, // einfacher Tag-Name const XMLCh *const qname ) // qualifizierter Tag-Name static XercesString name = fromnative("name"); static XercesString species = fromnative("species"); static XercesString dob = fromnative("dateofbirth"); // currenttext_ enthält den Inhalt des Elements, das gerade // endet. Setzte damit die entsprechende Eigenschaft von Animal. Animal& animal = animallist_.back( ); if (localname == name) animal.setname(tonative(currenttext_)); else if (localname == species) animal.setspecies(tonative(currenttext_)); else if (localname == dob) animal.setdateofbirth(tonative(currenttext_)); 14.3 Ein komplexes XML-Dokument parsen 539

25 Beispiel 14-9: Ein SAX2-ContentHandler für animals_ns.xml, der die Struktur des Dokuments prüft (Fortsetzung) ; vector<animal>& animallist_; // zu füllende Liste bool parsinganimallist_; // Parsing-Status bool parsinganimal_; // Parsing-Status bool parsinganimalchild_; // Parsing-Status XercesString currenttext_; // Zeichendaten für den // aktuellen Textknoten Links Wenn Sie Beispiel 14-9 mit Beispiel 14-6 vergleichen, können Sie sehen, wie komplex es sein kann, eine Dokumentstruktur mit Hilfe von Callbacks zu verifizieren. Zudem führt Beispiel 14-9 immer noch nicht so viele Prüfungen durch wie Beispiel 14-3: Es prüft zum Beispiel nicht, dass die Kinder eines Elements animal in der richtigen Reihenfolge auftauchen. Glücklicherweise gibt es viel einfachere Wege, eine Dokumentstruktur mit SAX2 zu verifizieren, wie Sie in den Rezepten 14.5 und 14.6 sehen werden. Siehe auch Rezepte 14.1, 14.4, 14.5 und Ein XML-Dokument verändern Problem Sie wollen ein XML-Dokument so als C++-Objekt darstellen, dass Sie dessen Elemente, Attribute, Texte, die DTD, Verarbeitungsinstruktionen und Kommentare verändern können. Lösung Nutzen Sie die Xerces-Implementierung des W3C-DOM. Zunächst verwenden Sie die Klasse xercesc::domimplementationregistry, um eine Instanz der Klasse xercesc:: DOMImplementation zu erhalten, dann erstellen Sie mit DOMImplementation eine Instanz des Parsers xercesc::dombuilder. Danach registrieren Sie eine Instanz von xercesc:: DOMErrorHandler, um Benachrichtigungen über Fehler beim Parsen zu erhalten, und rufen die Methode parseuri() des Parsers mit der URI oder dem Dateinamen Ihres XML- Dokuments auf. Wenn das Parsen erfolgreich ist, liefert parseuri einen Zeiger auf ein DOMDocument zurück, das das XML-Dokument repräsentiert. Sie können dann die durch die W3C-DOM-Spezifikation definierten Funktionen nutzen, um das Dokument zu untersuchen und zu verändern. Wenn Sie mit den Änderungen fertig sind, können Sie das Dokument in einer Datei speichern, indem Sie von DOMImplementation einen DOMWriter anfordern und dessen Methode writenode() mit einem Zeiger auf das DOMDocument als Argument aufrufen. 540 Kapitel 14: XML

Zählen von Objekten einer bestimmten Klasse

Zählen von Objekten einer bestimmten Klasse Zählen von Objekten einer bestimmten Klasse Ziel, Inhalt Zur Übung versuchen wir eine Klasse zu schreiben, mit der es möglich ist Objekte einer bestimmten Klasse zu zählen. Wir werden den ++ und den --

Mehr

Einführung in die Java- Programmierung

Einführung in die Java- Programmierung Einführung in die Java- Programmierung Dr. Volker Riediger Tassilo Horn riediger horn@uni-koblenz.de WiSe 2012/13 1 Wichtig... Mittags keine Pommes... Praktikum A 230 C 207 (Madeleine + Esma) F 112 F 113

Mehr

5.2 Neue Projekte erstellen

5.2 Neue Projekte erstellen 5.2 Neue Projekte erstellen Das Bearbeiten von bestehenden Projekten und Objekten ist ja nicht schlecht wie aber können Sie neue Objekte hinzufügen oder gar völlig neue Projekte erstellen? Die Antwort

Mehr

Vorkurs C++ Programmierung

Vorkurs C++ Programmierung Vorkurs C++ Programmierung Klassen Letzte Stunde Speicherverwaltung automatische Speicherverwaltung auf dem Stack dynamische Speicherverwaltung auf dem Heap new/new[] und delete/delete[] Speicherklassen:

Mehr

Ziel, Inhalt. Programmieren in C++ Wir lernen wie man Funktionen oder Klassen einmal schreibt, so dass sie für verschiedene Datentypen verwendbar sind

Ziel, Inhalt. Programmieren in C++ Wir lernen wie man Funktionen oder Klassen einmal schreibt, so dass sie für verschiedene Datentypen verwendbar sind Templates und Containerklassen Ziel, Inhalt Wir lernen wie man Funktionen oder Klassen einmal schreibt, so dass sie für verschiedene Datentypen verwendbar sind Templates und Containerklassen 1 Ziel, Inhalt

Mehr

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12 Grundlagen: Folge 19 - Bäume 19.1 Binärbäume - Allgemeines Unter Bäumen versteht man in der Informatik Datenstrukturen, bei denen jedes Element mindestens zwei Nachfolger hat. Bereits in der Folge 17 haben

Mehr

Urlaubsregel in David

Urlaubsregel in David Urlaubsregel in David Inhaltsverzeichnis KlickDown Beitrag von Tobit...3 Präambel...3 Benachrichtigung externer Absender...3 Erstellen oder Anpassen des Anworttextes...3 Erstellen oder Anpassen der Auto-Reply-Regel...5

Mehr

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen Binäre Bäume 1. Allgemeines Binäre Bäume werden grundsätzlich verwendet, um Zahlen der Größe nach, oder Wörter dem Alphabet nach zu sortieren. Dem einfacheren Verständnis zu Liebe werde ich mich hier besonders

Mehr

Grundlagen von Python

Grundlagen von Python Einführung in Python Grundlagen von Python Felix Döring, Felix Wittwer November 17, 2015 Scriptcharakter Programmierparadigmen Imperatives Programmieren Das Scoping Problem Objektorientiertes Programmieren

Mehr

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Objektorientierte Programmierung für Anfänger am Beispiel PHP Objektorientierte Programmierung für Anfänger am Beispiel PHP Johannes Mittendorfer http://jmittendorfer.hostingsociety.com 19. August 2012 Abstract Dieses Dokument soll die Vorteile der objektorientierten

Mehr

Installation und Inbetriebnahme von Microsoft Visual C++ 2010 Express

Installation und Inbetriebnahme von Microsoft Visual C++ 2010 Express Howto Installation und Inbetriebnahme von Microsoft Visual C++ 2010 Express Peter Bitterlich Markus Langer 12. Oktober 2012 Zusammenfassung Dieses Dokument erklärt Schritt für Schritt die Installation

Mehr

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster Es gibt in Excel unter anderem die so genannten Suchfunktionen / Matrixfunktionen Damit können Sie Werte innerhalb eines bestimmten Bereichs suchen. Als Beispiel möchte ich die Funktion Sverweis zeigen.

Mehr

SEP 114. Design by Contract

SEP 114. Design by Contract Design by Contract SEP 114 Design by Contract Teile das zu entwickelnde Programm in kleine Einheiten (Klassen, Methoden), die unabhängig voneinander entwickelt und überprüft werden können. Einheiten mit

Mehr

Einführung in die Programmierung

Einführung in die Programmierung Technische Universität München WS 2003/2004 Institut für Informatik Prof. Dr. Christoph Zenger Testklausur Einführung in die Programmierung Probeklausur Java (Lösungsvorschlag) 1 Die Klasse ArrayList In

Mehr

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden.

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden. In einer Website haben Seiten oft das gleiche Layout. Speziell beim Einsatz von Tabellen, in denen die Navigation auf der linken oder rechten Seite, oben oder unten eingesetzt wird. Diese Anteile der Website

Mehr

1 topologisches Sortieren

1 topologisches Sortieren Wolfgang Hönig / Andreas Ecke WS 09/0 topologisches Sortieren. Überblick. Solange noch Knoten vorhanden: a) Suche Knoten v, zu dem keine Kante führt (Falls nicht vorhanden keine topologische Sortierung

Mehr

Wie halte ich Ordnung auf meiner Festplatte?

Wie halte ich Ordnung auf meiner Festplatte? Wie halte ich Ordnung auf meiner Festplatte? Was hältst du von folgender Ordnung? Du hast zu Hause einen Schrank. Alles was dir im Wege ist, Zeitungen, Briefe, schmutzige Wäsche, Essensreste, Küchenabfälle,

Mehr

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0) Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0) Peter Koos 03. Dezember 2015 0 Inhaltsverzeichnis 1 Voraussetzung... 3 2 Hintergrundinformationen... 3 2.1 Installationsarten...

Mehr

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken. Seite erstellen Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken. Es öffnet sich die Eingabe Seite um eine neue Seite zu erstellen. Seiten Titel festlegen Den neuen

Mehr

Ruhr.pm XML-Daten verarbeiten mit XML::LibXML Autor: EMail: Datum: http://ruhr.pm.org/

Ruhr.pm XML-Daten verarbeiten mit XML::LibXML Autor: EMail: Datum: http://ruhr.pm.org/ XML-Daten verarbeiten mit XML::LibXML Autor: EMail: Datum: Simon Wilper simon AT ruhr.pm.org http://ruhr.pm.org/ Template Version 0.1 The use of a camel image in association with Perl is a trademark of

Mehr

Adminer: Installationsanleitung

Adminer: Installationsanleitung Adminer: Installationsanleitung phpmyadmin ist bei uns mit dem Kundenmenüpasswort geschützt. Wer einer dritten Person Zugriff auf die Datenbankverwaltung, aber nicht auf das Kundenmenü geben möchte, kann

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Objektorientierte Programmierung 1 Geschichte Dahl, Nygaard: Simula 67 (Algol 60 + Objektorientierung) Kay et al.: Smalltalk (erste rein-objektorientierte Sprache) Object Pascal, Objective C, C++ (wiederum

Mehr

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 Referentin: Dr. Kelly Neudorfer Universität Hohenheim Was wir jetzt besprechen werden ist eine Frage, mit denen viele

Mehr

Datensicherung. Beschreibung der Datensicherung

Datensicherung. Beschreibung der Datensicherung Datensicherung Mit dem Datensicherungsprogramm können Sie Ihre persönlichen Daten problemlos Sichern. Es ist möglich eine komplette Datensicherung durchzuführen, aber auch nur die neuen und geänderten

Mehr

Programmieren in Java

Programmieren in Java Programmieren in Java objektorientierte Programmierung 2 2 Zusammenhang Klasse-Datei In jeder *.java Datei kann es genau eine public-klasse geben wobei Klassen- und Dateiname übereinstimmen. Es können

Mehr

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Ab der Version forma 5.5 handelt es sich bei den Orientierungshilfen der Architekten-/Objektplanerverträge nicht

Mehr

Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only

Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only Methoden Wie Konstruktoren und Destruktoren zum Auf- und Abbau von Objekten definiert werden, Wie inline-methoden Methoden,, Zugriffsmethoden und Read-Only Only- Methoden einzusetzen sind, Der this-pointer

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Dr. Dietrich Boles Aufgaben zu UE16-Rekursion (Stand 09.12.2011) Aufgabe 1: Implementieren Sie in Java ein Programm, das solange einzelne Zeichen vom Terminal einliest, bis ein #-Zeichen

Mehr

Objektorientierte Programmierung. Kapitel 12: Interfaces

Objektorientierte Programmierung. Kapitel 12: Interfaces 12. Interfaces 1/14 Objektorientierte Programmierung Kapitel 12: Interfaces Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2012/13 http://www.informatik.uni-halle.de/ brass/oop12/

Mehr

Primzahlen und RSA-Verschlüsselung

Primzahlen und RSA-Verschlüsselung Primzahlen und RSA-Verschlüsselung Michael Fütterer und Jonathan Zachhuber 1 Einiges zu Primzahlen Ein paar Definitionen: Wir bezeichnen mit Z die Menge der positiven und negativen ganzen Zahlen, also

Mehr

Software Engineering Klassendiagramme Assoziationen

Software Engineering Klassendiagramme Assoziationen Software Engineering Klassendiagramme Assoziationen Prof. Adrian A. Müller, PMP, PSM 1, CSM Fachbereich Informatik und Mikrosystemtechnik 1 Lesen von Multiplizitäten (1) Multiplizitäten werden folgendermaßen

Mehr

Anleitung über den Umgang mit Schildern

Anleitung über den Umgang mit Schildern Anleitung über den Umgang mit Schildern -Vorwort -Wo bekommt man Schilder? -Wo und wie speichert man die Schilder? -Wie füge ich die Schilder in meinen Track ein? -Welche Bauteile kann man noch für Schilder

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Universität der Bundeswehr Fakultät für Informatik Institut 2 Priv.-Doz. Dr. Lothar Schmitz FT 2006 Zusatzaufgaben Lösungsvorschlag Objektorientierte Programmierung Lösung 22 (Java und UML-Klassendiagramm)

Mehr

Was meinen die Leute eigentlich mit: Grexit?

Was meinen die Leute eigentlich mit: Grexit? Was meinen die Leute eigentlich mit: Grexit? Grexit sind eigentlich 2 Wörter. 1. Griechenland 2. Exit Exit ist ein englisches Wort. Es bedeutet: Ausgang. Aber was haben diese 2 Sachen mit-einander zu tun?

Mehr

OP-LOG www.op-log.de

OP-LOG www.op-log.de Verwendung von Microsoft SQL Server, Seite 1/18 OP-LOG www.op-log.de Anleitung: Verwendung von Microsoft SQL Server 2005 Stand Mai 2010 1 Ich-lese-keine-Anleitungen 'Verwendung von Microsoft SQL Server

Mehr

Log xmllog textlog Log() start(filename) add(message) end() instance() Abbildung 7-10: Die Protokollierungs-API mit einer einfachen Fassade

Log xmllog textlog Log() start(filename) add(message) end() instance() Abbildung 7-10: Die Protokollierungs-API mit einer einfachen Fassade HACK #76 Hack APIs mit dem Façade-Muster vereinfachen Durch die Verwendung des Façade-Entwurfsmusters können Sie die anderen Programmierern zugängliche API vereinfachen. #76 Dies ist ein Muster, von dem

Mehr

Sich einen eigenen Blog anzulegen, ist gar nicht so schwer. Es gibt verschiedene Anbieter. www.blogger.com ist einer davon.

Sich einen eigenen Blog anzulegen, ist gar nicht so schwer. Es gibt verschiedene Anbieter. www.blogger.com ist einer davon. www.blogger.com Sich einen eigenen Blog anzulegen, ist gar nicht so schwer. Es gibt verschiedene Anbieter. www.blogger.com ist einer davon. Sie müssen sich dort nur ein Konto anlegen. Dafür gehen Sie auf

Mehr

Empfehlungen zur Nutzung der CD zum Buch: Klee & Wiemann: Beweglichkeit und Dehnfähigkeit. Schorndorf: Hofmann, 2005. 1

Empfehlungen zur Nutzung der CD zum Buch: Klee & Wiemann: Beweglichkeit und Dehnfähigkeit. Schorndorf: Hofmann, 2005. 1 Empfehlungen zur Nutzung der CD zum Buch: Klee & Wiemann: Beweglichkeit und Dehnfähigkeit. Schorndorf: Hofmann, 2005. 1 Starten der CD Nach dem Einlegen der CD in Ihr CD-Laufwerk müsste die CD von selbst

Mehr

Objektorientierte Programmierung mit C++ Vector und List

Objektorientierte Programmierung mit C++ Vector und List Vector und List Ziel, Inhalt Wir lernen die Klassen vector und list aus der Standard-C++ Library kennen und anwenden. In einer Übung wenden wir diese Klassen an um einen Medienshop (CD s und Bücher) zu

Mehr

Durchführung der Datenübernahme nach Reisekosten 2011

Durchführung der Datenübernahme nach Reisekosten 2011 Durchführung der Datenübernahme nach Reisekosten 2011 1. Starten Sie QuickSteuer Deluxe 2010. Rufen Sie anschließend über den Menüpunkt /Extras/Reisekosten Rechner den QuickSteuer Deluxe 2010 Reisekosten-Rechner,

Mehr

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b AGROPLUS Buchhaltung Daten-Server und Sicherheitskopie Version vom 21.10.2013b 3a) Der Daten-Server Modus und der Tresor Der Daten-Server ist eine Betriebsart welche dem Nutzer eine grosse Flexibilität

Mehr

Java Einführung Collections

Java Einführung Collections Java Einführung Collections Inhalt dieser Einheit Behälterklassen, die in der Java API bereitgestellt werden Wiederholung Array Collections (Vector, List, Set) Map 2 Wiederholung Array a[0] a[1] a[2] a[3]...

Mehr

KURZANLEITUNG CLOUD OBJECT STORAGE

KURZANLEITUNG CLOUD OBJECT STORAGE KURZANLEITUNG CLOUD OBJECT STORAGE Version 1.12 01.07.2014 SEITE _ 2 INHALTSVERZEICHNIS 1. Einleitung... Seite 03 2. Anmelden am Cloud&Heat Dashboard... Seite 04 3. Anlegen eines Containers... Seite 05

Mehr

Ordner Berechtigung vergeben Zugriffsrechte unter Windows einrichten

Ordner Berechtigung vergeben Zugriffsrechte unter Windows einrichten Ordner Berechtigung vergeben Zugriffsrechte unter Windows einrichten Was sind Berechtigungen? Unter Berechtigungen werden ganz allgemein die Zugriffsrechte auf Dateien und Verzeichnisse (Ordner) verstanden.

Mehr

Zwischenablage (Bilder, Texte,...)

Zwischenablage (Bilder, Texte,...) Zwischenablage was ist das? Informationen über. die Bedeutung der Windows-Zwischenablage Kopieren und Einfügen mit der Zwischenablage Vermeiden von Fehlern beim Arbeiten mit der Zwischenablage Bei diesen

Mehr

Technische Dokumentation SilentStatistikTool

Technische Dokumentation SilentStatistikTool Technische Dokumentation SilentStatistikTool Version 1.0 Marko Schröder 1115063 Inhalt Einleitung... 3 Klasse Program... 3 Klasse ArgumentHandler... 3 Bereitgestellte Variablen... 3 Bereitgestellte Methoden...

Mehr

Die Dateiablage Der Weg zur Dateiablage

Die Dateiablage Der Weg zur Dateiablage Die Dateiablage In Ihrem Privatbereich haben Sie die Möglichkeit, Dateien verschiedener Formate abzulegen, zu sortieren, zu archivieren und in andere Dateiablagen der Plattform zu kopieren. In den Gruppen

Mehr

Java: Vererbung. Teil 3: super() www.informatikzentrale.de

Java: Vererbung. Teil 3: super() www.informatikzentrale.de Java: Vererbung Teil 3: super() Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und IMMER zuerst den Konstruktor der Elternklasse auf! Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und

Mehr

Lieber SPAMRobin -Kunde!

Lieber SPAMRobin -Kunde! Lieber SPAMRobin -Kunde! Wir freuen uns, dass Sie sich für SPAMRobin entschieden haben. Mit diesem Leitfaden möchten wir Ihnen die Kontoeinrichtung erleichtern und die Funktionen näher bringen. Bitte führen

Mehr

Leichte-Sprache-Bilder

Leichte-Sprache-Bilder Leichte-Sprache-Bilder Reinhild Kassing Information - So geht es 1. Bilder gucken 2. anmelden für Probe-Bilder 3. Bilder bestellen 4. Rechnung bezahlen 5. Bilder runterladen 6. neue Bilder vorschlagen

Mehr

Beschreibung E-Mail Regeln z.b. Abwesenheitsmeldung und Weiterleitung

Beschreibung E-Mail Regeln z.b. Abwesenheitsmeldung und Weiterleitung Outlook Weiterleitungen & Abwesenheitsmeldungen Seite 1 von 6 Beschreibung E-Mail Regeln z.b. Abwesenheitsmeldung und Weiterleitung Erstellt: Quelle: 3.12.09/MM \\rsiag-s3aad\install\vnc\email Weiterleitung

Mehr

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress. Anmeldung http://www.ihredomain.de/wp-admin Dashboard Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress. Das Dashboard gibt Ihnen eine kurze Übersicht, z.b. Anzahl der Beiträge,

Mehr

Arbeiten mit UMLed und Delphi

Arbeiten mit UMLed und Delphi Arbeiten mit UMLed und Delphi Diese Anleitung soll zeigen, wie man Klassen mit dem UML ( Unified Modeling Language ) Editor UMLed erstellt, in Delphi exportiert und dort so einbindet, dass diese (bis auf

Mehr

Microsoft PowerPoint 2013 Folien gemeinsam nutzen

Microsoft PowerPoint 2013 Folien gemeinsam nutzen Hochschulrechenzentrum Justus-Liebig-Universität Gießen Microsoft PowerPoint 2013 Folien gemeinsam nutzen Folien gemeinsam nutzen in PowerPoint 2013 Seite 1 von 4 Inhaltsverzeichnis Einleitung... 2 Einzelne

Mehr

Das Leitbild vom Verein WIR

Das Leitbild vom Verein WIR Das Leitbild vom Verein WIR Dieses Zeichen ist ein Gütesiegel. Texte mit diesem Gütesiegel sind leicht verständlich. Leicht Lesen gibt es in drei Stufen. B1: leicht verständlich A2: noch leichter verständlich

Mehr

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI Universität Osnabrück Drei-Schichten-Architektur 3 - Objektorientierte Programmierung in Java Vorlesung 6: 3-Schichten-Architektur Fachkonzept - GUI SS 2005 Prof. Dr. F.M. Thiesing, FH Dortmund Ein großer

Mehr

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage .htaccess HOWTO zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage Stand: 21.06.2015 Inhaltsverzeichnis 1. Vorwort...3 2. Verwendung...4 2.1 Allgemeines...4 2.1 Das Aussehen der.htaccess

Mehr

Einführung in die Programmierung

Einführung in die Programmierung : Inhalt Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund - mit / ohne Parameter - mit / ohne Rückgabewerte

Mehr

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung Anleitung zur Daten zur Datensicherung und Datenrücksicherung Datensicherung Es gibt drei Möglichkeiten der Datensicherung. Zwei davon sind in Ges eingebaut, die dritte ist eine manuelle Möglichkeit. In

Mehr

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben Sichtbarkeit & statische Methoden Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben Nicht sichtbare Methoden Wollen Eltern bestimmte Methoden vor den

Mehr

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter 2 Inhaltsverzeichnis 1 Web-Kürzel 4 1.1 Einführung.......................................... 4 1.2 Web-Kürzel.........................................

Mehr

Zimmertypen. Zimmertypen anlegen

Zimmertypen. Zimmertypen anlegen Zimmertypen anlegen Hier legen Sie Ihre Zimmer an, damit sie auf der Homepage dargestellt werden und online buchbar gemacht werden können. Wobei wir ausdrücklich darauf hinweisen möchten, dass es ganz

Mehr

Enigmail Konfiguration

Enigmail Konfiguration Enigmail Konfiguration 11.06.2006 Steffen.Teubner@Arcor.de Enigmail ist in der Grundkonfiguration so eingestellt, dass alles funktioniert ohne weitere Einstellungen vornehmen zu müssen. Für alle, die es

Mehr

Erstellen einer PostScript-Datei unter Windows XP

Erstellen einer PostScript-Datei unter Windows XP Erstellen einer PostScript-Datei unter Windows XP Sie möchten uns Ihre Druckvorlage als PostScript-Datei einreichen. Um Fehler in der Herstellung von vorneherein auszuschließen, möchten wir Sie bitten,

Mehr

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag Ludwig-Maximilians-Universität München WS 2015/16 Institut für Informatik Übungsblatt 9 Prof. Dr. R. Hennicker, A. Klarl Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung:

Mehr

Bauteilattribute als Sachdaten anzeigen

Bauteilattribute als Sachdaten anzeigen Mit den speedikon Attributfiltern können Sie die speedikon Attribute eines Bauteils als MicroStation Sachdaten an die Elemente anhängen Inhalte Was ist ein speedikon Attribut?... 3 Eigene Attribute vergeben...

Mehr

12. Dokumente Speichern und Drucken

12. Dokumente Speichern und Drucken 12. Dokumente Speichern und Drucken 12.1 Überblick Wie oft sollte man sein Dokument speichern? Nachdem Sie ein Word Dokument erstellt oder bearbeitet haben, sollten Sie es immer speichern. Sie sollten

Mehr

Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert

Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert Beamen in EEP Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert Zuerst musst du dir 2 Programme besorgen und zwar: Albert, das

Mehr

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 18

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 18 Kapitel 3 Datentypen und Variablen Seite 1 von 18 Datentypen - Einführung - Für jede Variable muss ein Datentyp festgelegt werden. - Hierdurch werden die Wertemenge und die verwendbaren Operatoren festgelegt.

Mehr

AutoCAD 2007 - Dienstprogramm zur Lizenzübertragung

AutoCAD 2007 - Dienstprogramm zur Lizenzübertragung AutoCAD 2007 - Dienstprogramm zur Lizenzübertragung Problem: Um AutoCAD abwechselnd auf mehreren Rechnern einsetzen zu können konnte man bis AutoCAD 2000 einfach den Dongle umstecken. Seit AutoCAD 2000i

Mehr

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = 0.51129 Euro ergeben.

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = 0.51129 Euro ergeben. Aufgabe 1.30 : Schreibe ein Programm DM_in_Euro.java zur Umrechnung eines DM-Betrags in Euro unter Verwendung einer Konstanten für den Umrechnungsfaktor. Das Programm soll den DM-Betrag als Parameter verarbeiten.

Mehr

WOT Skinsetter. Nun, erstens, was brauchen Sie für dieses Tool zu arbeiten:

WOT Skinsetter. Nun, erstens, was brauchen Sie für dieses Tool zu arbeiten: WOT Skinsetter WOT Skinsetter steht für World of Tanks skinsetter (WOTS von nun an). Mit diesen Tool können Sie Skins importieren und ändern, wann immer Sie möchten auf einfache Weise. Als World of Tanks

Mehr

Einführung in die Programmierung (EPR)

Einführung in die Programmierung (EPR) Goethe-Center for Scientific Computing (G-CSC) Goethe-Universität Frankfurt am Main Einführung in die Programmierung (EPR) (Übung, Wintersemester 2014/2015) Dr. S. Reiter, M. Rupp, Dr. A. Vogel, Dr. K.

Mehr

Musterlösung für Schulen in Baden-Württemberg. Windows 2003. Basiskurs Windows-Musterlösung. Version 3. Stand: 19.12.06

Musterlösung für Schulen in Baden-Württemberg. Windows 2003. Basiskurs Windows-Musterlösung. Version 3. Stand: 19.12.06 Musterlösung für Schulen in Baden-Württemberg Windows 2003 Basiskurs Windows-Musterlösung Version 3 Stand: 19.12.06 Impressum Herausgeber Zentrale Planungsgruppe Netze (ZPN) am Kultusministerium Baden-Württemberg

Mehr

SharePoint Workspace 2010 Installieren & Konfigurieren

SharePoint Workspace 2010 Installieren & Konfigurieren [Geben Sie Text ein] SharePoint Workspace 2010 Installieren & Konfigurieren SharePoint Workspace 2010 Installieren & Konfigurieren Inhalt SharePoint Workspace 2010 Installieren... 2 SharePoint Workspace

Mehr

Java Kurs für Anfänger Einheit 5 Methoden

Java Kurs für Anfänger Einheit 5 Methoden Java Kurs für Anfänger Einheit 5 Methoden Ludwig-Maximilians-Universität München (Institut für Informatik: Programmierung und Softwaretechnik von Prof.Wirsing) 22. Juni 2009 Inhaltsverzeichnis Methoden

Mehr

Um dies zu tun, öffnen Sie in den Systemeinstellungen das Kontrollfeld "Sharing". Auf dem Bildschirm sollte folgendes Fenster erscheinen:

Um dies zu tun, öffnen Sie in den Systemeinstellungen das Kontrollfeld Sharing. Auf dem Bildschirm sollte folgendes Fenster erscheinen: Einleitung Unter MacOS X hat Apple die Freigabe standardmäßig auf den "Public" Ordner eines Benutzers beschränkt. Mit SharePoints wird diese Beschränkung beseitigt. SharePoints erlaubt auch die Kontrolle

Mehr

S TAND N OVEMBE R 2012 HANDBUCH DUDLE.ELK-WUE.DE T E R M I N A B S P R A C H E N I N D E R L A N D E S K I R C H E

S TAND N OVEMBE R 2012 HANDBUCH DUDLE.ELK-WUE.DE T E R M I N A B S P R A C H E N I N D E R L A N D E S K I R C H E S TAND N OVEMBE R 2012 HANDBUCH T E R M I N A B S P R A C H E N I N D E R L A N D E S K I R C H E Herausgeber Referat Informationstechnologie in der Landeskirche und im Oberkirchenrat Evangelischer Oberkirchenrat

Mehr

1. Software installieren 2. Software starten. Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software

1. Software installieren 2. Software starten. Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software 1. Software installieren 2. Software starten Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software 3. Auswahl 1. Neues Fotobuch erstellen oder 2. ein erstelltes, gespeichertes Fotobuch laden und bearbeiten.

Mehr

Suchbäume. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Suchbäume. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung Suchbäume Annabelle Klarl Zentralübung zur Vorlesung Einführung in die Informatik: http://www.pst.ifi.lmu.de/lehre/wise-13-14/infoeinf WS13/14 Action required now 1. Smartphone: installiere die App "socrative

Mehr

4. Jeder Knoten hat höchstens zwei Kinder, ein linkes und ein rechtes.

4. Jeder Knoten hat höchstens zwei Kinder, ein linkes und ein rechtes. Binäre Bäume Definition: Ein binärer Baum T besteht aus einer Menge von Knoten, die durch eine Vater-Kind-Beziehung wie folgt strukturiert ist: 1. Es gibt genau einen hervorgehobenen Knoten r T, die Wurzel

Mehr

Erstellen einer digitalen Signatur für Adobe-Formulare

Erstellen einer digitalen Signatur für Adobe-Formulare Erstellen einer digitalen Signatur für Adobe-Formulare (Hubert Straub 24.07.13) Die beiden Probleme beim Versenden digitaler Dokumente sind einmal die Prüfung der Authentizität des Absenders (was meist

Mehr

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6 Gudrun Fischer Sascha Kriewel programmierung@is.informatik.uni-duisburg.de Anmeldung zur Klausur! Übungsblatt Nr. 6 Um an der Klausur teilzunehmen, müssen sich Studierende der angewandten Informatik in

Mehr

Outlook Vorlagen/Templates

Outlook Vorlagen/Templates Joachim Meyn Outlook Vorlagen/Templates Erstellen Sie Vorlagen bzw. Templates in Outlook Joachim Meyn 27.03.2013 Inhaltsverzeichnis Outlook Vorlagen (.oft Dateien)... 2 Vorbereitung... 2 Anlegen einer

Mehr

Kleines Handbuch zur Fotogalerie der Pixel AG

Kleines Handbuch zur Fotogalerie der Pixel AG 1 1. Anmelden an der Galerie Um mit der Galerie arbeiten zu können muss man sich zuerst anmelden. Aufrufen der Galerie entweder über die Homepage (www.pixel-ag-bottwartal.de) oder über den direkten Link

Mehr

Flash Videos einbinden

Flash Videos einbinden Flash Videos einbinden Im Kapitel Videos einbinden ( - ) haben Sie gesehen, wie man einfach und ohne Zusatzprogramme kleine Videoclips auf seiner einbinden kann. Ich persönlich würde jedem dieses Verfahren

Mehr

Adobe Photoshop. Lightroom 5 für Einsteiger Bilder verwalten und entwickeln. Sam Jost

Adobe Photoshop. Lightroom 5 für Einsteiger Bilder verwalten und entwickeln. Sam Jost Adobe Photoshop Lightroom 5 für Einsteiger Bilder verwalten und entwickeln Sam Jost Kapitel 2 Der erste Start 2.1 Mitmachen beim Lesen....................... 22 2.2 Für Apple-Anwender.........................

Mehr

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss Systeme 1 Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss Threads Die Adressräume verschiedener Prozesse sind getrennt und geschützt gegen den Zugriff anderer Prozesse. Threads sind leichtgewichtige

Mehr

Frankieren in Microsoft Word mit dem E Porto Add in der Deutschen Post

Frankieren in Microsoft Word mit dem E Porto Add in der Deutschen Post Frankieren in Microsoft Word mit dem E Porto Add in der Deutschen Post 1. E Porto Word Add in für Microsoft Office 2003, 2007 oder 2010 kostenfrei herunterladen unter www.internetmarke.de/add in/download

Mehr

DOKUMENTATION VOGELZUCHT 2015 PLUS

DOKUMENTATION VOGELZUCHT 2015 PLUS DOKUMENTATION VOGELZUCHT 2015 PLUS Vogelzucht2015 App für Geräte mit Android Betriebssystemen Läuft nur in Zusammenhang mit einer Vollversion vogelzucht2015 auf einem PC. Zusammenfassung: a. Mit der APP

Mehr

Excel Pivot-Tabellen 2010 effektiv

Excel Pivot-Tabellen 2010 effektiv 7.2 Berechnete Felder Falls in der Datenquelle die Zahlen nicht in der Form vorliegen wie Sie diese benötigen, können Sie die gewünschten Ergebnisse mit Formeln berechnen. Dazu erzeugen Sie ein berechnetes

Mehr

News & RSS. Einleitung: Nachrichten er-(veröffentlichen) und bereitstellen Nachrichten erstellen und bereitstellen

News & RSS. Einleitung: Nachrichten er-(veröffentlichen) und bereitstellen Nachrichten erstellen und bereitstellen News & RSS Nachrichten er-(veröffentlichen) und bereitstellen Nachrichten erstellen und bereitstellen Einleitung: Sie wollen Ihre Nutzer immer mit den neuesten Informationen versorgen bzw. auf dem laufendem

Mehr

Facebook I-Frame Tabs mit Papoo Plugin erstellen und verwalten

Facebook I-Frame Tabs mit Papoo Plugin erstellen und verwalten Facebook I-Frame Tabs mit Papoo Plugin erstellen und verwalten Seit Anfang Juni 2012 hat Facebook die Static FBML Reiter deaktiviert, so wird es relativ schwierig für Firmenseiten eigene Impressumsreiter

Mehr

Anleitung zum erfassen von Last Minute Angeboten und Stellenangebote

Anleitung zum erfassen von Last Minute Angeboten und Stellenangebote Anleitung zum erfassen von Last Minute Angeboten und Stellenangebote Zweck dieser Anleitung ist es einen kleinen Überblick über die Funktion Last Minute auf Swisshotelportal zu erhalten. Für das erstellen

Mehr

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 22

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 22 Kapitel 19 Vererbung, UML Seite 1 von 22 Vererbung - Neben der Datenabstraktion und der Datenkapselung ist die Vererbung ein weiteres Merkmal der OOP. - Durch Vererbung werden die Methoden und die Eigenschaften

Mehr

Benutzerhandbuch. Leitfaden zur Benutzung der Anwendung für sicheren Dateitransfer.

Benutzerhandbuch. Leitfaden zur Benutzung der Anwendung für sicheren Dateitransfer. Benutzerhandbuch Leitfaden zur Benutzung der Anwendung für sicheren Dateitransfer. 1 Startseite Wenn Sie die Anwendung starten, können Sie zwischen zwei Möglichkeiten wählen 1) Sie können eine Datei für

Mehr

Ihre Interessentendatensätze bei inobroker. 1. Interessentendatensätze

Ihre Interessentendatensätze bei inobroker. 1. Interessentendatensätze Ihre Interessentendatensätze bei inobroker Wenn Sie oder Ihre Kunden die Prozesse von inobroker nutzen, werden Interessentendatensätze erzeugt. Diese können Sie direkt über inobroker bearbeiten oder mit

Mehr

Anleitung zum erstellen einer PDF-Datei aus Microsoft Word

Anleitung zum erstellen einer PDF-Datei aus Microsoft Word Anleitung zum erstellen einer PDF-Datei aus Microsoft Word 1. Vorbereitung des PCs Um dem Tutorial folgen zu können müssen folgende Programme auf Ihrem PC installiert sein: Ghostskript 8.64: Ghostskript

Mehr

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER Inhalt 1 Einleitung... 1 2 Einrichtung der Aufgabe für die automatische Sicherung... 2 2.1 Die Aufgabenplanung... 2 2.2 Der erste Testlauf... 9 3 Problembehebung...

Mehr

Dokumentation für das Spiel Pong

Dokumentation für das Spiel Pong Dokumentation für das Spiel Pong BwInf - Turnierserver Didaktik der nformatik BWINF KI Wettbewerbs-Plattform Stand: 02.09.2014 Grundlagen In diesem KI-Turnier programmiert ihr einen Schläger für das Retro-Spiel

Mehr