Xml Sort, sortieren von XML-Daten

  • Autor: H. Wiedow
  • Eingestellt:  08/09/2004

Einige Webprojekte erfordern es, dass ich Daten aus XML - Dokumenten auswerten muss um hieraus entsprechenden Webseiten zu erstellen. In der Regel arbeite ich hier mit einem XSLT - Dokument und selektiere die Daten über die Abfragesprache für XML XPath. Manchmal kommt es aber vor, dass ich lediglich einige Daten brauche um hiermit zum Beispiel eine DropDownList mit Daten zu füllen. Sollen die Daten dann auch noch sortiert dargestellt werden, muss man schon einige Klassen des Net Frameworks bemühen.

Mit XSLT wäre das kein Problem und ich könnte dort einfach über das <xsl:sort> Element die Daten sortieren und über eine Schleife die entsprechenden Daten auswählen. Aber um nur einige Daten in einer DropDownList darzustellen wäre es ein wenig aufwendig ein Style-Sheet zu erstellen und besonders performant wäre das auch nicht.

Also schaute ich mich erst einmal in den von Net Framework bereitgestellten Librarys um und bin im Namespace System.Xml.XPath fündig geworden. Das Zusammenstpiel der beiden Typen XPathExpression und XPathNavigator führt hier zum Erfolg.

Der Typ XPathExpression stellt eine überladene Methode AddSort() zur Verfügung um die Daten zu sortieren und mit der Klasse XPathNavigator können wir durch das Dokument navigieren.

Um die Methode der Klasse XPathExpression nutzen zu können braucht man eine Instanz des Typen XPathNavigator. Eine Instanz des XPathNavigator, lässt sich nicht wie erwartet mit: XPathNavigator nav = new XPathNavigator(); erstellen. Wir können einen XPathNavigator nur über die Methode CreateNavigator(); der Typen: XmlDocument, XmlDataDocument, oder XPathDocument erstellen.

Beispiel XPathNavigator erstellen:

	
					void SortXmlData(){					
							XPathDocument doc = new							
							XPathDocument(Server.MapPath("Test.xml"));
							XPathNavigator nav = doc.CreateNavigator();											
					}				
				

Nun erstell ich eine Instanz des Typen XPathExpression und kompiliere den Ausdruck mit dem erstellen XPathNavigator.

Beispiel XPathExpression erstellen:

										
							string XPathDate =							
							"//Visitor[not(Plattform=preceding::Visitor/Plattform)]/Plattform";
							XPathExpression exp = nav.Compile(xpath);					
					

Dieser XPath Ausdruck gruppiert den Knoten Plattform. Einen Knoten auf diese Weise zu gruppieren ist nicht sehr performant, aber für unser Beispiel soll es reichen. Wer gerne eine effektivere Methode anwenden möchte um eine Knotenmenge zu gruppieren sollte sich einmal mit der The Muenchian Method beschäftigen.

Nun haben wir alle Voraussetzungen geschaffen, um die Methode AddSort() der Klasse XPathExpression aufrufen zu können. XPathExpression stellt zwei überladenen Methoden von AddSort() bereit.

						public abstract void AddSort(
						object expr,
						IComparer comparer
						);
						

Erlaub es eine eigene Sortierroutine zu übergeben, auf diese Möglichkeit möchte ich an dieser Stelle aber nicht näher eingehen.
Wir werden die zweite Version der Methode AddSort() benutzen.

							public abstract void AddSort(
							object expr,
							XmlSortOrder order,
							XmlCaseOrder caseOrder,
							string lang,
							XmlDataType dataType
							);
					

Beispiel für einen Aufruf der AddSort-Methode:

				expr.AddSort("text()", XmlSortOrder.Descending,
				XmlCaseOrder.None, "", XmlDataType.Text);
				

Hierzu habe ich im Netz zahlreiche Beispiele gesehen, die einfach falsch waren. Selbst die Microsoft-Seite brachte hierzu ein falsches Beispiel, das einfach nicht funktionierte und mich somit ermunterte diesen Artikel zu schreiben. In den Beispielen wurde für den Parameter object expr oft der Elementname des XML Knoten angegeben. Damit funktioniert die Routine nicht. Text() weißt den XML-Parser an den Text der Knotenmenge zu sortieren und nur so funktioniert es.

Es gibt noch ein anderes Problem, wenn das XML-Dokument ein Namespace-Prefix nutzt, muss man einen Bug umschiffen indem man über die Klasse XmlNamespaceManager zwei Instanzen der Klasse XPathExpression benutzt. Nähere Informationen finden Sie hierzu auf:
BUG: Data Not Sorted When You Use Namespace Prefix in String Passed to XPathExpression.AddSort
(In diesem Beispiel wird eine Attributmenge sortiert.)

Nun können wir über einen XPathNodeIterator durch die sortierten Elemente des XML-Dokuments navigieren und die Daten nutzen.

Beispiel für die Verwendung des XPathNodeIterator

						XPathNodeIterator iterator =
						nav.Select(expr.Clone());
						while (iterator.MoveNext())
						{
						Response.Write(iterator.Current.Value.ToString());
						}
						

Hier bleibt noch zu erwähnen um die AnwendungMulti Threading fähig zu halten, sollte man die Methode Clone() der Klasse XPathExpression nutzen.

 
 

Resoursen zum Thema:

  • Wer sich das Zusammenspiel der einzelnen Klassen genauer ansehen möchte, kann den
    Quellcode downloaden
  • Informationen zu XML:
    Eine gute Anlaufstelle um sich näher mit dem Thema XML und XSLT zu beschäftigen, ist sicherlich:
    xmlforasp.net