14.8 Das Document Object Model (DOM)
14.8.1 Allgemeines

Die Klasse XmlReader bietet nur einen schreibgeschützten, vorwärts gerichteten Lesezugriff, mit XmlWriter nur einen vorwärts gerichteten Schreibzugriff. Zum Bearbeiten des Inhalts eines Elements, zum Einfügen neuer oder zum Löschen enthaltener Elemente gibt es weder Methoden noch Eigenschaften.
Abhilfe schafft das Document Object Model, kurz DOM genannt. Hierbei handelt es sich um eine Spezifikation einer Schnittstelle für den beliebigen Zugriff auf die Elemente in einem XML-Dokument. Diese Spezifikation ist vom W3-Konsortium definiert worden.
Beim Arbeiten auf Basis von DOM wird das komplette XML-Dokument in den Speicher geladen und wird in Form einer Baumstruktur dargestellt. Wenn XML in das Dokumentobjektmodell (DOM) eingelesen wird, werden die einzelnen Teile in Knoten umgesetzt. Diese enthalten zusätzliche Metadaten über sich selbst, z. B. ihren Knotentyp und ihre Werte. Der Knotentyp besteht aus seinem Objekt und bestimmt, welche Aktionen ausgeführt und welche Eigenschaften festgelegt oder abgerufen werden.
Wie das intern realisiert wird, möchte ich Ihnen anhand des folgenden einfachen XML-Codes zeigen:
<Person>
<Name>Fischer</Name>
</Person>
Dieser XML-Code wird im Speicher durch die in der folgenden Abbildung gezeigte Knotenstruktur dargestellt.
Abbildung 14.7 Einfache DOM-Struktur
Das Person-Element wird zu einem XmlElement-Objekt, ebenso wie das folgende Element Name. Der Elementinhalt wird zu einem XmlText-Objekt. Die Methoden und Eigenschaften von XmlElement unterscheiden sich von denen, die für ein XmlText-Objekt verfügbar sind. Folglich ist es wichtig, zu wissen, in welchen Knotentyp das XML-Markup umgesetzt wird, da der Knotentyp bestimmt, welche Aktionen ausgeführt werden können.
Projizieren wir dieses kleine Beispiel auf ein größeres XML-Dokument, präsentiert sich dieses im Speicher als komplexe Baumstruktur. Zur Verdeutlichung diene die folgende XML-Struktur.
<?xml version="1.0" encoding="utf-8" ?>
<Personen>
<Person>
<Name>Fischer</Name>
<Alter>45</Alter>
<Ort="Aachen" PLZ="52072"></Ort>
</Person>
</Personen>
Listing 14.47 XML-Dokument der in Abbildung 14.7 gezeigten DOM-Struktur
In Abbildung 14.8 sehen Sie, wie dieses an sich noch sehr kleine XML-Fragment durch eine bereits verhältnismäßig komplexe Struktur im Speicher repräsentiert wird.
Abbildung 14.8 Darstellung eines XML-Dokuments als Baumstruktur
14.8.2 Arbeiten mit »XmlDocument«

XML-Daten laden
Ein XmlDocument-Objekt enthält manipulierbare XML-Daten auf der Basis von DOM. Nach der Instanziierung der Klasse stehen Ihnen mit Load und LoadXml zwei Methoden zur Verfügung, um das Objekt mit Daten zu füllen.
Der Methode Load können Sie eine URL als Zeichenfolge übergeben. Die URL kann eine lokale Datei oder eine HTTP-URL (also eine Webadresse) sein. Weitere Überladungen erlauben auch die Übergabe eines Stream-, TextReader- oder XmlReader-Objekts.
XmlDocument doc = new XmlDocument();
doc.Load(@"D:\Personen.xml");
Liegt das XML-Dokument in einer Zeichenfolge vor, bietet sich die Methode LoadXml an. Bedingung ist, dass die Zeichenfolge wohlgeformtes XML beschreibt, da ansonsten eine XmlException geworfen wird.
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Person><Zuname>Franz</Zuname></Person>");
Die Variable doc beschreibt nun das im Speicher befindliche XML-Dokument. Mit den Eigenschaften und Methoden des XmlDocument-Objekts können Sie anschließend beliebig durch die Baumstruktur der Knoten navigieren und diese beliebig bearbeiten.
14.8.3 »XmlDocument« und »XPathNavigator«

