XML-Verarbeitung: Navigierung
Um innerhalb eines XML-Dokuments zu navigieren, bietet uns C# eine XPath-Schnittstelle. Hierfür benötigen wir die Klassen XPathDocument und XPathNavigator. Dem Konstruktor der XPathDocument-Klasse wird als Parameter der Dateiname übergeben. Über die Funktion CreateNavigator() des XPathDocument-Objekts erhalten wir ein Objekt der XPathNavigator-Klasse.
Um einen XPath-Ausdruck zu verarbeiten, kann die Funktion Evaluate() verwendet werden. Diese erwartet eine Zeichenkette als Parameter. Der Rückgabewert ist ein Objekt, welcher in den meisten Fällen mit Hilfe der ToString()-Funktion in eine Zeichenkette umgewandelt werden kann, um den gewünschten Wert zu erhalten. Die Funktion MoveToFirstChild() navigiert zum ersten Element in der nächsten Ebene. Zu den nächsten Elementen in der gleichen Ebene können wir mit Hilfe der Funktion MoveToNext() navigieren. Hier ist schon deutlich erkennbar, dass der XPath-Navigator durch die einzelnen Ebenen navigiert. Über die Eigenschaft NodeType können wir den Typ des aktuellen Knotens abfragen. Hierfür dient die Enumeration XPathNodeType, die mit der Enumeration XmlNodeType vergleichbar ist. Auch die Eigenschaften Name und Value sind so wie in der XmlReader-Klasse auch verfügbar. Über die Eigenschaft HasChildren können wir abfragen, ob das Element weitere untergeordnete Elemente hat. Für die Navigation durch Attribute dienen die Funktionen MoveToFirstAttribute() und MoveToNextAttribute(). Sowohl MoveToFirstChild() und MoveToNext() als auch MoveToFirstAttribute() und MoveToNextAttribute() geben einen boolschen Wert zurück, mit welchem festgestellt werden kann, ob die Navigation möglich war. Wenn wir wieder in die übergeordnete Ebene wechseln wollen, können wir die Funktion MoveToParent() verwenden. Das Beispiel wird den Zusammenhang der einzelnen Funktionen und das Konzept der Navigierung etwas verständlicher erklären.
Program.cs
XPathDocument oDocument; XPathNavigator oNavigator; try { oDocument = new XPathDocument("test.xml"); oNavigator = oDocument.CreateNavigator(); // zum (ersten) Wurzel-Element navigieren oNavigator.MoveToFirstChild(); // versuchen in die untegeordnete Elementen-Ebene zu wechseln if (oNavigator.MoveToFirstChild()) { // mit einer Schleife durch alle direkt untergeordneten Elemente (2. Ebene) gehen do { if (oNavigator.NodeType == XPathNodeType.Comment) Console.WriteLine("Kommentar: " + oNavigator.Value); else if (oNavigator.NodeType == XPathNodeType.Element) { Console.WriteLine("Element: " + oNavigator.Name); if (oNavigator.HasChildren) Console.WriteLine(" -> weitere Unterelemente vorhanden"); // versuchen in die Attribut-Ebene zu wechseln if (oNavigator.MoveToFirstAttribute()) { Console.WriteLine(" -> Attribute vorhanden:"); // mit einer Schleife durch alle Attribute des Elementes gehen do { Console.WriteLine(" + {0} = {1}", oNavigator.Name, oNavigator.Value); } while (oNavigator.MoveToNextAttribute()); // wieder zurück in die Elementen-Ebene wechseln oNavigator.MoveToParent(); } } } while (oNavigator.MoveToNext()); } // oDocument und oNavigator müssen nicht geschlossen werden } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.ReadKey();
test.xml
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <datenbank> <stadt stadtstaat="ja"> <name>Berlin</name> <bundesland>Berlin</bundesland> <flaeche>891,85 km</flaeche> <einwohnerzahl>3.543.676</einwohnerzahl> </stadt> <stadt landeshauptstadt="ja"> <name>München</name> <bundesland>Bayern</bundesland> <flaeche>310,43 km</flaeche> <einwohnerzahl>1.378.176</einwohnerzahl> </stadt> <stadt stadtstaat="ja"> <name>Hamburg</name> <bundesland>Hamburg</bundesland> <flaeche>755,26 km¦</flaeche> <einwohnerzahl>1.813.587</einwohnerzahl> </stadt> <!-- Frankfurt am Main ist nicht die Landeshauptstadt! --> <stadt landeshauptstadt="nein"> <name>Frankfurt am Main</name> <bundesland>Hessen</bundesland> <flaeche>248,31 km</flaeche> <einwohnerzahl>691.518</einwohnerzahl> </stadt> <stadt landeshauptstadt="nein"> <name>Köln</name> <bundesland>Nordrhein-Westfalen</bundesland> <flaeche>405,17 km</flaeche> <einwohnerzahl>1.017.155</einwohnerzahl> </stadt> </datenbank>