Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 16 XML
Pfeil 16.1 XML-Dokumente
Pfeil 16.1.1 Wohlgeformte und gültige XML-Dokumente
Pfeil 16.1.2 Regeln für wohlgeformten XML-Code
Pfeil 16.1.3 Kommentare
Pfeil 16.1.4 Verarbeitungsanweisungen
Pfeil 16.1.5 Reservierte Zeichen in XML
Pfeil 16.1.6 CDATA-Abschnitte
Pfeil 16.1.7 Namensräume (Namespaces)
Pfeil 16.2 Gültigkeit eines XML-Dokuments
Pfeil 16.2.1 XML Schema (XSD)
Pfeil 16.2.2 XML-Dokument mit einem XML Schema verknüpfen
Pfeil 16.2.3 Struktur eines XML Schemas
Pfeil 16.3 Die Klasse »XmlReader«
Pfeil 16.3.1 XML-Dokumente mit einem »XmlReader«-Objekt lesen
Pfeil 16.3.2 Validieren eines XML-Dokuments
Pfeil 16.4 Eigenschaften und Methoden der Klasse »XmlReader«
Pfeil 16.4.1 Navigation mit dem »XmlReader«
Pfeil 16.4.2 Eigenschaften und Methoden im Zusammenhang mit Attributen
Pfeil 16.4.3 Eigenschaften und Methoden im Zusammenhang mit Namespaces
Pfeil 16.4.4 Daten lesen
Pfeil 16.5 Die Klasse »XmlWriter«
Pfeil 16.5.1 Die Methoden der Klasse »XmlWriter«
Pfeil 16.6 Navigation durch XML (XPath)
Pfeil 16.6.1 Die Klasse »XPathNavigator«
Pfeil 16.6.2 XPath-Ausdrücke
Pfeil 16.6.3 Kontextknoten
Pfeil 16.6.4 Beispiele mit XPath-Ausdrücken
Pfeil 16.6.5 Knotenmengen mit der »Select«-Methode
Pfeil 16.6.6 Auswerten von XPath-Ausdrücken
Pfeil 16.7 Document Object Model (DOM)
Pfeil 16.7.1 Allgemeines
Pfeil 16.7.2 Arbeiten mit XmlDocument
Pfeil 16.7.3 XmlDocument und XPathNavigator
Pfeil 16.7.4 Die Klasse »XmlNode« (Operationen mit Knoten)
Pfeil 16.7.5 XML-Struktur manipulieren
Pfeil 16.7.6 Knoten ändern
Pfeil 16.7.7 Löschen in einem XML-Dokument
Pfeil 16.8 Serialisierung mit »XmlSerializer«
Pfeil 16.8.1 XML-Serialisierung mit Attributen steuern
Pfeil 16.9 LINQ to XML
Pfeil 16.9.1 Klassenhierarchie von LINQ to XML
Pfeil 16.9.2 Die Klasse »XElement«
Pfeil 16.9.3 Die Klasse »XDocument«
Pfeil 16.9.4 Navigation im XML-Dokument
Pfeil 16.9.5 Änderungen am XML-Dokument vornehmen


Galileo Computing - Zum Seitenanfang

16.9 LINQ to XML Zur nächsten ÜberschriftZur vorigen Überschrift

LINQ to XML vereinigt die Fähigkeiten von DOM sowie die von XPath beschriebenen Möglichkeiten, die im Speicher befindlichen XML-Daten zu verwalten, abzufragen und darüber hinaus auch zu ändern. Mit LINQ to XML soll dem Entwickler, der sich vorher mit mehreren unterschiedlichen APIs auseinandersetzen musste, die Arbeit mit XML einfacher gemacht werden. Im Folgenden werden wir uns mit der in .NET 3.5 eingeführten Technik beschäftigen. Da LINQ to XML eine eigenständige API (Klassenbibliothek) ist, gestattet LINQ to SQL das Arbeiten XML-Dokumenten, ohne dass dabei LINQ-Abfragen zwangsläufig eingesetzt werden müssen.

Damit Sie die Bibliothek einsetzen können, müssen Sie auf die Assembly System.Xml.Linq verweisen und sollten auch den gleichnamigen Namespace bekannt geben.


