In dieser Blogserie möchte ich Ihnen eine kleine Auswahl aus den „Rezepten“ unseres neuen Titels Visual C# 2017 präsentieren und Ihnen als künftigen oder fortgeschrittenen C#-Programmierer einen Vorgeschmack darauf geben, wie Sie einzelne Komponenten für das Microsoft .NET Framework programmieren können. Heute geht es darum, XML-Daten in eine TreeView einzulesen, weitere Themen werden folgen.

Mit einem kleinen Beispielprogramm möchten wir Ihnen zeigen, wie Sie XML-Daten strukturiert in einer TreeView-Komponente anzeigen können. Das Programm lässt sich schnell und einfach an Ihre eigenen Erfordernisse anpassen, beispielsweise um den Unterschied zwischen den einzelnen Knotentypen darzustellen.

Oberfläche

Fügen Sie in ein Formular einen Button sowie eine TreeView-Komponente ein.

Quelltext

Binden Sie zunächst den Namespace System.Xml ein.

Mit dem Klick auf die Schaltfläche wird eine Instanz des XMLDocument-Objektes erzeugt und die Datei daten.xml geladen:

private void button1_Click(object sender, System.EventArgs e)
{
    XmlDocument xmlDoc = new XmlDocument();
    try
    {
       xmlDoc.Load("daten.xml");
    }
    catch
    {
       MessageBox.Show("Datei nicht gefunden!");
       return;
    }

Gleichzeitig löschen wir die bisherigen Inhalte der TreeView-Komponente:

treeView1.Nodes.Clear();

Die Prozedur ShowNode rufen wir mit folgenden Argumenten auf:

  • Vorgängerknoten im Baum (null, d.h. keiner) und
  • Wurzelknoten der XML-Daten (xmlDOC)
ShowNode(null, xmlDoc);
    treeView1.Nodes[0].ExpandAll();
}

Die Prozedur zur Anzeige in der TreeView:

private void ShowNode(TreeNode parent, XmlNode node)
{
    string Caption = "";
    TreeNode tn;

Wird kein gültiges DOM-Objekt übergeben, wird die Routine beendet:

if (node == null) 
    {
       return;
    }

Die Beschriftung des Baumknotens festlegen:

if (node.NodeType == XmlNodeType.Document)
    {
        Caption = "XML-Datei";
    }
    if (node.NodeType == XmlNodeType.Element)
    {
        Caption = node.Name;
    }
    if ((node.NodeType == XmlNodeType.CDATA)||(node.NodeType == XmlNodeType.Text))
    {
        Caption = node.Value;
    }
    if (Caption == "")
    {
        return;
    }

Je nach Knotentyp müssen wir andere Eigenschaften zur Bestimmung der Beschriftung auslesen.

Erzeugen eines neuen Baumknotens mit der gewählten Beschriftung:

if (parent == null)
    {
        tn = treeView1.Nodes.Add(Caption);
    }
    else
    {
        tn = parent.Nodes.Add(Caption);
    }

Sollten Unterelemente vorhanden sein, rufen wir für jedes dieser Elemente die aktuelle Prozedur rekursiv auf:

if (node.ChildNodes != null)
    {
       for (int i = 0; i < node.ChildNodes.Count; i++)
       {
          ShowNode(tn, node.ChildNodes.Item(i));
       }
    }
 }

Test

Starten Sie das Programm und klicken Sie auf die Schaltfläche, um die Daten aus der Datei zu lesen.

Abbildung 1: XML-Daten in eine Treeview einlesen

Abbildung 1: XML-Daten in eine Treeview einlesen

Ergänzung

Wer lieber mit dem XmlReader arbeiten möchte, der muss sich zwar von der rekursiven Programmierung verabschieden, der grundsätzliche Ablauf beim Füllen der TreeView bleibt jedoch gleich:

Starten der Routine:

private void button2_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            ShowNode2(null);
            treeView1.Nodes[0].ExpandAll();
        }

Die eigentliche Routine zum Einlesen:

private void ShowNode2(TreeNode parent)
        {
            TreeNode tn = parent;
            XmlReaderSettings myset = new XmlReaderSettings();
            myset.IgnoreWhitespace = true;

Den XmlReader initialisieren:

XmlReader xr = XmlReader.Create("daten.xml", myset);

Alle XML-Elemente durchlaufen:

while (xr.Read())
            {

Handelt es sich um ein EndElement, müssen wir im Baum eine Ebene nach „oben“ wechseln:

if (xr.NodeType == XmlNodeType.EndElement)
                {
                    tn = tn.Parent;
                }
                else
                {

Elemente haben einen Name:

if (xr.NodeType == XmlNodeType.Element)
                    {
                        if (tn == null)
                        {
                            tn = treeView1.Nodes.Add(xr.Name);
                        }
                        else
                        {
                             tn = tn.Nodes.Add(xr.Name);
                        }
                    }

Texte besitzen einen Value:

if (xr.NodeType == XmlNodeType.Text)
                    {
                        tn.Text = $"{tn.Text}: {xr.Value}";
                    }
                }
            }
        }

Inhalt der Datei daten.xml:

<?xml version="1.0"?>
<!-- Die eigentlichen Daten -->
<DATEN>
  <ERDE>
    <KONTINENT>
      <NAME>Australien</NAME>
    </KONTINENT>
    <KONTINENT>
      <NAME>Antarktik</NAME>
    </KONTINENT>
    <KONTINENT>
      <NAME>Asien</NAME>
    </KONTINENT>
    <KONTINENT>
      <NAME>Afrika</NAME>
    </KONTINENT>
    <KONTINENT>
      <NAME>Europa</NAME>
      <FLÄCHE>10500000</FLÄCHE>
      <EINWOHNER>718500000</EINWOHNER>
      <LAND>
        <NAME>Frankreich</NAME>
        <FLÄCHE>543965</FLÄCHE>
        <EINWOHNER>57800000</EINWOHNER>
      </LAND>
      <LAND>
        <NAME>Deutschland</NAME>
        <FLÄCHE>356854</FLÄCHE>
        <EINWOHNER>80767600</EINWOHNER>
        <ORT marke="O1">
          <NAME>München</NAME>
        </ORT>
        <ORT marke="O2">
          <NAME>Deggendorf</NAME>
        </ORT>
      </LAND>
      <LAND>
        <NAME>Schweden</NAME>
      </LAND>
      <LAND>
        <NAME>Österreich</NAME>
      </LAND>
      <LAND>
        <NAME>Schweiz</NAME>
      </LAND>
      <LAND>
        <NAME>Italien</NAME>
      </LAND>
      <LAND>
        <NAME>Spanien</NAME>
      </LAND>
    </KONTINENT>
    <KONTINENT>
      <NAME>Nordamerika</NAME>
    </KONTINENT>
    <KONTINENT>
      <NAME>Südamerika</NAME>
    </KONTINENT>
  </ERDE>
  <PERSONEN>
    <PERSON ort="O1">
      <NAME>Kotz</NAME>
      <VORNAME>Jürgen</VORNAME>
    </PERSON>
    <PERSON ort="O2">
      <NAME>Kotz</NAME>
      <VORNAME>Julia</VORNAME>
    </PERSON>
    <PERSON ort="O3">
      <NAME>Kotz</NAME>
      <VORNAME>Lennard</VORNAME>
    </PERSON>
  </PERSONEN>
</DATEN>