Es gibt noch eine andere Variante, durch die Baumstruktur zu navigieren. Ausgangspunkt sind dabei die Methoden und Eigenschaften der Klasse XPathNavigator. Dazu wird auf die Referenz des XmlDocuments die Methode CreateNavigator aufgerufen, deren Rückgabewert ein XPathNavigator-Objekt ist.
XmlDocument doc = new XmlDocument();
doc.Load(@"D:\Personen.xml");
XPathNavigator navi = doc.CreateNavigator();
Die Kombination zwischen einem XPathNavigator und einem XmlDocument bietet den Vorteil, die zahlreichen Navigationsmöglichkeiten von XPathNavigator nutzen zu können. Allerdings hat dieser Verbund einen gravierenden Nachteil, denn das XML-Dokument muss zweimal im Speicher abgebildet werden, was bei der Größe vieler XML-Dokumente aus performance- und ressourcentechnischer Sicht nicht mehr akzeptabel ist.
Geänderte Daten speichern
Einer der großen Vorteile von DOM gegenüber anderen Techniken ist, dass die XML-Daten geändert und gespeichert werden können. Dazu stellt das XmlDocument-Objekt die Methode Save bereit, der als Argument eine den Speicherort beschreibende Zeichenfolge oder ein Stream-, TextWriter- oder XmlWriter-Objekt übergeben wird.
14.8.4 Die Klasse »XmlNode« (Operationen mit Knoten)

Ein Objekt vom Typ XmlNode repräsentiert im Speicher einen einzelnen Knoten eines XML-Dokuments. XmlNode ist eine abstrakte Klasse, die viele Methoden und Eigenschaften bereitstellt, um durch eine Knotenstruktur zu navigieren, sie zu ändern oder auch zu ergänzen.
Zahlreiche Ableitungen von XmlNode beschreiben die unterschiedlichen Knotentypen innerhalb eines XML-Dokuments und erweitern die geerbten Eigenschaften und Methoden um knotenspezifische. Zu diesen Ableitungen gehören auch die Klassen, die beispielsweise ein Attribut oder die XML-Deklaration beschreiben, sowie die Klasse XmlDocument. Einen Überblick über die Vererbungshierarchie erhalten Sie in Abbildung 14.9.
Abbildung 14.9 Die Ableitungen der Klasse »XmlNode«
Wenn Sie sich die Liste der Eigenschaften in der Dokumentation der Klasse XmlNode ansehen, werden Sie feststellen, dass sich die meisten zwei Kategorien zuordnen lassen: Sie werden einige Eigenschaften finden, die rein der informellen Analyse eines Knotens dienen, und eine zweite Gruppe, die der Navigation dient.
Den Inhalt eines Knotens auswerten
Sehen wir uns in der folgenden Tabelle zuerst die Eigenschaften an, die informellen Charakter haben.
Eigenschaft | Beschreibung |
InnerText |
Ruft die verketteten Werte des Knotens und sämtlicher ihm untergeordneten Knoten ab oder legt diese fest. Die zurückgegebene Zeichenfolge enthält kein XML-Markup. |
InnerXml |
Liefert das Markup, das nur die untergeordneten Knoten dieses Knotens |
IsReadOnly |
Gibt an, ob der Knoten schreibgeschützt ist. |
Name |
Ruft den Bezeichner des Knotens ab. |
NamespaceURI |
Ruft den Namespace-URI dieses Knotens ab. |
NodeType |
Ruft den Typ des Knotens ab. |
OuterXml |
Ruft das Markup ab, das den aktuellen und alle ihm untergeordneten |
Prefix |
Ruft das Namespace-Präfix dieses Knotens ab oder legt dieses fest. |
Value |
Liefert den Wert des Knotens oder legt ihn fest. Der zurückgegebene Wert hängt vom Knotentyp ab. Beispielsweise liefert der Typ XmlNodetype.Element null, während es sich bei einem Knoten vom Typ Text um den Inhalt des Textknotens handelt. |
Ein Wort noch zu der Eigenschaft NodeType, die uns den Typ des aktuellen Knotens liefert. Diese Eigenschaft ist vom Typ der Enumeration XmlNodeType. Um einen Überblick über einige der wichtigeren Mitglieder dieser Enumeration zu erhalten, sehen Sie sich bitte die folgende Tabelle an.
Konstante | Beschreibung |
Element |
Beschreibt ein Element (z. B. <Person>). |
Attribute |
Beschreibt ein Attribut. |
Text |
Beschreibt den Textinhalt eines Knotens. |
CDATA |
Beschreibt einen CDATA-Abschnitt. |
EntityReference |
Beschreibt eine Entität (z. B. <). |
Comment |
Beschreibt einen Kommentar. |
WhiteSpace |
Beschreibt Leerraum zwischen Markup. |
Die Ausgaben der Eigenschaften InnerText, InnerXml, Name und Value hängen vom Knotentyp ab. Handelt es sich dabei beispielsweise um XmlNodeType.Element oder XmlNodeType.Attribute, wird der entsprechende Bezeichner ausgegeben. Nicht jeder Knotentyp hat einen Bezeichner, der auswertbar ist. Daher liefert Name für diese Knotengruppe einen alternativen Text, z. B. #text, #comment oder #cdata-section. Andererseits haben einige Knoten keinen Inhalt, der mit Value abgerufen werden könnte. Dann ist die Rückgabe null.
Nehmen wir an, im XML-Fragment
<Person>Franz</Person>
würde die Variable node vom Typ XmlNode den Knoten Person beschreiben. (Anmerkung: Befindet sich das genannte Element in einem XML-Dokument, muss zuerst dorthin navigiert werden.) Rufen wir die Name-Eigenschaft ab, wird uns
Person
ausgegeben. InnerXml und InnerText liefern beide gleichermaßen
Franz
zurück, während Value keinen Inhalt hat und null ist. Navigieren wir nun weiter, so dass node auf den Textknoten zeigt, wird Name die Ausgabe
#text
haben und Value sowie InnerText den gewünschten Inhalt Franz anzeigen.
Das folgende Beispielprogramm zeigt die informellen Ausgaben im Zusammenhang. An LoadXml wird dabei eine XML-Struktur übergeben. Anschließend wird mit der Eigenschaft DocumentElement das Stammelement der Struktur abgerufen und in der Variablen root gespeichert. Der Rückgabewert der Eigenschaft DocumentElement ist vom Typ XmlElement, auf das danach exemplarisch Eigenschaften aufgerufen werden.
// Beispiel: ..\Kapitel 14\XmlNodeSample
static void Main(string[] args) {
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Person><Name Zuname='Müller'><Alter>34</Alter>" +
"Peter</Name></Person>");
XmlNode root = doc.DocumentElement;
// Eigenschaft 'Name'
Console.WriteLine("Name:");
Console.WriteLine("{0}\n", root.Name);
// Eigenschaft 'OuterXml'
Console.WriteLine("OuterXml:");
Console.WriteLine("{0}\n", root.OuterXml);
// Eigenschaft 'InnerXml'
Console.WriteLine("InnerXml:");
Console.WriteLine("{0}\n", root.InnerXml);
// Eigenschaft 'Value'
Console.Write("Value:");
if (root.Value == null)
Console.WriteLine(" <leer>\n");
else
Console.WriteLine("\n{0}\n",root.Value);
// Eigenschaft 'InnerText'
Console.WriteLine("InnerText:");
Console.WriteLine("{0}",root.InnerText);
Console.ReadLine();
}
Listing 14.48 Das Beispielprogramm »XmlNodeSample«
Die Ausgabe an der Konsole können Sie in Abbildung 14.10 sehen.
Abbildung 14.10 Die Ausgabe des Beispiels »XmlNodeSample«
Mit den Eigenschaften eines »XmlNode«-Objekts navigieren
Jetzt wollen wir uns die Eigenschaften eines XmlNode-Objekts anschauen, die der Navigation in einer XML-Struktur dienen. Auch hier sollten Sie sich zunächst einen Überblick über die Eigenschaften anhand einer Tabelle verschaffen.
Eigenschaft | Beschreibung |
Attributes |
Diese Eigenschaft ruft eine Auflistung vom Typ XmlAttributCollection ab, die die Attribute des aktuellen Knotens enthält. |
ChildNodes |
Ruft alle untergeordneten Knoten des Knotens ab. |
FirstChild |
Ruft das erste untergeordnete Element des aktuellen Knotens ab. |
HasChildNodes |
Ruft einen Wert ab, der angibt, ob dieser Knoten über untergeordnete Knoten verfügt. |
Item |
Ruft das erste untergeordnete Element mit dem angegebenen Bezeichner ab. |
LastChild |
Ruft das letzte untergeordnete Element des aktuellen Knotens ab. |
NextSibling |
Ruft den nächsten nebengeordneten Knoten ab, der dem aktuellen Knoten folgt. |
ParentNode |
Ruft das übergeordnete Element des aktuellen Knotens ab. |
PreviousSibling |
Ruft den vorhergehenden nebengeordneten Knoten des aktuellen Knotens ab. |
Die Vorgehensweise beim Einsatz dieser Eigenschaften ähnelt der Navigation mit XmlReader oder XPathNavigator. Von jedem beliebigen XmlNode-Objekt aus können Sie mit den Eigenschaften FirstChild, LastChild, NextSibling, PreviousSibling und ParentNode zum nächsten untergeordneten Element, zum letzten untergeordneten Element, zum nächsten bzw. letzten nebengeordneten Element oder gar zum übergeordneten Element wechseln.
Die Collection »XmlChildNodes«
Die Eigenschaft ChildNodes liefert eine Liste aller direkt untergeordneten Knoten ab. Diese wird durch den Typ XmlNodeList beschrieben. Viele Möglichkeiten bietet diese Liste nicht, aber Sie können diese Liste in einer Schleife durchlaufen, sich mit Count die Anzahl der untergeordneten Knoten besorgen oder mit Item einen bestimmten Knoten an der angegebenen Indexposition in der Liste abfragen.
XmlDocument doc = new XmlDocument();
doc.Load(@"D:\Personen.xml");
XmlNode root = doc.DocumentElement;
XmlNodeList nodeList = root.ChildNodes;
foreach (XmlNode node in nodeList)
{
[...]
}
Listing 14.49 Die Liste aller direkt untergeordneten Knoten abfragen
Die Schleifenvariable node kann natürlich dazu benutzt werden, um den damit aktuell referenzierten Knoten weiter zu untersuchen, ob er seinerseits selbst untergeordnete Knoten hat.
Um einen bestimmten untergeordneten Knoten auszuwerten, können Sie sich die Referenz auf das diesen Knoten beschreibende XmlNode-Objekt mit
XmlNode node = irgendeinKnoten.ChildNodes[2];
oder alternativ auch mit
XmlNode node = nodeList[2];
besorgen. In beiden Fällen erhalten Sie die Referenz auf den dritten untergeordneten Knoten.
Auswerten eines kompletten XML-Dokuments
Um ein XML-Dokument komplett auszuwerten, bietet sich ein rekursiver Aufruf einer Methode an, in der eine Untersuchung des aktuellen Knotens stattfindet. Hier spielen die beiden Eigenschaften Attributes und HasChildNodes ihre ganze Stärke aus.
// Beispiel: ..\Kapitel 14\XmlNodeNavigation
static void Main(string[] args) {
XmlDocument doc = new XmlDocument();
doc.Load(@"..\..\Personen.xml");
XmlNode root = doc.DocumentElement;
GetNodes(root, 0);
Console.ReadLine();
}
static void GetNodes(XmlNode node, int level) {
switch (node.NodeType) {
// Prüfen, ob es sich um ein Element handelt
case XmlNodeType.Element:
Console.Write(new string(' ', level * 2));
Console.Write("<{0}", node.Name);
// Prüfen, ob das aktuelle Element Attribute hat
if (node.Attributes != null) {
foreach (XmlAttribute attr in node.Attributes)
Console.Write(" {0}='{1}'", attr.Name, attr.Value);
}
Console.Write(">");
// Prüfen, ob das aktuelle Element untergeordnete Elemente hat
if (node.HasChildNodes)
foreach (XmlNode child in node.ChildNodes) {
if (child.NodeType != XmlNodeType.Text)
Console.WriteLine();
GetNodes(child, level + 1);
}
break;
// Prüfen, ob es sich um auswertbare Daten handelt
case XmlNodeType.Text:
Console.Write(node.Value);
break;
}
}
Listing 14.50 Das Beispielprogramm »XmlNodeNavigation«
Liefert Attributes einen Wert ungleich null, hat das aktuelle Element Attribute, die in einer Schleife abgefragt werden können. HasChildNodes liefert einen Boolean. Ist dieser true, kann die Liste der untergeordneten Knoten mit der Eigenschaft ChildNodes durchlaufen werden. Dabei kommt es zu einem rekursiven Aufruf der benutzerdefinierten Methode GetNodes.
In diesem Beispiel wurden keine Namespaces und Präfixe zur eindeutigen Identifizierung der Elemente in der XML-Datei benutzt. Bei der Navigation spielt das keine Rolle, da etwaig vorhandene Namespaces als Attribute bewertet werden und die Elemente samt dem Präfix ausgegeben werden. Der Parameter level der Methode ChildNodes dient dazu, optisch ansprechende Einzüge in der Ausgabe darstellen zu können.
Abbildung 14.11 Ausgabe des Beispiels »XmlNodeNavigation«
XPath-Ausdrücke verwenden
Um ein Element in einer XML-Struktur eindeutig zu adressieren, können Sie auch einen XPath-Ausdruck festlegen. Die Klasse XmlNode kennt zwei Methoden, denen Sie einen XPath-Ausdruck übergeben können: SelectNodes und SelectSingleNode. Beide Methoden werden auch von der Klasse XmlDocument unterstützt und können daher auch auf die Referenz des XmlDocument-Objekts aufgerufen werden.
SelectNodes liefert eine Auflistung des Typs XmlNodeList mit allen gefundenen Elementen zurück, die dem XPath-Ausdruck entsprechen. Das folgende Codefragment gibt die Liste aller Zunamen aus der XML-Datei Personen.xml aus.
XmlDocument doc = new XmlDocument();
doc.Load(@"..\..\Personen.xml");
XmlNodeList liste = doc.SelectNodes("//Person//Zuname");
foreach(XmlNode temp in liste)
Console.WriteLine("Name: {0}", temp.InnerXml);
Listing 14.51 Mit »SelectNodes« mehrere Knoten abrufen
Sind Sie nur am ersten Element interessiert, liefert der Aufruf von SelectSingleNode genau dieses.
XmlNodeList liste = root.SelectNodes("//Person//Zuname");
Beide Methoden haben zudem noch jeweils eine Überladung, die ein Objekt vom Typ XmlNamespaceManager erwartet, mit dem Sie die Präfixe der Elemente auflösen können. Diese Klasse wurde bereits in Abschnitt 14.7.6 behandelt.
Suche nach bestimmten Elementen
Im folgenden Beispielprogramm wird demonstriert, wie die Inhalte bestimmter Elemente ausgewertet werden können. Im Mittelpunkt steht dabei die Methode GetElementsByTagName, der das zu durchsuchende Element angegeben wird.
// Beispiel: ..\Kapitel 14\SearchForElements
static void Main(string[] args){
XmlDocument doc = new XmlDocument();
doc.Load(@"..\..\Personen.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("Zuname");
// Resultate anzeigen
for (int i = 0; i < elemList.Count; i++) {
Console.WriteLine(elemList[i].InnerXml);
}
Console.ReadLine();
}
Listing 14.52 Beispielprogramm »SearchForElements«
Als Ergebnis werden die Namen aller im XML-Dokument enthaltenen Personen ausgegeben.
14.8.5 Manipulieren einer XML-Struktur

Zahlreiche Methoden sind in den Klassen XmlDocument, XmlNode und XmlNodeList definiert, um neue Knoten hinzuzufügen, vorhandene zu ändern oder gar zu löschen. Um einen besseren Überblick über die sich bietenden Möglichkeiten zu bekommen, wird den drei Operationen des Hinzufügens, Editierens und Löschens jeweils ein eigener Abschnitt gewidmet.
Hinzufügen eines Knotens
Um zu zeigen, wie zusätzliche Knoten einer XML-Struktur hinzugefügt werden, soll im nächsten Codefragment zunächst eine komplett neue XML-Struktur bereitgestellt werden, die wie folgt aussieht:
<?xml version="1.0" encoding="ibm850" ?>
<!--Dies ist ein Kommentar-->
<Personen>
<Person>Peter</Person>
</Personen>
Code, der dies leistet, würde wie folgt lauten:
XmlNode nodePerson, nodeName;
XmlDocument doc = new XmlDocument();
XmlComment cmt = doc.CreateComment("Dies ist ein Kommentar");
doc.AppendChild(cmt);
XmlNode nodeRoot = doc.CreateElement("Personen");
doc.AppendChild(nodeRoot);
nodePerson = doc.CreateElement("Person");
nodeRoot.AppendChild(nodePerson);
nodeName = doc.CreateTextNode("Peter");
nodePerson.AppendChild(nodeName);
doc.Save(Console.Out);
Listing 14.53 Einen Knoten einem XML-Dokument hinzufügen
Die resultierende XML-Struktur weist insgesamt vier Knoten auf, die der Reihe nach erzeugt werden. Dazu stellt die Klasse XmlDocument mehrere passende CreateXxx-Methoden bereit. Im Code werden mit CreateComment, CreateElement und CreateTextNode ein Kommentar, zwei Elementknoten und ein Textknoten erzeugt.
Die Basisklasse aller Knoten, XmlNode, vererbt an alle Ableitungen, also auch an XmlDocument, die Methode AppendChild. Der Aufruf dieser Methode auf einen bestimmten Knoten bewirkt, dass die dem Parameter übergebene XmlNode-Referenz zu einem untergeordneten Knoten des Knotens wird, auf dem die Methode aufgerufen wird.
Nach allem bleibt festzuhalten, dass es sich immer um zwei Schritte handelt, einen neuen Knoten einem existierenden XML-Dokument hinzuzufügen:
- Erzeugen des neuen Knotens mit einer Create-Methode auf die Referenz des XmlDocument-Objekts.
- Aufrufen der Methode AppendChild auf den Knoten, dem der neue Knoten hinzugefügt werden soll. Die Referenz des neuen Knotens wird dabei als Argument dem Methodenaufruf übergeben.
Wird ein neues XML-Dokument erzeugt, dürfen Sie auf dessen Referenz nur einmal die CreateElement-Methode aufrufen, da das so hinzugefügte Element das Wurzelelement des XML-Dokuments beschreibt, von dem es bekanntlich zur Sicherstellung der Wohlgeformtheit nur eines geben darf.
In der folgenden Tabelle finden Sie eine Übersicht der gängigsten CreateXxx-Methoden von XmlDocument.
Methode | Beschreibung |
CreateAttribute |
Erstellt ein neues Objekt vom Typ XmlAttribute. |
CreateCDataSection |
Erstellt ein neues Objekt vom Typ XmlCDataSection. |
CreateComment |
Erstellt ein neues Objekt vom Typ XmlComment. |
CreateDefaultAttribute |
Erstellt ein Standardattribut mit dem angegebenen Präfix, lokalen Namen und Namespace-URI. |
CreateElement |
Erstellt ein neues Objekt vom Typ XmlElement. |
CreateNode |
Erstellt ein neues Objekt vom Typ XmlNode. |
CreateProcessingInstruction |
Erstellt ein neues Objekt vom Typ XmlProcessingInstruction. |
CreateTextNode |
Erstellt ein neues Objekt vom Typ XmlText. |
CreateXmlDeclaration |
Erstellt ein neues Objekt vom Typ XmlDeclaration. |
14.8.6 Ändern eines Knotens

Um einen Knoten zu ändern, benötigen Sie zuerst die Referenz auf den entsprechenden Knoten. Dabei kommen die diversen Navigationsmethoden in Frage oder, was deutlich besser ist, ein XPath-Ausdruck. Das zeigt das folgende Beispielprogramm, das zum Ziel hat, in der Datei Personen.xml das Alter von Klaus Meier neu festzulegen.
// Beispiel: ..\Kapitel 14\EditXmlNode
static void Main(string[] args) {
XmlDocument doc = new XmlDocument();
doc.Load(@"..\..\Personen.xml");
XmlNode root = doc.DocumentElement;
// Referenz auf das zu ändernde Element besorgen
XmlNode node = root.SelectSingleNode("//Person[Zuname ='Meier']/Alter");
if (node != null)
{
XmlNode nodeAlter = node.FirstChild;
// Das Alter ändern
nodeAlter.Value = "33";
XmlNode parent = node.ParentNode;
GetNodes(parent, 0);
Console.ReadLine();
return;
}
else
{
Console.WriteLine("Der angegebene Zuname existiert nicht.");
Console.ReadLine();
}
}
static void GetNodes(XmlNode node, int level) {
switch (node.NodeType) {
// Prüfen, ob es sich um ein Element handelt
case XmlNodeType.Element:
Console.Write(new string(' ', level * 2));
Console.Write("<{0}>", node.Name);
if (node.HasChildNodes)
foreach (XmlNode child in node.ChildNodes) {
if (child.NodeType != XmlNodeType.Text)
Console.WriteLine();
GetNodes(child, level + 1);
}
break;
// Prüfen, ob es sich um auswertbare Daten handelt
case XmlNodeType.Text:
Console.Write(node.Value);
break;
}
}
Listing 14.54 Ändern eines Knotens
Nach dem Laden der Datei und der Referenzierung des Wurzelelements wird mit SelectSingleNode ein XPath-Ausdruck abgesetzt, der anhand des Elements Zuname nach Meier sucht:
//Person[Zuname ='Meier']/Alter
Man sollte berücksichtigen, dass die entsprechende Person nicht vom XML-Dokument beschrieben wird. Der Rückgabewert der Methode SelectSingleNode ist in dem Fall null. Wird das Element Meier gefunden, liefert das Ergebnis des XPath-Ausdrucks das Element Alter und wird mit FirstChild auf den Textknoten verschoben, dessen Inhalt anschließend über die Eigenschaft Value verändert wird. Alternativ hätten Sie auch direkt die Referenz auf das Element Alter benutzen können, um die Änderung vorzunehmen. Sie müssen dann die Eigenschaft InnerText ändern:
XmlNode node = root.SelectSingleNode("//Person[Zuname ='Meier']/Alter");
if (node != null) {
node.InnerText = "33";
[...]
Um uns vom Erfolg zu überzeugen, wird am Ende das die Person Meier betreffende Element komplett ausgegeben. Hierzu dient die Methode GetNodes, die ich Ihnen in ähnlicher Form bereits in Abschnitt 14.8.4 im Beispielprogramm XmlNodeNavigation vorgestellt habe.
Attribute ändern
Um einem Element ein Attribut hinzuzufügen, muss auf die Referenz des entsprechenden Elements die Methode SetAttribute aufgerufen werden. Der Aufruf von SetAttribute erzeugt aber nur dann ein neues Attribut, wenn es ein solches namentlich noch nicht gibt. Ansonsten wird der Inhalt des gefundenen Attributs nur geändert.
Im folgenden Listing wird sowohl ein neues Attribut zu einem XmlElement hinzugefügt als auch ein vorhandenes editiert.
static void Main(string[] args) {
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Personen><Person><Name>Fischer</Name>" +
"<Daten alter='56' ort='Bonn'/></Person></Personen>");
XmlNode root = doc.DocumentElement;
string xpath = "/Personen/Person/Daten";
XmlElement node = (XmlElement)root.SelectSingleNode(xpath);
// Attribut 'ort' ändern
node.SetAttribute("ort", "Aachen");
// Attribut 'plz' hinzufügen
node.SetAttribute("plz", "52072");
// Ausgabe der XML-Struktur
Console.WriteLine(doc.InnerXml);
}
Listing 14.55 Ändern eines Attributs
14.8.7 Löschen in einem XML-Dokument

Löschen eines Elements
Um ein Element aus einer XML-Struktur zu entfernen, rufen Sie die Methode RemoveChild auf das übergeordnete Element des zu löschenden Elements auf. Der Methode wird die Referenz auf das Element übergeben, das entfernt werden soll. Im folgenden Codefragment wird aus der Datei die dritte Person (Petra Schmidt) gelöscht.
XmlDocument doc = new XmlDocument();
doc.Load("Personen.xml");
XmlNode root = doc.DocumentElement;
XmlNode node = root.SelectSingleNode("//Person[Zuname='Schmidt']");
root.RemoveChild(node);
Listing 14.56 Löschen eines Elements aus einem XML-Dokument
Löschen von Attributen
Zum Entfernen eines Attributs stellt Ihnen die Klasse XmlElement vier Methoden zur Verfügung, die Sie der folgenden Tabelle entnehmen können.
Methode | Beschreibung |
RemoveAllAttributes |
Löscht alle angegebenen Attribute des Elements. |
RemoveAttribute |
Entfernt das angegebene Attribut, dessen Bezeichner der Methode übergeben wird. |
RemoveAttributeAt |
Entfernt den Attributknoten mit dem angegebenen Index aus dem Element. |
RemoveAttributeNode |
Löscht das angegebene Attribut, das als XmlAttribute-Referenz angegeben wird. |
Im nächsten Codebeispiel wird exemplarisch das Attribut Ort der Person Meier gelöscht. Dabei wird die Methode RemoveAttribute verwendet. Zum Auffinden dient ein XPath-Ausdruck, dessen Rückgabe bekanntlich vom Typ XmlNode ist. Da die Löschmethode jedoch in der Klasse XmlElement definiert ist, muss das Resultat der Methode SelectSingleNode entsprechend typumgewandelt werden.
string xpath = "//Person[Zuname='Meier']/Adresse";
XmlDocument doc = new XmlDocument();
doc.Load(@"..\..\Personen.xml");
XmlNode root = doc.DocumentElement;
XmlElement element = (XmlElement)root.SelectSingleNode(xpath);
Console.WriteLine(element.Name);
element.RemoveAttribute("Ort");
Listing 14.57 Löschen mit »RemoveAttribute«
Untergeordnete Elemente und Attribute löschen
Mit RemoveAll stellen die Klassen XmlNode und XmlElement eine Methode bereit, die gleichzeitig alle angegebenen Attribute und untergeordneten Elemente des aktuellen Knotens entfernt.
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Person ort='Aachen' plz='52072'>" +
"<Name>Franz Schmitz</Name></Person>");
XmlNode root = doc.DocumentElement;
root.RemoveAll();
Listing 14.58 Löschen aller Attribute mit »RemoveAll«
Als Resultat bleibt als Ergebnis nur noch
<Person></Person>
stehen.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.