Galileo Computing - Zum Seitenanfang

16.9.1 Klassenhierarchie von LINQ to XML Zur nächsten ÜberschriftZur vorigen Überschrift

Ehe wir uns die Fähigkeiten von LINQ to XML ansehen, sollten wir einen Blick auf die Klassenbibliothek werfen. Allzu viele Klassen hat LINQ to XML nicht zu bieten, was die Einarbeitung sicherlich deutlich vereinfacht. In Abbildung 16.12 ist die Klassenhierarchie dargestellt.

Da in diesem Buch nur ein kurzer Abriss von LINQ to XML erfolgt, soll es genügen, wenn an dieser Stelle nur die wichtigsten Klassen beschrieben werden.


Tabelle 16.20 Wichtige Klassen von LINQ to XML

Klasse Beschreibung

XElement

Bei dieser Klasse handelt es sich wohl um die wichtigste Klasse von LINQ to XML. Sie beschreibt einen XML-Element-Knoten, der untergeordnete Elemente enthalten kann. Die Klasse stellt eine Vielzahl von Methoden zur Verfügung, um innerhalb der XML-Struktur zu navigieren oder auch um XML-Elemente zu bearbeiten.

XDocument

XDocument ist der Klasse XElement sehr ähnlich. Das wichtigste Unterscheidungsmerkmal im Vergleich zur Klasse XElement ist, dass ein XDocument-Objekt auch die XML-Deklaration und mehrere XML-Prozessinstruktionen bearbeiten kann.

XAttribute

Diese Klasse repräsentiert XML-Attribute und stellt passende Methoden zum Verwalten und Erzeugen zur Verfügung. Die Arbeit mit Attributen ähnelt dem Arbeiten mit den Elementen. Intern werden Attribute als Name/Wert-Paar behandelt, das einem Element zugeordnet ist.

XDeclaration

Die XDeclaration wird für die Angabe der XML-Version und der Codierung benötigt.

XComment

Ein Objekt dieser Klasse stellt einen XML-Kommentar dar.

XNode

Die Klasse XNode ist abstrakt definiert und stellt ihren Ableitungen Methoden zur Bearbeitung der Elemente einer XML-Struktur zur Verfügung.

XProcessingInstruction

Diese Klasse repräsentiert eine Processing Instruction (PI).


Abbildung 16.12 Klassenhierarchie von LINQ to XML


Galileo Computing - Zum Seitenanfang

16.9.2 Die Klasse »XElement« Zur nächsten ÜberschriftZur vorigen Überschrift

XML-Daten in den Speicher laden

Um die Daten einer XML-Datei in den Speicher zu laden, wird die Methode Load der Klasse XElement aufgerufen, zum Beispiel:


XElement xml = XElement.Load(@"D:\Personen.xml");

Der Methode Load können Sie einen Stream, ein TextReader-Objekt, ein XmlReader-Objekt oder eine Zeichenfolge übergeben. Bei der Zeichenfolge darf es sich auch um einen URI oder eine relative Angabe handeln, die dann relativ zum Anwendungsordner gilt. Darüber hinaus finden sich weitere Überladungen, die einen zweiten Parameter vom Typ LoadOptions beschreiben. Mit der Option LoadOptions.PreserveWhitespace ließe sich beispielsweise angeben, dass die Leerzeichen beibehalten werden sollen.


Anmerkung

Es gibt auch einige wenige Fälle, in denen das XML nicht in einer Datei vorliegt oder aus einem URI bezogen wird. Stattdessen wird das XML durch eine einfache Zeichenfolge beschrieben. Für diesen Fall stellt die Klasse XElement die statische Methode Parse zur Verfügung, die ein XElement-Objekt aus einer XML-Zeichenfolge erstellt, zum Beispiel:

string xml = "<Name>Andreas</Name>";
XElement element = XElement.Parse(xml);

XML-Daten erzeugen und speichern

Ein XElement-Objekt beschreibt als Container weitere untergeordnete Elemente. Über die Konstruktoren werden die Elemente ineinander verschachtelt, um so die gewünschte XML-Struktur abzubilden. Exemplarisch wollen wir die folgende XML-Struktur mit der LINQ-to-XML-API abbilden.


