C#: Grundlagen LINQ to XML

Im Beitrag C#: CSV-Datei mit LINQ einlesen wurde beschrieben wie man mit LINQ eine CSV-Datei einlesen kann. Nun gibt es mit LINQ to XML-API eine komfortable Möglichkeit XML-Dateien zu verarbeiten. Damit ist es möglich LINQ-Abfragen für das XML-Dokument zu schreiben, um Auflistungen von Elementen und Attributen abzurufen. Darüber hinaus werden Methoden für das Editieren (wie z.B. Hinzufügen oder Löschen) bereitgestellt. Dazu werden keine Kenntnisse in XPath, XQuery oder DOM benötigt, was den Umgang mit XML-Dokumenten ungemein erleichtert. Dabei kommt man in fast allen Fällen mit deutlich weniger und besser verständlichem Quellcode zum Ziel, als dies mit den vorgenannten Technologien der Fall ist. In diesem Artikel werden nun einige Beispiele gezeigt wie man mit der LINQ to XML-API XML-Dokumente einlesen, erstellen und editieren kann.

Die LINQ to XML-API

Die relevanten Klassen befinden sich im System.Xml.Linq-Namespace. Die folgende Tabelle gibt einen kurzen Überblick über die wichtigsten Klassen:

Klassen der LINQ to XML-API

KlasseBeschreibung
XDocumentDiese Klasse repräsentiert ein komplettes XML-Dokument. Für das Laden und Sichern von bestehenden XML-Dokumenten werden die statischen Methoden Load und Save zur Verfügung gestellt. Über den Konstruktor können neue XML-Dokumente erzeugt werden.
XElementEine der wichtigsten Klassen aus dem System.Xml.Linq-Namepace ist die XElement-Klasse. Diese Klasse repräsentiert ein XML-Element, das wiederum weitere XML-Elemente (XML-Fragment) 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. Über diese Methoden ist es dann möglich Elemente/Attribute hinzuzufügen, zu editieren oder zu löschen. Ebenso werden Methoden zum Laden/Sichern bereitgestellt. Über den Konstruktor können komplette XML-Baumstrukturen erzeugt werden.
XAttributeDiese Klasse stellt ein XML-Attribut dar und kann für die Erzeugung/Verwaltung von XML-Attributen verwendet werden.
XCommentKlasse für die Verwaltung von XML-Kommentaren
XNodeDiese abstrakte Klasse stellt einen XML-Knoten (Element-, Kommentar-, Dokumenttyp-, Verarbeitungsanweisungs- oder Textknoten) in der XML-Struktur dar. Dabei sind die wichtigsten Methoden zum Hinzufügen, Löschen, Ersetzen oder Verschieben von Knoten innerhalb des XML-Dokuments bereits implementiert.
XDeclarationStellt eine XML-Deklaration dar und wird für die Angabe der XML-Version sowie der Kodierung (Zeichensatz, z.B. UTF-8/UTF-16) genutzt.

Weitere Informationen zu den einzelnen Klassen sind in der MSDN-Dokumentation zum System.Xml.Linq-Namespace zu finden. Kommen wir nach dieser Kurzübersicht zu einigen Beispielen, die die Verwendung der oben gezeigten Klassen verdeutlichen.

Erzeugen von XML-Strukturen

Einer der bedeutendsten Vorteile beim Programmieren mit LINQ to XML ist die einfache Erstellung von selbst komplexesten XML-Strukturen. Dafür muss nicht jedes XML-Element einzeln erzeugt werden, sondern die LINQ to XML-API erlaubt die direkte Verkettung der Konstruktoren der einzelnen Elemente (XElement, XAttribute, usw.). Angenommen man möchte das folgende XML-Fragment erstellen (ich greife hier nochmal das Beispiel mit den Postleitzahlen auf):

In C# könnte dieses XML-Fragment wie folgt erzeugt werden:

Wie oben zu sehen orientiert sich die Schachtelung der einzelnen Objekt-Konstruktoren an der Schachtelung der XML-Tags (inklusive der Definition der einzelnen Attribute). Damit hätte man schon das erste XML-Fragment erzeugt. Um daraus jetzt ein komplettes XML-Dokument zu erzeugen kann man wie folgt vorgehen:

Hier wird nun die Klasse XDocument verwendet, welche eine komplette XML-Datei repräsentiert. In Zeile 20 wird dann die Save-Methode dieser Klasse verwendet, um die erzeugte XML-Struktur in eine Datei zu schreiben. Der Output sieht dann wie folgt aus:

LinqToXml_01

Laden von XML-Dokumenten

Natürlich ist es auch möglich bestehende XML-Dokumente einzulesen. Dafür stellt die Klasse XDocument Load– bzw. Save-Methoden bereit. Von der XDocument.Load-Methode gibt es diverse Überladungen, die es erlauben Daten aus diversen Quellen, wie z.B. aus einer Datei (auch URL), einem XmlReader oder TextReader, einzulesen. Darüber hinaus existiert eine Parse-Methode, um Daten aus einer Zeichenkette einzulesen. Nachfolgend mal ein Auflistung der zur Verfügung stehenden Methoden:

Die gleichen statischen Methoden werden von der XElement-Klasse bereitgestellt (XElement.Load-Methode bzw. XElement.Parse-Methode). Diese Methoden liefern anstatt eines XDocument-Objekts eine XElement-Instanz zurück. Hier mal zwei einfache Beispiele:

Laden und Sichern einer XML-Datei

Parsen eines Strings

Ich möchte an dieser Stelle nicht weiter auf Details der einzelnen Überladungen eingehen. Hier lediglich der Verweis auf die MSDN-Dokumentation (XDocument.Load-Methode bzw. XDocument.Parse-Methode).

Sichern einer XML-Datei

Die Klassen XDocument und XElement bieten verschiedene Möglichkeiten XML-Dateien zu editieren. Hat man nun Änderungen an einer XML-Datei vorgenommen möchte man die gemachten Änderungen meistens auch wieder persisitieren. Hier bieten sich die verschiedenen Überladungen der Save-Methode zur Ausgabe in eine Datei, einen TextWriter oder XmlWriter an:

Weitere Informationen zu der Save-Methode sind in der MSDN-Dokumentation zu finden:

Editieren von XML-Dokumenten

In vielen Fällen sollen die XML-Dateien bzw. XML-Fragmente nicht nur angezeigt, sondern auch bearbeitet werden. Dies lässt sich auch mit der LINQ to XML-API realisieren. Wie man dazu vorgehen muss wird in den nachfolgenden Beispielen gezeigt.

Editieren

Das Editieren von Elementen oder Attributen lässt sich mit der LINQ to XML-API recht einfach umsetzen. Dafür navigiert man zunächst mit den XElement-Methoden zum gewünschten Knoten und für dann die SetElementValue– bzw. SetAttributeValue-Methode aus, um die gewünschten Änderungen durchzuführen. Das könnte dann in etwa so aussehen:

In diesem Beispiel wird zunächst der Eintrag für die Postleitzahl mit dem Wert 66914 ermittelt. Danach wird die SetElementValue-Methode verwendet um für diesen Eintrag eine neue Postleitzahl zu setzen. Für das Editieren von Attributen wird einfach die SetAttributeValue-Methode verwendet.

Hinzufügen von Daten

Für das Hinzufügen von Daten werden die folgenden Methoden zur Verfügung gestellt:

MethodeBeschreibung
AddFügt den angegebenen Inhalt als untergeordneten Knoten in das Dokument oder Element ein
AddFirstFügt den angegebenen Inhalt als ersten untergeordneten Knoten in das Dokument oder Element ein
AddBeforeSelfFügt den angegebenen Inhalt direkt vor dem jeweiligen Knoten in das Dokument oder Element ein

AddAfterSelfFügt den angegebenen Inhalt direkt nach dem jeweiligen Knoten in das Dokument oder Element ein

Das Hinzufügen eines neuen XML-Elements könnte wie folgt realisiert werden:

In Zeile 1 wird das letzte Element innerhalb eines XML-Dokuments ermittelt und in der Variable plz abgelegt. Diese Variable ist vom Typ XElement und wird nun dazu verwendet ein neues Element einzufügen. Dafür wird einfach die Add-Methode dieses Objekts aufgerufen und als Parameter eine neue XElement-Instanz mitgegeben (Zeile 2). Wenn man sich das Ganze jetzt im Debugger anschaut sieht das wie folgt aus:

LinqToXml_04

Löschen von Daten

Das Löschen von Elementen funktioniert analog dem Hinzufügen von Elementen. Die Klasse XElement stellt hierfür ebenfalls geeignete Methoden bereit:

MethodeBeschreibung
RemoveEntfernt den aktuellen Knoten aus seinem übergeordneten Dokument bzw. Element
RemoveAllEntfernt Knoten und Attribute aus diesem Dokument bzw. Element
RemoveAnnotationsEntfernt Anmerkung des spezifizierten Typs

RemoveAttributesEntfernt die Attribute dieses XElement.
RemoveNodesEntfernt die untergeordneten Knoten aus diesem Dokument oder Element.

CSV-Datei in eine XML-Datei konvertieren

Im Beitrag C#: CSV-Datei mit LINQ einlesen wurde beschrieben wie man mit LINQ eine CSV-Datei einlesen kann. Die dort verarbeitete CSV-Datei (mit den deutschen Postleitzahlen) soll jetzt in eine XML-Datei umgewandelt werden. Alles was man dafür braucht wurde in den vorangegangen Beispielen bereits beschrieben und wird jetzt einfach miteinander kombiniert. Diese Konvertierung könnte man wie folgt realisieren:

In Zeile 1-3 wird das XML-Dokument erstellt, Zeile 4-5 erledigen das Einlesen der CSV-Datei und in den Zeilen 6-10 wird pro eingelesener Zeile ein XML-Fragment erzeugt. Das war schon alles! Im Debugger sieht das dann so aus:

LinqToXml_02

Speichert man das Ganze jetzt noch als Datei ab erhält mal folgendes Ergebnis:

LinqToXml_03

Wie an den Beispielen zu sehen ist es mit der LINQ to XML-API auf einfache Art und Weise möglich XML-Dateien zu erzeugen bzw. zu editieren. Ich nutze die LINQ to XML-API gerne für die Arbeit mit XML-Konfigurationsdateien. Weitere Informationen zu der LINQ to XML-API sind in den folgenden Online-Quellen zu finden:

Literaturverzeichnis und Weblinks

Abk.Quelle
[1]Übersicht über LINQ to XML
https://msdn.microsoft.com/de-de/library/bb387061.aspx
[2]LINQ to XML
https://msdn.microsoft.com/de-de/library/bb387098.aspx
[3]System.Xml.Linq-Namespace
https://msdn.microsoft.com/de-de/library/system.xml.linq(v=vs.110).aspx
Fork me on GitHub