<?xml version="1.0" encoding="utf-8"?>
<Personen>
  <Person>
    <Name>Fischer</Name>
    <Vorname>Manfred</Vorname>
    <Alter>45</Alter>
  </Person>
</Personen>

Der Code, der dieses XML erzeugt, lautet wie folgt:


XElement persons = new XElement("Personen",
                       new XElement("Person",
                           new XElement("Name", "Fischer"),
                           new XElement("Vorname", "Manfred"),
                           new XElement("Alter", "45")
                       )
                   );
persons.Save(@"D:\Personen.xml");

Mit einer einzigen Anweisung hat man bereits das XML erzeugt – übrigens einschließlich des Prologs. Diese Anweisung in eine Zeile zu schreiben ist wenig ratsam. Sie sollten stattdessen eine Schachtelung im Code vornehmen, aus der auch die Struktur der XML-Tags ersichtlich ist. Das ist natürlich deutlich intuitiver, als dazu beispielsweise die Klasse XmlWriter zu verwenden (vergleichen Sie dazu bitte das Beispielprogramm XmlWriterSample in Abschnitt 16.5). Zum Schluss wird durch Aufruf der Methode Save das mit Code beschriebene XML in einer Datei gespeichert. Es erweist sich als vorteilhaft, dass Sie sich nicht weiter um die End-Tags Gedanken machen müssen, denn diese sind bereits durch die Klammerung des Programmcodes vorgegeben und werden damit bereits zur Entwurfszeit sichergestellt.

Der Konstruktor der Klasse XElement hat drei Überladungen. In unserem Beispiel haben wir die folgende benutzt:


public XElement(XName name, Object content)

Sehen wir uns zuerst den ersten Parameter an. Dieser ist vom Typ XName. Übergeben wir an dieser Stelle einen String, wird die Zeichenfolge hinter den Kulissen implizit in ein XName-Objekt konvertiert. Das vereinfacht die Übergabe an den ersten Parameter ganz deutlich.

Dem zweiten Parameter können wir ein x-beliebiges Objekt übergeben. Am häufigsten kommen hier die folgenden Objekte zum Einsatz:

  • ein XElement-Objekt, das als untergeordnetes Element eingefügt wird
  • eine Zeichenfolge, die als Textinhalt bewertet wird
  • ein XAttribute-Objekt, das als Attribut dem Element hinzugefügt wird
  • eine XProcessingInstruction oder ein XComment
  • ein XText-Objekt, das häufig einen CData-Wert beschreibt

Namespaces definieren

Um einen Namespace festzulegen, benutzen Sie das Element XAttribute.


XNamespace ns = "http://www.tollsoft.de";
XElement persons = new XElement(ns + "Personen");

Dabei wird das folgende XML erzeugt:


<Personen xmlns="http://www.tollsoft.de" />

Um einen Namespace mit einem Präfix zu verbinden, können Sie an das Element ein XAttribute-Element anhängen. Übergeben Sie dem Konstruktor zuerst den durch die Eigenschaft Xmlns des XNamespace-Elements beschriebenen Namespace, und verbinden Sie diesen mit dem Präfix. Dem zweiten Parameter übergeben Sie die XNamespace-Variable.

Das hört sich kompliziert an, deshalb sehen wir uns dazu auch sofort ein Beispiel an. Nehmen wir dazu das Beispiel von oben. Es soll ein Namespace definiert werden (http://www.tollsoft.de), der als Präfix pers vor jedem XML-Element angegeben werden soll. Der Code sieht dann wie folgt aus:


XNamespace ns = "http://www.tollsoft.de";
XElement persons = new XElement(ns + "Personen",
                       new XAttribute(XNamespace.Xmlns + "pers", ns), 
                           new XElement(ns + "Person",
                               new XElement(ns + "Name", "Fischer"),
                               new XElement(ns + "Vorname", "Manfred"),
                               new XElement(ns + "Alter", "45")
                           )
                   );

Aus diesem Codefragment resultiert das folgende XML-Dokument:


<?xml version="1.0" encoding="utf-8"?>
<pers:Personen xmlns:pers="http://www.tollsoft.de">
  <pers:Person>
    <pers:Name>Fischer</pers:Name>
    <pers:Vorname>Manfred</pers:Vorname>
    <pers:Alter>45</pers:Alter>
  </pers:Person>
</pers:Personen>


Galileo Computing - Zum Seitenanfang

16.9.3 Die Klasse »XDocument« Zur nächsten ÜberschriftZur vorigen Überschrift

Die beiden Klassen XElement und XDocument sind sich sehr ähnlich. Mit beiden können Sie XML-Daten laden und speichern sowie die XML-Daten bearbeiten. Der wesentlichste Unterschied ist, dass mit XDocument auch die XML-Deklaration bearbeitet werden kann und mehrere XML-Prozessinstruktionen hinzugefügt werden können. Möchten Sie also in den geladenen Daten auf XML-Kommentare, die XML-Deklaration oder XML-Prozessinstruktionen zugreifen, ist die Klasse XDocument jedenfalls die bessere Wahl. Dazu ein Beispiel:


XDocument doc = new XDocument(
  new XDeclaration("1.0", "utf-8", "yes"),
  new XComment("Dokument enthält Personen"),
  new XProcessingInstruction("XML-StyleSheet", "meine.xsl"),
  new XElement("Personen", 
      new XElement( ...));


Galileo Computing - Zum Seitenanfang

16.9.4 Navigation im XML-Dokument Zur nächsten ÜberschriftZur vorigen Überschrift

Die beiden Klassen XElement und XDocument unterscheiden sich nicht wesentlich. Das wurde bereits eben erwähnt. Die gleiche Aussage gilt auch hinsichtlich der Navigationsmöglichkeiten. XElement und XDocument weisen zahlreiche Möglichkeiten auf, die eine Navigation durch ein XML-Dokument ermöglichen. Hier auf alle einzugehen, würde den Rahmen des Buches sprengen. Allerdings sollen Sie mit den wichtigsten Navigationsmethoden, die auch oft als Achsenmethoden bezeichnet werden, das Prinzip der Navigation kennenlernen.

Als Ausgangspunkt dient uns dabei eine XML-Datei, die die Daten von drei Personen und einem Kunden beschreibt:


<?xml version="1.0" encoding="utf-8"?>
<Personen>
  <Person>
    <Name>Fischer</Name>
    <Vorname>Manfred</Vorname>
    <Alter>45</Alter>
    <Adresse Ort="Aachen" Strasse="Gasse 1"></Adresse>
  </Person>
  <Kunde>
    <Name>Tollsoft AG</Name>
  </Kunde>
  <Person>
    <Name>Meier</Name>
    <Vorname>Franz</Vorname>
    <Alter>76</Alter>
    <Adresse Ort="Ulm" Strasse="Avenue 12"></Adresse>
  </Person>
  <Person>
    <Name>Schmidt</Name>
    <Vorname>Detlef</Vorname>
    <Alter>28</Alter>
    <Adresse Ort="Bonn" Strasse="Weg 34"></Adresse>
  </Person>
</Personen>

Die Methode »Element«

Die Methode Element gestattet uns, ein Element aufgrund seines Namens zu selektieren. Wir wollen das sofort testen und schreiben den folgenden Code, um auf das erste <Person>-Element zuzugreifen.


XElement root = XElement.Load(@"..\..\Personen.xml");
XElement element = root.Element("Person");
Console.WriteLine(element);

Hier wird die Load-Methode der Klasse XElement benutzt, um auf die Datei Personen.xml zuzugreifen. Die Variable root referenziert danach das Stammelement Personen des geöffneten XML-Dokuments. Darauf rufen Sie die Methode Element auf und übergeben ein XName-Objekt. Alternativ lässt sich auch der Bezeichner des gesuchten Elements als Zeichenfolge angeben, die implizit in den Typ XName konvertiert wird. Die Ausgabe an der Konsole wird wie folgt lauten:


<Person>
  <Name>Fischer</Name>
  <Vorname>Manfred</Vorname>
  <Alter>45</Alter>
  <Adresse Ort="Aachen" Strasse="Gasse 1"></Adresse>
</Person>

Ändern Sie die Ausgabeanweisung in der Weise ab, dass Sie das XElement element in eine Zeichenfolge konvertieren. Das ist möglich, weil die Klasse XElement eine ganze Reihe expliziter Typumwandlungen definiert, unter anderem auch in string:


Console.WriteLine((string)element);

Nun werden nur noch die Werte der Elemente angezeigt, also:


FischerManfred45

Wenn Sie der Methode Element einen Bezeichner übergeben, der nicht im XML-Dokument gefunden wird, ist der Rückgabewert null.

Die Methode »Elements«

Gehen wir nun einen Schritt weiter. Wie Sie dem XML-Dokument entnehmen können, sind unterhalb des Stammelements drei <Person>-Elemente und ein <Kunde>-Element angeordnet. Uns interessieren jetzt ausschließlich die <Person>-Elemente, aber nicht das <Kunde>-Element. Hier hilft uns die Methode Elements weiter, die im Gegensatz zu Element nicht nur das erste, sondern alle übereinstimmenden Elemente zurückliefert. Der Rückgabewert ist vom Typ IEnumerable<XElement>. Sie können die Methode parameterlos aufrufen oder ein Element vom Typ XName übergeben (oder, wie im Abschnitt zuvor bereits erwähnt, eine Zeichenfolge). Die Liste der <Person>-Elemente erhalten wir mit den folgenden Anweisungen:


XElement root = XElement.Load(@"..\..\Personen.xml");
IEnumerable<XElement> elements = root.Elements("Person");
foreach (XElement item in elements)
  Console.WriteLine(item);

Die Anzeige an der Konsole gibt uns alle <Person>-Elemente einschließlich der untergeordneten Elemente aus:


<Person>
  <Name>Fischer</Name>
  <Vorname>Manfred</Vorname>
  <Alter>45</Alter>
  <Adresse Ort="Aachen" Strasse="Gasse 1"></Adresse>
</Person>
...
<Person>
  <Name>Schmidt</Name>
  <Vorname>Detlef</Vorname>
  <Alter>28</Alter>
  <Adresse Ort="Bonn" Strasse="Weg 34"></Adresse>
</Person>

Die Methode Elements lässt sich auch parameterlos aufrufen, also:


XElement root = XElement.Load(@"..\..\Personen.xml");
IEnumerable<XElement> elements = root.Elements();

Es werden daraufhin alle Elemente anzeigt, die dem Element untergeordnet sind, auf dem die Methode aufgerufen wird.


<Person> ... </Person>
<Kunde> ... </Kunde>
<Person> ... </Person>
<Person> ... </Person>

Die Methode »Attribute«

Das Element Adresse hat mit Ort und Strasse zwei Attribute. Wir wollen nun in Erfahrung bringen, welcher Wert sich hinter dem Attribut Strasse des ersten Elements verbirgt. Dazu navigieren wir zum ersten <Person>-Element und von dort aus zum Element <Adresse>. Auf dessen Referenz rufen wir die Methode Attribut auf und geben dabei den Attributbezeichner an. Genauso wie die Methode Element liefert uns Attribut das erste passende Element. Wird kein übereinstimmendes Element gefunden, ist der Rückgabewert auch in diesem Fall null.


XElement root = XElement.Load(@"..\..\Personen.xml");
XElement element = root.Element("Person");
XElement address = element.Element("Adresse");
XAttribute attr = address.Attribute("Strasse");
Console.WriteLine(attr);

Aus dem Code resultiert die folgende Konsolenausgabe:


Strasse="Gasse 1"

Die Methode »Descendants«

Die Methode Descendants (Nachfahren) ermittelt alle Elemente, die einem bestimmten Knoten untergeordnet sind. Wir wollen uns die Methode Descendants wieder am Beispiel unseres XML-Dokuments ansehen. Unser Ziel sei es, alle Elemente zu finden, die dem ersten <Person>-Element untergeordnet sind.


XElement root = XElement.Load(@"..\..\Personen.xml");
XElement element = root.Element("Person");
IEnumerable<XElement> elements = element.Descendants();
foreach (XElement item in elements)
  Console.WriteLine(item);

Weil wir durch den Aufruf der Methode Element zum ersten passenden <Person>-Element navigieren, wird die Ausgabe wie folgt lauten:


<Name>Fischer</Name>
<Vorname>Manfred</Vorname>
<Alter>45</Alter>
<Adresse Ort="Aachen" Strasse="Gasse 1"></Adresse>

Vergleichen Sie diese Ausgabe mit der sehr ähnlichen der Methode Element: Das aktuelle Element ist nicht Bestandteil der Ergebnismenge.

Sie können der Methode Descendants auch ein XName-Objekt übergeben. Die Methode liefert dann alle untergeordneten Elemente, die dem mit XName beschriebenen Element entsprechen. Vielleicht interessieren Sie sich für sämtliche Namen im Dokument. Hier sind die Anweisungen dazu:


XElement root = XElement.Load(@"..\..\Personen.xml");
IEnumerable<XElement> elements = root.Descendants("Name");
foreach (XElement item in elements)
  Console.WriteLine((string)item);

Da die Laufvariable item in einen String umgewandelt wird, lautet die Ausgabe:


Fischer
Tollsoft AG
Meier
Schmidt

Die Methode »Ancestors«

Mit der Methode Descendants suchen Sie nach Elementen, die weiter im Inneren eines XML-Dokuments, also untergeordnet sind. Die Methode Ancestors (Vorfahren) arbeitet in exakt entgegengesetzter Richtung: Sie sucht nach übereinstimmenden Elementen oberhalb des aktuellen Knotens.

Nachdem wir bisher gesehen haben, wie wir mit verschiedenen Methoden der Klasse XElement innerhalb eines XML-Dokuments navigieren können, wollen wir die Methode Ancestors dazu benutzen, endlich einen LINQ-Ausdruck zu verwenden, um ein bestimmtes Ziel bei der Auswertung zu erreichen. Es sollen uns dabei die Daten interessieren, die die Person mit dem Namen Meier beschreiben.


XElement root = XElement.Load(@"..\..\Personen.xml");
// nach der Person 'Meier' suchen
XElement person = root.Descendants("Name")
                      .Where(pers => (string)pers == "Meier")
                      .First();
// Knoten 'Person' des gefundenen Elements referenzieren
var elemts = person.Ancestors("Person");
// alle Elemente abfragen
foreach(var item in elemts.Elements())
  // prüfen, ob das aktuelle Element Attribute hat
  if (item.HasAttributes){ 
    // Liste aller Attribute abfragen
    foreach (var temp in item.Attributes())
      Console.WriteLine((string) temp);
  }
  else
    Console.WriteLine((string)item);

Nach dem Laden des XML-Dokuments mit der Methode Load suchen wir mit Descendants alle <Name>-Elemente im Dokument. Mit der Erweiterungsmethode Where filtern wir alle Elemente heraus, die die Person Meier beschreiben. Die Erweiterungsmethode First liefert bei mehreren gleichnamigen Personen in der Ergebnismenge die zuerst gefundene Person.

Da <Name> nur eines von mehreren datenbeschreibenden Elementen ist, müssen wir mit Ancestors in der Dokumentstruktur eine Ebene höher gehen, um das dazugehörige <Person>-Element referenzieren. Die Methode Elements gestattet es dann, auf dem gefundenen <Person>-Element alle untergeordneten Elemente mit Elements abzurufen. Dabei kommt erschwerend hinzu, dass eines der untergeordneten Elemente Attribute hat, die ebenfalls ausgewertet werden müssen. Daher prüfen wir die Elemente mit HasAttributes dahingehend, ob durch das aktuelle Element auch Attribute beschrieben werden. Sollte das der Fall sein, durchlaufen wir diese in einer Schleife. Die Liste aller Attribute stellt uns die Methode Attributes zur Verfügung.


Hinweis

Die Codefragmente zur Navigation finden Sie auf der Buch-DVD innerhalb des Beispielprogramms NavigationSamples.



Galileo Computing - Zum Seitenanfang

16.9.5 Änderungen am XML-Dokument vornehmen topZur vorigen Überschrift

Sicherlich werden Sie ein XML-Dokument nicht nur einlesen, sondern es darüber hinaus auch bearbeiten wollen. Dazu zählen sowohl das Ändern vorhandener Daten als auch das Hinzufügen oder Löschen vorhandener Elemente.

XML-Dokument editieren

Um den Wert eines bestimmten Elements zu ändern, müssen wir es zunächst einmal referenzieren. Angenommen, die Altersangabe des Herrn Schmidt in unserem Dokument sei deutlich zu jung ausgefallen, und wir müssen sie ändern. Dazu müssen wir Herrn Schmidt zunächst im XML-Dokument ausfindig machen, ehe wir die Anpassung vornehmen können.

Zur Änderung eines Elements dient die Methode SetElementValue. Zur Änderung muss ein Aufruf auf dem übergeordneten Element erfolgen. SetElementValue erwartet zwei Parameter: Der erste beschreibt ein XName-Objekt, der zweite ist vom Typ Object. Das XName-Objekt kann durch den Bezeichner des zu ändernden Elements beschrieben werden, der zweite Parameter erwartet den neuen Wert.

Das folgende Codefragment zeigt, wie Sie das zu ändernde Element aufspüren und ändern können.


XElement root = XElement.Load(@"D:\Personen.xml");
XElement name = root.Descendants("Name")
                .Where(pers => (string)pers == "Fischer")
                .First();
XElement person = name.Parent;
person.SetElementValue("Alter", 18);

Wie schon im letzten Beispielcode suchen wir zuerst den Eintrag Fischer im XML-Dokument. Im nächsten Schritt muss das direkt übergeordnete Element referenziert werden. Die im letzten Abschnitt vorgestellte Methode Ancestors ist dazu wenig geeignet, da sie uns eine Liste liefert, in der anschließend ein erneuter Suchvorgang ausgeführt werden müsste. Deutlich besser eignet sich die Eigenschaft Parent, die das direkt übergeordnete XElement liefert, also die Referenz auf das <Person>-Element des Herrn Fischer. Darauf wird die SetElementValue-Methode aufgerufen.

Element hinzufügen

Zum Hinzufügen von Elementen stehen Ihnen mehrere Möglichkeiten zur Verfügung. Zuerst seien die Methoden Add, AddAfterSelf, AddBeforeSelf und AddFirst genannt. Diese werden durch das XElement-Objekt zur Verfügung gestellt. Dabei wird AddFirst das neue Element vor dem aktuell referenzierten Element einfügen, AddAfterSelf fügt es nach dem aktuell referenzierten Element ein – jeweils auf derselben Strukturebene. AddFirst hingegen fügt das neue Element als erstes untergeordnetes Element ein, Add als letztes aller untergeordneten. Allen vier Methoden übergeben Sie das neue Element als XElement-Objekt, z. B. so:


person.Add(new XElement("Telefon", 12345));

Sie können aber auch die im vorigen Abschnitt vorgestellte Methode SetElementValue zum Hinzufügen eines neuen untergeordneten Elements einsetzen. Wenn Sie dazu dem ersten Parameter ein XName-Objekt (oder eine entsprechende Zeichenfolge) übergeben, die namentlich nicht als untergeordnetes Element erkannt wird, wird das XName-Objekt als neu hinzuzufügendes Element interpretiert.

Genauso soll es nun dem einzigen Kunden in unserem Dokument ergehen:


XElement root = XElement.Load(@"D:\Personen.xml");
XElement name = root.Descendants("Name")
                    .Where(pers => (string)pers == "Tollsoft AG")
                    .First();
XElement person = name.Parent;
person.SetElementValue("Telefon", 123456);

Element löschen

Auch zum Löschen eines Elements werden von der Klasse XElement mehrere Methoden angeboten (z. B. Remove, RemoveAll, RemoveAttribute). Da uns die Methode SetElementValue aber bereits sehr vertraut geworden ist, wollen wir sie dazu benutzen. Sie müssen dazu nur im zweiten Parameter null übergeben. Das ist bereits alles.

Um das noch zuvor zugestandene Element für die Telefonnummer des Kunden wieder zu entfernen, genügt die folgende Anweisung:


person.SetElementValue("Telefon", null);



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2010

Visual C# 2010
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2010
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern