Professional Documents
Culture Documents
Sandini Bib
Essentials
.NET
Die .NET Essentials greifen die wichtigsten Themen des .NET Frameworks auf und behandeln auf knappem Raum, was Sie wissen mssen, um sofort eigene .NET Anwendungen auf hchstem Niveau zu schreiben. Ohne umstndliche Einfhrung kommen Sie umgehend zum Kern des jeweiligen Themas und finden Antworten auf Fragen, mit denen Sie sich beim Codieren immer wieder konfrontiert sehen. Die Autoren zeigen Lsungen auf, die Sie bernehmen oder variieren und in eigene Projekte integrieren knnen: GDI+
Ellen Diehl, Thomas Ehrenberg 192 Seiten 16,95 [D]/sFr 27,50 ISBN 3-8273-1993-5
Web Forms
Holger Schwichtenberg 144 Seiten EUR 16,95 [D]/sFr 27,50 ISBN 3-8273-2010-0
Web Forms ASP.NET-Programmierung mit System.Web.UI: Webcontrols, Ereignisse, State Management, Datenbindung, User Controls, Debugging
Windows Forms
Michael Kofler 176 Seiten 16,95 [D]/sFr 27,50 ISBN 3-8273-1994-3
ADO.NET
Ralf Westphal 144 Seiten 16,95 [D]/sFr 27,50 ISBN 3-8273-1997-8
Grafische Benutzerschnittstellen mit System.Windows.Forms Formularinterna, mehrere Fenster, Multithreading, Zwischenablage, Drag&Drop
Datenbankprogrammierung mit System.Data: relationale Datenbanken fr ADO.NET, komplexe hierarchische Daten, Fehlerbehandlung
... aktuelles Fachwissen rund um die Uhr zum Probelesen, Downloaden oder auch auf Papier.
www.InformIT.de
Sandini Bib
Essentials
.NET
Armin Hanisch
Sandini Bib
Die Deutsche Bibliothek CIP-Einheitsaufnahme Ein Titeldatensatz fr diese Publikation ist bei Der Deutschen Bibliothek erhltlich. Die Informationen in diesem Produkt werden ohne Rcksicht auf einen eventuellen Patentschutz verffentlicht. Warennamen werden ohne Gewhrleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Abbildungen und Texten wurde mit grter Sorgfalt vorgegangen. Trotzdem knnen Fehler nicht vollstndig ausgeschlossen werden. Verlag, Herausgeber und Autoren knnen fr fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung bernehmen. Fr Verbesserungsvorschlge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulssig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwhnt werden, sind gleichzeitig eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Produkt wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie zum Schutz vor Verschmutzung ist aus umweltvertrglichem und recyclingfhigem PE-Material.
5 05
4 04
2 03
1 02
ISBN 3-8273-1998-6 2002 by Addison-Wesley Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Strae 1012, D-81829 Mnchen/Germany Alle Rechte vorbehalten Einbandgestaltung: Barbara Thoben, Kln Lektorat: Christine Auf, cauf@pearson.de, Tobias Draxler, tdraxler@pearson.de Korrektorat: Katja Treu, Mnchen Herstellung: Monika Weiher, mweiher@pearson.de Satz: reemers publishing services gmbh, Krefeld, www.reemers.de Druck und Verarbeitung: Media-Print, Paderborn Printed in Germany
Sandini Bib
Essentials
.NET
Inhalt
Einfhrung
Vorwort Voraussetzungen Typografie Beispielcodes, Errata, Hinweise
7
7 7 8 8
1
1.1 1.2 1.3 1.4
XML-Basics
XML-Terminologie Namensrume Die .NET-Namensrume Untersttzte Standards
9
9 11 13 13
2
2.1 2.2 2.3
15
15 21 26
3
3.1 3.2
27
32 37
4
4.1 4.2 4.3 4.4 4.5
39
39 39 44 48 52
5
5.1 5.2 5.3 5.4 5.5
XPath-Abfragen
Warum XPath? Grundlagen SelectNodes und SelectSingleNode Nutzung des XPathNavigators Zusammenfassung
53
53 53 59 61 65
6
6.1 6.2
XML-Namensrume
Einfhrung Zusammenfassung
67
67 77
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Inhalt
7
7.1 7.2 7.3 7.4 7.5
XSL-Transformationen
Grundlagen Stylesheets laden Transformation durchfhren Transformationen verketten und optimieren Zusammenfassung
79
79 81 82 86 87
8
8.1 8.2 8.3
89
89 96 112
9
9.1 9.2 9.3 9.4
113
113 113 121 125
10
10.1 10.2
XML-Dokumentation
XML-Kommentare Zusammenfassung
127
127 134
11
Ausblick Stichwortverzeichnis
135 137
Sandini Bib
Essentials
.NET
Einfhrung
Vorwort
Thema dieses Bandes sind die XML-Basisklassen des .NET-Frameworks und ihre Verwendung sowie die Rolle von XML als Basisinfrastruktur innerhalb der .NET-Umgebung. XML ist bereits seit einigen Jahren dabei, sich zur neuen lingua franca innerhalb der IT-Welt zu entwickeln und auch Microsoft setzt im Rahmen der .NET Initiative auf XML. Es gibt wohl kaum einen Bereich innerhalb des .NET-Frameworks, in dem XML keine Rolle spielt. Als universelles Austausch- und Speicherformat wird es fr Konfigurationsdateien, ADO.NET, die Objektserialisierung, Schemas und XSLT bis hin zu SOAP und Web Services als sprachneutrales Format benutzt. Als Entwickler haben Sie kompletten Zugriff auf eine Reihe von hochoptimierten und vollstndigen Klassen, die nahezu jede Anforderung abdecken und ber den Funktionsumfang der alten XML Core Services der COM-Welt (MSXML) weit hinausgehen. Mit nur wenigen Zeilen an Code sind Sie in der Lage, Daten zu transformieren, XML-Strukturen aufzubauen oder zu validieren und mit ADO.NET sogar beliebige XML-Dateien entweder als relationales DataSet oder als XML-Baumstruktur zu behandeln.
Voraussetzungen
Bentigte Software
Zum Nachvollziehen der Beispiele in diesem Buch bentigen Sie einen Rechner mit Windows 2000 oder Windows XP, Visual Studio .NET oder das .NET-Framework SDK. Die Beispiele zu diesem Buch finden Sie zum Download auf der Website fr diese Buchreihe, die unter dem URL http://www.dotnet-essentials.de erreichbar ist. Dieses Buch geht davon aus, dass Sie zumindest das .NET-Framework und die Kommandozeilen-Tools installiert haben. Sie bentigen nicht unbedingt Visual Studio .NET, obwohl Sie im Kapitel ber XML-Validierung und XMLDokumentation sicher davon profitieren, da die grafische Oberflche doch einige Aufgaben erleichtert. Aber auch diese Kapitel enthalten Hinweise, wie Sie ohne das Visual Studio .NET zurechtkommen.
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Einfhrung
Vorkenntnisse
Die Zielgruppe dieser Buchreihe sind Entwickler mit Programmiererfahrung, die sich bereits erfolgreich mit den Grundlagen von .NET und Visual Studio vertraut gemacht haben. Sie finden in diesen Bnden praktische Beispiele und kompakte Informationen ohne die endlose Wiederholung von Grundlagen. Der Autor geht davon aus, dass Sie C# beherrschen bzw. Code, der in C# geschrieben wurde, lesen knnen und mit der objektorientierten Programmierung vertraut sind. Aus Platzgrnden sind viele Listings nicht komplett abgedruckt, sondern zeigen lediglich den Code einer (meist statischen) Methode ohne die Klassendefinition und die using-Anweisungen drumherum, da Sie sicher in der Lage sind, diese zu ergnzen. Wo es sinnvoll erschien oder bestimmte zustzliche Namespaces eingebunden wurden, wurden komplette Listings abgedruckt. Die Quellcodes der Downloads sind natrlich alle vollstndig.
Typografie
Normaler Flietext wird mit dieser Schriftart dargestellt. Falls innerhalb eines Textabsatzes einzelne Schlsselwrter oder Klassen- bzw. Variablennamen vorkommen, werden diese als Klassenname hervorgehoben.
Listings im Text besitzen diese Schriftart und wurden nach Mglichkeit so umbrochen, dass die Struktur trotz der geringen Spaltenbreite erhalten bleibt. Einzelne Listingszeilen erhalten diese Formatierung
Auswahlen in einem MENNAMEN oder als DIALOGOPTION werden ebenfalls besonders gekennzeichnet. Alle Dateinamen, URLs oder Pfadangaben sind wie hier gezeigt hervorgehoben.
Sandini Bib
Essentials
.NET
XML-Basics
1.1 XML-Terminologie
Knoten, Elemente, Tags und Attribute
Eine XML-Struktur (Struktur deshalb, da XML nicht notwendigerweise immer in einer Datei vorliegen muss, beispielsweise als MemoryStream) ist eine baumfrmige Struktur. Dieser Baum besteht aus einzelnen Knoten oder Elementen, die in textueller Form durch entsprechende Tags dargestellt werden. Ein Element kann einen reinen Textinhalt oder Unterelemente (oder Kindknoten) besitzen, auch ein gemischter Inhalt aus Text und Unterelementen ist mglich. Je nach Programmiermodell (Streamingzugriff ber XmlReader oder DOM-Zugriff ber ein XmlDocument) wird diese XML-Struktur seriell gelesen und Element fr Element an die Anwendung weitergegeben oder die komplette Datei wird gelesen und die Baumstruktur im Speicher aufgebaut (wobei hier der Ressourcenbedarf dementsprechend gro werden kann). Ein Element kann entweder ein XML-Element, ein Kommentar, eine Verarbeitungsanweisung an den XML-Parser oder Leerraum sein. Elemente knnen Attribute enthalten, die allerdings in keiner bestimmten Reihenfolge vorliegen mssen (der XML-Standard erlaubt ausdrcklich eine wechselnde Attributreihenfolge bei gleichen Elementen) und die daher in den XML-Klassen in einer ungeordneten Auflistung mitgefhrt werden. Attribute besitzen einen Namen und einen Wert. XML als Baum oder als Stream
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
1 XML-Basics
Kommentare
Ein Kommentar beginnt auch in XML mit der Zeichenfolge <!-- und endet mit der Zeichenfolge -->. Innerhalb eines Kommentars drfen keine doppelten Bindestriche vorkommen. Kommentare sind nicht innerhalb eines Element-Tags erlaubt und drfen auch nicht vor der ersten Verarbeitungsanweisung vorkommen, die eine XML-Datei als solche kennzeichnet (<?xml ...?>, Details s.u.). Eine Verarbeitungsanweisung (processing instruction) ist kein Element, sondern eine Anweisung an den XML-Parser bzw. die Anwendung, eine bestimmte Aktion auszufhren oder eine Kennzeichnung fr bestimmte Eigenschaften des Dokumentes. Diese beginnen immer mit der Zeichenkette <? und enden mit ?>. Soll ein Abschnitt oder Elementinhalt als regulrer Text aufgefasst werden, ohne dass der XML-Parser versucht, darin Markup zu erkennen, kann dieser Abschnitt als CDATA-Sektion (CDATA steht fr character data) geschrieben werden. Dazu wird folgendes Konstrukt verwendet:
<![CDATA[ Hier kann dies & das stehen <grins>, ohne dass der Parser ber diese Zeichen stolpert <sic!> ]]> Listing 1.1: Ein CDATA-Abschnitt
CDATA
Entities
Sonderzeichen bzw. Entitten beginnen in XML immer mit einem kaufmnnischen Und-Zeichen (&) und enden mit einem Semikolon (;). Folgende Entities sind bereits vordefiniert: Entity
& < > " ' � �
Bedeutung
Das &-Zeichen Das <-Zeichen Das >-Zeichen Das "-Zeichen Das '-Zeichen Das Zeichen mit dem Code 00 Das Zeichen mit dem hexadezimalen Code 00
Elemente
Elemente sind der ganze Rest, also ein ffnendes und ein schlieendes Tag, dazwischen entweder weitere Elemente oder ein Textinhalt. Auch ein gemischter Inhalt aus Textzeichen, Unterelementen oder z.B. CDATA ist mglich. Alternativ zu der Konstruktion <element></element> kann ein Element ohne Inhalt auch als <element /> abgekrzt werden.
10
Sandini Bib
Namensrume
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Es wird strikt zwischen Gro- und Kleinschreibung unterschieden, d.h. ein Tag <Buch> ist ein anderes Tag als <buch>. Jedes geffnete Tag muss auch wieder geschlossen werden. Attributwerte mssen grundstzlich in Anfhrungszeichen eingeschlossen werden, die Reihenfolge der Attribute in einem Element ist nicht definiert. Ohne ein Schema sind nur CDATA-Attributwerte erlaubt. Es sind keine isolierten Auszeichnungszeichen (wie <, >) erlaubt, diese mssen als Entitten angegeben werden, z.B. > als >. Tags mssen korrekt geschachtelt werden, d.h. es sind keine verschrnkten Schachtelungen erlaubt. Zu Beginn einer XML-Datei steht die Verarbeitungsanweisung <?xml?> mit einer Versionsangabe (obligatorisch) und einer Zeichencodierung (optional), z.B. <?xml version="1.0"?>.
Eine XML-Struktur oder -datei, die diese Bedingungen erfllt, wird als wohlgeformte XML-Datei bezeichnet. Eine gltige XML-Datei liegt dann vor, wenn der Inhalt dieser Datei anhand einer Grammatik validiert werden kann (beispielsweise ber eine DTD oder ein XSD-Schema).
1.2 Namensrume
Das Problem der Namenskonflikte ist so alt wie die Softwareentwicklung selbst. Stellen Sie sich vor, Sie entwickeln ein Kalenderprogramm mit Datumsberechnungen. Natrlich nennen Sie diese Klasse Datum. In einem Nachbarteam arbeitet ein Kollege ebenfalls an einer Klasse fr Datumsberechnung, allerdings fr den Kalender der Inkas. Auch er nennt seine Klasse Datum. In einem System ohne Namespaces htten Sie nun ein Problem. Mit dem .NET-Framework und den Namensrumen erhalten Sie zwei Vorteile: Zum einen besitzen Sie damit eine weitere Mglichkeit, logisch zusammengehrige Klassen in einem Namensraum zu sammeln. Zum anderen vermeiden Sie damit die Konflikte bei der Namensgebung von Klassen und mssen sich nicht irgendwelche obskuren Prfixe aus Vorname und Blutgruppe des Entwicklers fr die
11
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
1 XML-Basics
Benennung von Klassen ausdenken. Wenn Sie sich jetzt fragen, wo denn dabei das Problem liegt, arbeiten Sie einfach mal ein Jahr lang in einem Programmierteam mit 20 Entwicklern. Namensrume gibt es auch woanders Ein anderes Beispiel sind Internet-Domains. Ein Domainname wie TollesProdukt ist nur einmal vorhanden. Glcklicherweise existiert fr das Domain Name System eine auf Namensrumen basierende Lsung, die sogenannten Toplevel-Domains. Unterhalb von z.B. .com kann es die Domain geben, genauso aber unterhalb von .net und beispielsweise .de, damit haben dann immerhin drei Firmen die Mglichkeit, sich um diesen Namen zu streiten. Bei DNS wird der Namensraumkennzeichner als Postfix an den Domainnamen angehngt, da Domainnamen von rechts nach links gelesen werden, um in der Hierarchie abzusteigen.
XML-Namensrume
Auch bei XML-Namensrumen existiert ein Prfix-Kennzeichner, der vor dem eigentlich Elementnamen geschrieben wird und durch einen Doppelpunkt vom Elementnamen getrennt wird. Der eigentliche Namensraum selbst wird durch einen URI angegeben und bei der Definition mit diesem Prfix verknft. URI/URN: siehe RFC2396
<dotnet:buch xmlns:dotnet="urn:dotnet-books-aw">
Die obige Zeile zeigt die Definition eines Namensraumes und die Verwendung des entsprechenden Prfix fr das Element. Weitere Details, auch die Verwendung von XML-Namensrumen im Programmcode, finden Sie im Kapitel ber die Untersttzung von Namensrumen.
.NET-Namensrume
Auch ein komplexes Produkt wie das .NET-Framework kommt nicht ohne einen Mechanismus zur Vermeidung von Namenskonflikten aus. So ist es ohne weiteres mglich, zwei Klassen mit dem Name Error zu definieren, solange sich diese beiden Klassen in verschiedenen Namensrumen befinden. Auch in .NET wird der Namensraum (im Gegensatz beispielsweise zum Internet Domain Name System) vor dem Namen der Klasse angegeben, die einzelnen Elemente werden hier durch einen Dezimalpunkt getrennt und Namensrume sind im Gegensatz zu XML hierarchisch ber mehrere Ebenen schachtelbar. Achten Sie also darauf, XML-Namensrume und .NET-Namensrume fr Klassen nicht zu verwechseln.
12
Sandini Bib
Die .NET-Namensrume
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
13
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
1 XML-Basics
XML 1.0 http://www.w3.org/TR/1998/REC-xml-19980210 (einschlielich DTD-Untersttzung) XML-Namespaces http://www.w3.org/TR/REC-xml-names/ (sowohl Streamebene als auch DOM) XSD-Schemas http://www.w3.org/2001/XMLSchema XPath-Ausdrcke http://www.w3.org/TR/xpath XSLT-Transformationen http://www.w3.org/TR/xslt DOM Level 1 Core http://www.w3.org/TR/REC-DOM-Level-1/ DOM Level 2 Core http://www.w3.org/TR/DOM-Level-2/
14
Sandini Bib
Essentials
.NET
Die Basis fr die XML-Infrastruktur in .NET bilden unter anderem die beiden abstrakten Klassen XmlReader und XmlWriter. Diese beiden Klassen definieren den grundlegenden Leistungsumfang fr alle abgeleiteten Klassen.
15
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
XmlReader / XmlTextReader
Der einfachste Ansatz ist das Einlesen eines XML-Dokuments von einem URL oder einem Dateinamen .
// einlesen einer XML-Datei public void ReadXmlDoc(string docurl) { XmlTextReader rdr = new XmlTextReader(docurl); while (rdr.Read()) { // behandlung des aktuellen knotens } rdr.Close(); } Listing 2.1: Die einfachste Art, eine XML-Datei zu lesen
Innerhalb der while-Schleife kann nun der aktuell gelesene Knoten der Datei untersucht und entsprechend verarbeitet werden.
Name
Attribute CDATA
Beschreibung
Ein Attribut, z.B. units="Celsius" Ein CDATA-Bereich, der Text enthlt, der sonst als XML-Auszeichnung erkannt wrde, z.B. <![CDATA[ <hi> ]]> Ein Kommentar, z.B. <!-- my comment --> Das Dokumentenobjekt, welches die Wurzel des XMLBaums darstellt. Ein XML-Fragement beinhaltet einen Knoten oder einen Teilbaum, nicht notwendigerweise in einem eigenen Dokument. Der Dokument-Typ, z.B. <!DOCTYPE ...> Ein einzelnes XML-Element, z.B. <temp> Ein schlieendes Tag fr ein Element, z.B. </temp>
16
Sandini Bib
Lesen von XML-Daten
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Name
EndEntity Entity EntityReference None Notation ProcessingInstruction SignificantWhitespace Text Whitespace XmlDeclaration
Beschreibung
Wird als Ergebnis einer Entity-Auflsung mit ResolveEntity zurckgeliefert und markiert das Ende eines Entity. Die Deklaration eines XML-Entity, z.B. <!ENTITY ...> Die Referenz auf ein Entity, z.B. ä Wird geliefert, wenn noch nie die Methode Read aufgerufen wurde. Ein Notationseintrag in der DTD, z.B. <!NOTATION ...> Eine Verarbeitungsanweisung, z.B. <?xml version="1.0"?> Leerraum, der beachtet werden soll, wenn z.B. die Option xml:space="preserve" verwendet wurde. Der Textinhalt eines XML-Knotens Leerraum zwischen Auszeichnungsknoten Die XML-Deklaration selbst, z.B. <?xml version='1.0'?>; diese Anweisung muss der erste Knoten im Dokument sein.
Knotentypen unterscheiden
Fr die nachfolgende kleine XML-Datei, die in den nchsten Beispielen benutzt wird, soll nun jeweils der Knotentyp sowie der Name des Elements ausgegeben werden.
<?xml version="1.0"?> <weatherdata> <station> <location>Algeirs</location> <weather>overcast</weather> <temp units="Celsius">11</temp> <humidity>93%</humidity> <wind>E</wind> <windspeed>5</windspeed> <airpressure>1028</airpressure> <airtrend>rising</airtrend> </station> <station> <location>Athens</location> <weather>mostly cloudy</weather> <temp units="Celsius">16</temp> <humidity>77%</humidity> <wind>SW</wind> <windspeed>2</windspeed> <airpressure>1024</airpressure>
17
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Da sich der Leerraum (white space) schlecht anzeigen lsst, erfolgt die Ausgabe hier ber die Klasse Convert als Hexdump der Zeichencodes.
// neue methode ReadXmlDoc mit Knotenbehandlung using System; using System.XML; using System.Text; namespace XmlReader { class clsReaderClass { XmlTextReader rdr; public clsReaderClass(string docurl) { rdr = new XmlTextReader(docurl); } public void ReadXmlDoc() { while (rdr.Read()) { // den typ des knotens als string ausgeben Console.Write(rdr.NodeType); // abhngig vom typ ausgabe bauen switch(rdr.NodeType) { // ein element: name ausgeben case XmlNodeType.Element: Console.Write(" <" + rdr.Name + ">"); break; // schliessendes tag: / + name case XmlNodeType.EndElement: Console.Write(" </" + rdr.Name + ">"); break; // textinhalt: achtung! value statt name! case XmlNodeType.Text: Console.Write(" " + rdr.Value); break;
18
Sandini Bib
Lesen von XML-Daten
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// whitespace: zeichen als hexdump ausgeben case XmlNodeType.SignificantWhitespace: case XmlNodeType.Whitespace: for(int i = 0; i < rdr.Value.Length; i++) { int cv = Convert.ToUInt16(rdr.Value[i]); Console.Write(" {0:X2}", cv); } break; } Console.WriteLine(); } rdr.Close(); } // // Die Testklasse fr clsReaderClass // class TestClass { static void Main(string[] args) { clsReaderClass rc; rc = new clsReaderClass("miniwetter.xml"); rc.ReadXmlDoc(); } } } Listing 2.3: Unterscheidung der einzelnen Knotentypen
Hier die Ausgabe des Programms bis zum Ende des ersten stationKnotens:
XmlDeclaration Whitespace 0D 0A Element <weatherdata> Whitespace 0D 0A 09 Element <station> Whitespace 0D 0A 09 09 Element <location> Text Algeirs EndElement </location> Whitespace 0D 0A 09 09 Element <weather> Text overcast EndElement </weather> Whitespace 0D 0A 09 09 Element <temp>
19
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Text 11 EndElement </temp> Whitespace 0D 0A 09 09 Element <humidity> Text 93% EndElement </humidity> Whitespace 0D 0A 09 09 Element <wind> Text E EndElement </wind> Whitespace 0D 0A 09 09 Element <windspeed> Text 5 EndElement </windspeed> Whitespace 0D 0A 09 09 Element <airpressure> Text 1028 EndElement </airpressure> Whitespace 0D 0A 09 09 Element <airtrend> Text rising EndElement </airtrend> Whitespace 0D 0A 09 EndElement </station> Listing 2.4: Die Ausgabe der einzelnen Knoten
20
Sandini Bib
Schreiben von XML-Dateien
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
21
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
xtw.Close(); Console.WriteLine("Datei geschrieben."); } Listing 2.6: Schreiben von XML, die erste Version
Wie Sie aus dem Listing erkennen, existiert zum Schreiben von Elementen eine Methode WriteElementString, die Starttag, Inhalt und Endtag in einem Aufruf schreibt. Soll das Element jedoch Unterelemente oder Attribute enthalten, dann benutzen Sie besser die Methoden WriteStartElement und WriteEndElement, mit denen Sie die einzelnen Elemente gezielt beginnen und beenden knnen. Die Ausgabe des Programms in der Datei c:\tmp\ausgabe.xml sieht dann so aus:
<buecher><titel>Von Windows verweht ...</titel><preis waehrung="EUR">14.55</preis></buecher> Listing 2.7: Inhalt der erzeugten Datei
Hier sind noch einige Sachen zu verbessern. Zuerst ist dies keine gltige XML-Datei, noch nicht mal eine wohlgeformte, da die Verarbeitungsanweisung <?xml?> fehlt. Auerdem wre eine fr den (menschlichen) Entwickler etwas bessere Lesbarkeit recht schn. Diese beiden Punkte erreichen Sie durch ein paar nderungen im Code. Zuerst werden die beiden Methoden WriteStartDocument und WriteEndDocument integriert, die fr einen sauberen Rahmen um die XML-Struktur sorgen. Danach wird die Formatierung noch umgestellt. Hier die nderungen im Code:
public static void DemoXmlTextWriter() { // instanz erzeugen XmlTextWriter xtw = new XmlTextWriter(@"c:\tmp\ausgabe.xml", null); // formatierung einstellen // pro ebene 1 tab eingerckt xtw.Indentation = 1; xtw.IndentChar = '\t'; xtw.Formatting = Formatting.Indented; // inhalte schreiben xtw.WriteStartDocument(); xtw.WriteStartElement("buecher"); xtw.WriteElementString("titel", "Von Windows verweht ..."); xtw.WriteStartElement("preis"); xtw.WriteAttributeString("waehrung","EUR");
22
Sandini Bib
Schreiben von XML-Dateien
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
xtw.WriteString("14.55"); xtw.WriteEndElement(); xtw.WriteEndElement(); xtw.WriteEndDocument(); // writer schliessen xtw.Close(); Console.WriteLine("Datei geschrieben."); } Listing 2.8: Ausgabe mit XML-PI und Formatierung
Jetzt findet sich in der Ausgabe auch eine wohlgeformte XML-Struktur mit einer lesbaren Formatierung:
<?xml version="1.0"?> <buecher> <titel>Von Windows verweht ...</titel> <preis waehrung="EUR">14.55</preis> </buecher> Listing 2.9: Inhalte der Ausgabedatei
Nachdem es im Gegensatz zu beispielsweise HTML bei XML immer ein schlieendes Tag geben muss, werden Elemente ohne Inhalt in der Notation <elementname /> geschrieben. Viele Programme kommen damit aber nicht zurecht (vor allem ltere Browser), daher kann anstelle der Methode WriteEndElement die Methode WriteFullEndElement benutzt werden, die eine Ausgabe in der Form <elementname> </elementname> erzeugt. Neben der Methode WriteString zum Schreiben von Textinhalten existieren noch Methoden zum Schreiben von Binrdaten in BinHex- oder Base64-Notation, als CDATA-Bereich oder als Entity-Referenz fr Unicode-Zeichen. Alle diese Methoden folgenden aber dem gleichen Prinzip, so dass ein eigenstndiges Beispiel fr jede dieser Methoden hier nicht notwendig ist.
23
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
umgerechnet und ein evtl. vorhandenes Attribut Whrung ebenfalls korrekt umgestellt.
// umwandeln von xml-dateien per streaming-zugriff public static void DemoModifyXml(string inURL, string outURL) { // die reader und writer XmlTextReader rdr = new XmlTextReader(inURL); XmlTextWriter wrt = new XmlTextWriter(outURL, null); // ausgabe einruecken wrt.Formatting = Formatting.Indented; wrt.Indentation = 4; wrt.IndentChar = (char)32; // marker fuer preis-element bool bPreistag = false; // dokumenten-start-pi schreiben wrt.WriteStartDocument(); // alle knoten lesen while (rdr.Read()) { // abhngig vom typ ausgabe bauen switch(rdr.NodeType) { // element, auf "preis" testen case XmlNodeType.Element: bPreistag = (rdr.Name == "preis"); if(bPreistag) Console.WriteLine("{0} gefunden!", rdr.Name); wrt.WriteStartElement(rdr.Name); // attribute mit kopieren if(rdr.HasAttributes) { for(int i = 0;i < rdr.AttributeCount;i++) { rdr.MoveToAttribute(i); // waehrung ist jetzt EUR // also eintragen if(rdr.Name == "waehrung") wrt.WriteAttributeString(rdr.Name,"EUR"); else wrt.WriteAttributeString(rdr.Name,rdr.Value); } } break;
24
Sandini Bib
Schreiben von XML-Dateien
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// schliessendes tag: / + name case XmlNodeType.EndElement: if(rdr.Name == "preis" && bPreistag) { bPreistag = false; Console.WriteLine("/{0} gefunden!", rdr.Name); } wrt.WriteEndElement(); break; // textinhalt: achtung! value statt name! case XmlNodeType.Text: if(bPreistag) { decimal betrag = decimal.Parse(rdr.Value); betrag = betrag / 1.955830m; Console.WriteLine("Konvertiert!"); wrt.WriteString(betrag.ToString("F2")); } else wrt.WriteString(rdr.Value); break; } } rdr.Close(); wrt.WriteEndDocument(); wrt.Close(); } Listing 2.10: XML-Konvertierung manuell
Hier die beiden Dateien, zuerst die Eingabe-, dann die Ausgabedatei nach der Konvertierung:
<?xml version="1.0"?> <buecher> <buch> <titel>Von Windows verweht ...</titel> <preis waehrung="DEM">29,90</preis> </buch> <buch> <titel>Alice im Windowsland</titel> <preis waehrung="DEM">34,80</preis> </buch> </buecher> Listing 2.11: Die Eingabedatei
25
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
<?xml version="1.0"?> <buecher> <buch> <titel>Von Windows verweht ...</titel> <preis waehrung="EUR">15,29</preis> </buch> <buch> <titel>Alice im Windowsland</titel> <preis waehrung="EUR">17,79</preis> </buch> </buecher> Listing 2.12: Die Ausgabedatei
2.3 Zusammenfassung
Die Klassen XmlReader und XmlWriter sowie die davon abgeleiteten Klassen bieten einen ressourcenschonenden Zugriff auf XML-Dateien in Streaming-Form. Sie haben erfahren, wie sich feststellen lsst, welchen Knoten Sie gerade lesen, wie Elemente und Attribute geschrieben werden und wie mit Hilfe dieser Klassen auf einfache Art und Weise kleinere nderungen in XML-Dateien durchgefhrt werden knnen. Dieser rein lesend bzw. schreibende, nur vorwrtsgerichtete Zugriff reicht aber nicht aus, um alle Szenarien abzudecken. Fr komplexere nderungen oder die Navigation innerhalb der XML-Struktur reicht dieser Ansatz nicht mehr aus. Daher erfahren Sie im nchsten Kapitel, wie Sie den Zugriff ber das Document Object Model realisieren. Mit dieser Schnittstelle knnen Sie jeden Knoten eines Dokuments einzeln nach Ihren Anforderungen anspringen und ndern.
26
Sandini Bib
Essentials
.NET
Einfhrung
Serialisierung bedeutet, vereinfacht ausgedrckt, das berleben der Objekte nach einem Programmende oder die Verpackung der Objekte fr den Transport ber Prozess- und Maschinengrenzen bei einem Remote-Aufruf. Fr OOP-Systeme, die Mechanismen fr solche Aktionen boten, wurde dies dadurch gewhrleistet, dass aktuelle Daten und Variableninhalte in eine Datei geschrieben wurden. Der Code lag in der ausfhrbaren Datei vor und nach dem erneuten Start wurde die Datendatei geffnet und der Entwickler hatte die Aufgabe, alle Daten wieder in die richtigen Strukturen zu laden. Innerhalb des .NET-Frameworks ist XML das Rckgrat fr die Serialisierung von Klasseninstanzen. Die fr die Nutzung dieser Funktionalitt bentigten Namensrume des .NET-Frameworks sind System.XML und System.XML.Serialization. Terminologie
Als Ziel fr die Serialisierung knnen Sie bei der Methode Serialize des XmlSerializer drei mgliche Ausgabetypen spezifizieren:
Einen XmlWriter oder einen Nachfahren Einen Stream oder einen Nachfahren Einen TextWriter oder einen Nachfahren
27
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Nachdem es hier nur um das Herauschreiben der Instanzdaten geht, verwenden wir im Listing einen XmlWriter, da dieser als reine vorwrtsgerichtete Nur-Schreiben-Klasse den geringsten Overhead besitzt. Hier der Code, mit dem die Instanz serialisiert wird:
class TestClass { static void Main(string[] args) { XmlSerializer ser = new XmlSerializer(typeof(SimpleDemo)); XmlTextWriter tw = new XmlTextWriter("ausgabe.xml", null); SimpleDemo d = new SimpleDemo(); d.Kennzeichen = "LA-DY 2002"; d.KmStand = 45800; d.Verbrauch = 7.85; ser.Serialize(tw, d); tw.Close(); Console.WriteLine("Objekt serialisiert."); Console.Write("\nPress a key ...."); Console.ReadLine(); } } Listing 3.2: Serialisierung in eine XML-Datei
Nach dem erfolgreichen Durchlaufen des Codes liegt die Datei auf der Platte und Sie knnen sich deren Inhalt ansehen: Objekte als XML
<?xml version="1.0"?> <SimpleDemo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Kennzeichen>LA-DY 2002</Kennzeichen> <KmStand>45800</KmStand> <Verbrauch>7.85</Verbrauch> </SimpleDemo> Listing 3.3: Der Inhalt der XML-Ausgabedatei
Sie erkennen, dass das Wurzelelement den Namen der Klasse trgt und die einzelnen Elemente mit ihrer Bezeichnung den Namen der Felder entsprechen. Zustzlich werden die beiden Deklarationen der Namens-
28
Sandini Bib
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
rume fr XML-Schemas und XML-Schemainstanzen mit in das Wurzelelement aufgenommen (mehr zu Namensrumen erfahren Sie im Kapitel XML-Namensrume).
29
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Dieser Code produziert die in Abbildung 3.1 zu sehende Ausgabe und zeigt damit, dass so sehr leicht aus einer XML-Datei eine Objektinstanz erzeugt werden kann.
/// <remarks/> [System.XML.Serialization.XmlRootAttribute(Namespace="", IsNullable=true)] public class SimpleDemo { /// <remarks/> public string Kennzeichen; /// <remarks/> public int KmStand; /// <remarks/> public System.Double Verbrauch; } Listing 3.5: Automatisch aus einem Schema erzeugte Klasse
30
Sandini Bib
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Was aber passiert nun, wenn die Definition der Klasse nicht mit dem Aufbau der Datei bereinstimmt? Eine Mglichkeit wre es, nur Dateien anzunehmen, deren Aufbau genau der Klasse entspricht, indem fr die Klasse ein Schema erstellt und das Dokument damit validiert wird. Ein Beispiel dafr finden Sie im Kapitel ber die Validierung von XML-Dokumenten. Fr den anderen Fall wird die XML-Datei um ein zustzliches Element ergnzt, das in der Klasse nicht vorhanden ist. Ebenso wird die Klasse um ein weiteres Feld ergnzt, das in der XML-Datei nicht vorhanden ist.
<?xml version="1.0"?> <SimpleDemo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Kennzeichen>LA-DY 2002</Kennzeichen> <KmStand>45800</KmStand> <Leistung>108</Leistung> <Verbrauch>7.85</Verbrauch> </SimpleDemo> Listing 3.6: Die genderte XML-Datei // eine einfache demo-klasse public class SimpleDemo { public string Kennzeichen; public int KmStand; public double Verbrauch; public string Hersteller; } Listing 3.7: Die genderte Klasse mit dem neuen Feld
Bei der Ausfhrung des Programms erfolgt keine Fehlermeldung und die Ausgabe zeigt das Standardverhalten bei der Behandlung unbekannter Elemente in der XML-Datei:
31
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Elemente ignorieren
Zustzlich vorhandene Elemente werden also bei der Deserialisierung ignoriert, Felder in der Klasse ohne einen Inhalt in der XML-Datei werden von der Laufzeitumgebung bei der Erzeugung der Instanz initialisiert, bekommen dann aber keinen Wert aus der XML-Datei zugewiesen. Dieses Verhalten lsst sich, wie in den sptereren Abschnitten gezeigt, auch steuern und beinflussen.
Wird die genderte Klasse jetzt serialisiert, enthlt die XML-Datei die neuen Daten, wobei das mit dem Attribut [XmlIgnore] deklarierte Feld aus der Datei ausgelassen wird.
<?xml version="1.0"?> <root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" marke="Renault">
32
Sandini Bib
XML-Serialisierung im Detail
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<Kennzeichen>LA-DY 2002</Kennzeichen> <KmStand>45800</KmStand> </root> Listing 3.9: Der neue Inhalt der XML-Datei
Diese Klasse soll in der Lage sein, sich selbst zu serialisieren und ber eine statische Methode aus einer anzugebenden XML-Datei die Deserialisierung durchzufhren. Dies wird in die beiden Methoden SaveToXml und LoadFromXml eingepackt.
33
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
// serialisieren in eine xml-datei public void SaveToXml(string filename) { XmlSerializer ser = new XmlSerializer(typeof(DemoClass)); // einen xmlwriter einsetzen XmlTextWriter xml = new XmlTextWriter(filename, null); xml.Formatting = Formatting.Indented; xml.Indentation = 4; xml.IndentChar = (char)32; // klasseninsanz serialisieren ser.Serialize(xml, this); xml.Close(); } // deserialisieren aus einer xml-datei public static object LoadFromXml(string filename) { XmlSerializer ser = new XmlSerializer(typeof(DemoClass)); XmlTextReader rdr = new XmlTextReader(filename); if(ser.CanDeserialize(rdr)) return ser.Deserialize(rdr); else return null; } } // ende der klassendefinition Listing 3.11: Die beiden Wrapper fr die Serialisierung
Arrays serialisieren
Wird eine Instanz dieser Klasse ber den Aufruf von SaveToXml in eine XML-Datei geschrieben, wird eine ffentliche Eigenschaft als XML-Element mit dem Namen dieser Eigenschaft geschrieben (also analog zu einem normalen ffentlichen Feld). Das Array wird als XML-Element mit dem Namen des Arrays erstellt und die einzelnen Elemente dieses Arrays werden als Unterelemente, jeweils mit dem Namen des Datentyps, in die Datei geschrieben. Hier die erstellte XML-Datei:
<?xml version="1.0"?> <DemoClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <StrField>Hallo!!</StrField>
34
Sandini Bib
XML-Serialisierung im Detail
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<liste> <unsignedInt>1</unsignedInt> <unsignedInt>3</unsignedInt> <unsignedInt>5</unsignedInt> <unsignedInt>7</unsignedInt> <unsignedInt>11</unsignedInt> <unsignedInt>13</unsignedInt> <unsignedInt>17</unsignedInt> <unsignedInt>19</unsignedInt> </liste> <IndentLevel>4</IndentLevel> </DemoClass> Listing 3.12: Die serialisierte Instanz als XML-Datei
Fr die Deserialisierung muss ein parameterloser Konstruktor in der Klasse vorhanden sein (Sie haben sich vielleicht schon darber gewundert). Da der XmlSerializer aus den Daten der XML-Datei nicht erschlieen kann, welcher Konstruktor mit welchen Parametern aufzurufen ist, muss ein Konstruktor ohne Parameter vorhanden sein, der dann aufgerufen wird, um die Instanz zu erstellen. ber das Einlesen der restlichen XML-Elemente werden anschlieend die gleichlautenden ffentlichen Felder und Eigenschaften gesetzt.
Unknown-Ereignisse
35
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
<Klimaanlage /> </SimpleDemo> Listing 3.13: Der neue Inhalt der XML-Datei
36
Sandini Bib
Zusammenfassung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
3.2 Zusammenfassung
Serialisierung nach XML ist mit dem .NET-Framework auf einfache Art und Weise mglich, wobei Sie jederzeit in diesen Prozess eingreifen und die Serialisierung der Objektinstanzen genauer steuern knnen.
37
Sandini Bib
Sandini Bib
Essentials
.NET
XmlDocument
39
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Diese Methode ist mehrfach berladen. So knnen Sie anstelle des Dateinamens auch bei Bedarf einen URL oder eine Instanz eines XmlReaders angeben. LoadXml Falls die XML-Daten bereits in Form eines Strings vorliegen, kann dieser benutzt werden, um den Inhalt des Dokumentes festzulegen. Dafr existiert die Methode LoadXml, die als Parameter einen String erwartet:
// erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // stringinhalt fr XML, hier direkte zuweisung string s = "<person><vorname>Bob</vorname></person>"; // laden einer bestehenden Datei thedoc.LoadXml(s); // hier erfolgt die bearbeitung der datei Listing 4.2: Das Laden von bestehenden XML-Dokumenten
Somit sind wir in der Lage, Daten in XML in einem DOM-Objekt zu laden. In den nchsten Abschnitten dieses Kapitels wird es darum gehen, den Inhalt des Dokumentenbaums zu bearbeiten.
40
Sandini Bib
XML-Dokumente laden und lesen
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Um das <temp>-Element aus der ersten Stationsmeldung zu lesen, muss der zweite Kindknoten des Dokumentenknotens gelesen werden (der erste wre die Verarbeitungsanweisung <?xml version="1.0" ?>), davon den ersten Kindknoten (das Element <station>) und davon wiederum den dritten Knoten. Hier der entsprechende Codeausschnitt dazu:
static void SampleChildNodes() { XmlNode node; // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden einer bestehenden Datei thedoc.Load(@"h:\wetter.xml"); // das element <weatherdata> holen node = thedoc.ChildNodes[1]; // das element <temp> holen node = node.ChildNodes[0].ChildNodes[2]; // inhalt ausgeben Console.WriteLine("Inhalt: {0}", node.OuterXml); } Listing 4.4: Zugriff auf einen bestimmten Elementknoten per DOM
Die Ausgabe erfolgt dann ber die Eigenschaft OuterXml, so dass das Tag und die Attribute mit ausgegeben werden. Sind Sie nur am reinen Inhalt interessiert, knnen Sie statt dessen die Eigenschaft InnerText verwenden.
OuterXml
Sollte Ihnen der Programmablauf mehr wie ein Hpfen von Knoten zu Knoten vorkommen, bei dem sich die Reihenfolge der Elemente auf keinen Fall ndern darf, liegen Sie richtig. Im nchsten Kapitel werden Sie mit XPath-Abfragen eine wesentlich bessere Mglichkeit kennenlernen, ein Set aus einzelnen Knoten aus einem Dokumentenbaum zu extrahieren.
41
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
GetElementsByID
Zustzlich existiert noch eine Methode GetElementsByID, mit der alle Elemente mit einem bestimmten ID-Attribut zurckgeliefert werden. Dafr muss allerdings ein Schema oder eine DTD zur Validierung vorhanden sein, da in .NET im Document Object Model keine ID-Attribute vorgesehen sind, wenn diese nicht explizit ber eine DTD oder ein
42
Sandini Bib
XML-Dokumente laden und lesen
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Schema definiert werden. Mehr dazu im Kapitel ber die Validierung von XML-Dokumenten.
43
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
" Attribute.", n.Name); } } Listing 4.6: Ausgabe der Attribute und ihrer Werte
44
Sandini Bib
ndern von XML-Dokumenten per DOM
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
RemoveChild, RemoveAll
45
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
XmlDocument thedoc = new XmlDocument(); // laden einer bestehenden Datei thedoc.Load(@"h:\miniwetter.xml"); // hier erfolgt die bearbeitung ProcessElementDelete(thedoc); // genderte datei rausschreiben thedoc.Save("neuwetter.xml"); } Listing 4.8: Entfernen von Elementen aus der DOM-Struktur
Feststellen des Dokumentes, das diesen Knoten besitzt. Dazu hat jeder Knoten eine Eigenschaft OwnerDocument. Aufrufen der Methode CreateAttribute der Dokumentklasse und bergeben von Name und eventuell Namensraumprfixen. Setzen des Wertes fr das Attribut. Hinzufgen des neuen Attributes an die Attribute-Auflistung des aktuellen Knoten.
Die beiden nachfolgenden Methoden zeigen einen rekursiven Durchlauf durch ein XML-Dokument, bei dem fr jeden Stationsknoten der Name der Station aus dem Unterknoten <location> gelesen und bei <station> als ID-Attribut eingetragen wird. Danach wird die neue Struktur unter einem anderen Namen gespeichert. Damit die Ausgabe leichter lesbar ist, wird hier eine Datei verwendet, die nur zwei Eintrge fr Wetterstationen besitzt und die den Namen miniwetter.xml trgt.
// diese methode wird fr jeden knoten aufgerufen static void ProcessElementChildren(XmlNode theNode) { Console.WriteLine("Processing <{0}> ....", theNode.Name); // id bei station eintragen
46
Sandini Bib
ndern von XML-Dokumenten per DOM
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
if(theNode.LocalName == "location") { // neues attribut ueber dokument erzeugen XmlAttribute attr = theNode.OwnerDocument.CreateAttribute("id"); // attributwert setzen auf den inhalt // des aktuellen knotens (location) attr.Value = theNode.InnerText; // an die auflistung der attribute anhngen theNode.ParentNode.Attributes.Append(attr); } // alle eventuellen unterknoten abarbeiten foreach(XmlNode n in theNode.ChildNodes) { if(n.HasChildNodes) ProcessElementChildren(n); } }
// hauptmethode static void SampleRecurseElements() { // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden einer bestehenden Datei thedoc.Load(@"h:\miniwetter.xml"); // hier erfolgt die bearbeitung ProcessElementChildren(thedoc); // genderte datei rausschreiben thedoc.Save("neuwetter.xml"); } Listing 4.9: ndern einer DOM-Struktur
Soll ein Attribut eines Elementes gelscht werden, geschieht dies auf sehr einfache Weise durch den Aufruf der Methode RemoveAttribute der Klasse XmlElement, mit der ein benanntes Attribut aus einem XMLElement gelscht werden kann. Da dieser Vorgang nicht sonderlich geheimnisvoll ist, sei an dieser Stelle auf ein weiteres Listing verzichtet. Eine andere Alternative ist die Nutzung der hilfreichen Methode
SetAttribute der Klasse XmlElement. Bitte beachten Sie, dass aus Grnden
RemoveAttribute
47
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
des Zeilenumbruchs die beiden Zeilen 05 und 06 getrennt wurden, im Code ist dies eine einzige Zeile.
01 if(theNode.LocalName == "station") 02 { 03 XmlElement elem = ((XmlElement)theNode); 04 elem.SetAttribute("id", 05 elem.GetElementsByTagName("location") 06 .Item(0).InnerText); 07 } Listing 4.10: Alternative Erzeugung von Attributen
Mit dieser Methode lsst sich auch der Inhalt eines bereits bestehenden Attributes wieder ndern.
4.4 Ereignisbehandlung
Die Klasse XmlDocument beinhaltet auch eine Reihe von Ereignissen, in die sich Ihr Code mit einer eigenen Ereignisbehandlungsroutine einhngen kann. Auf diese Weise kann nicht nur mitverfolgt werden, ob ein Knoten gendert, eingefgt oder gelscht wurde. ber einen zweiten Satz von Ereignissen, der vor der eigentlichen Aktion ausgelst wird, lsst sich die Durchfhrung der nderung sogar bei Bedarf abbrechen.
Ereignis
NodeChanged NodeChanging NodeInserted NodeInserting NodeRemoved NodeRemoving
Beschreibung
Tritt auf, wenn ein Knoten in der DOM-Struktur gendert wurde Tritt auf, bevor ein Knoten in der DOM-Struktur gendert wird (Auslsen einer Exception bricht die Aktion ab) Tritt auf, wenn ein Knoten in der DOM-Struktur eingefgt wurde Tritt auf, bevor ein Knoten in der DOM-Struktur eingefgt wird (Auslsen einer Exception bricht die Aktion ab) Tritt auf, wenn ein Knoten in der DOM-Struktur gelscht wurde Tritt auf, bevor ein Knoten in der DOM-Struktur gelscht wird (Auslsen einer Exception bricht die Aktion ab)
Um auf eines dieser Ereignisse zu reagieren, muss in der Klasse ein EventHandler programmiert und dem Delegate fr das Ereignis mitgeteilt werden. Das folgende Listing zeigt eine Klasse, die beim Lschen eines Knotens eine entsprechende Meldung ausgibt.
// klasse zur ereignisbehandlung class EventDemo
48
Sandini Bib
Ereignisbehandlung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
{ public void DemoActions() { XmlDocument thedoc = new XmlDocument(); thedoc.NodeRemoved += new XmlNodeChangedEventHandler(this.OnDelete); thedoc.Load(@"h:\miniwetter.xml"); try { thedoc.ChildNodes[1].ChildNodes[0].RemoveAll(); } catch (Exception e) { Console.WriteLine(e.Message); } thedoc.Save(Console.Out); Console.Write("Press a key ...."); Console.ReadLine(); } // knoten wurde gelscht public void OnDelete(Object src, XmlNodeChangedEventArgs args) { Console.Write("Lschereginis: <{0}> {1}", args.Node.Name, args.Action.ToString()); if (args.Node.Value != null) Console.WriteLine(" Wert = {0}", args.Node.Value); else Console.WriteLine(""); } } Listing 4.11: Abfangen von Lschereignissen im Dokument
Analog dazu funktioniert die Behandlung der NodeChanged- und Node Inserted-Ereignisse. Interessant ist aber die Mglichkeit, in diesen Prozess einzugreifen und bei Bedarf durch das Auslsen einer Exception die Aktion abzubrechen. Dazu dienen die Ereignisse, deren Namen jeweils auf ...ing enden und die vielleicht besser als Anforderung bezeichnet werden.
NodeChanged, NodeInserted
49
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Im folgenden Beispiel soll verhindert werden, dass fr eine Station der <location>-Knoten gelscht wird, alle anderen Unterknoten von <station> sollen gelscht werden knnen. Denken Sie daran, beim Lschen von Unterelementen in einer Schleife nicht mit foreach zu arbeiten, da hier das Set der zu durchlaufenden Elemente nur einmal berechnet wird und dann nicht mehr gendert werden darf. Zustzlich muss die Schleife von hinten nach vorne durchlaufen werden, damit nach dem Lschen wegfallende Elemente die Reihenfolge nicht ducheinander bringen. Deshalb die auf den ersten Blick etwas merkwrdig aussehende Schleifenkonstruktion. Wollen Sie in einem Rutsch wirklich alle Unterknoten eines Knotens entfernen, benutzen Sie dazu am besten die Methode RemoveAll der Klasse XmlNode. Diese stellt eine ntzliche Erweiterung des DOM-Standards durch Microsoft dar.
// beispiel zum abfangen einer lschaktion im DOM class EventDemo { public void DemoActions() { XmlNode node; XmlDocument thedoc = new XmlDocument(); // eintragen der eventhandler thedoc.NodeRemoved += new XmlNodeChangedEventHandler(this.OnDelete); thedoc.NodeRemoving += new XmlNodeChangedEventHandler(this.OnDeleteReq); thedoc.Load(@"h:\miniwetter.xml"); // die erste station in der wetterdatei node = thedoc.ChildNodes[1].ChildNodes[0]; // alle unterelemente lschen for(int i = node.ChildNodes.Count-1; i >= 0; i--) { try { node.RemoveChild(node.ChildNodes[i]); } catch (Exception e) { Console.WriteLine(e.Message); } }
50
Sandini Bib
Ereignisbehandlung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// den inhalt der XML-Strukur zur // kontrolle ausgeben thedoc.Save(Console.Out); Console.Write("Press a key ...."); Console.ReadLine(); } // ab hier die ereignisbehandlungsroutinen // knoten wurde gelscht public void OnDelete(Object src, XmlNodeChangedEventArgs args) { Console.Write("Lschereignis: <{0}> {1}", args.Node.Name, args.Action.ToString()); if (args.Node.Value != null) Console.WriteLine(" Wert = {0}", args.Node.Value); else Console.WriteLine(""); } // knoten soll gelscht werden, extracheck public void OnDeleteReq(Object src, XmlNodeChangedEventArgs args) { Console.Write("Lschanfrage: <{0}> {1}", args.Node.Name, args.Action.ToString()); if (args.Node.Value != null) Console.WriteLine(" Wert = {0}", args.Node.Value); else Console.WriteLine(""); if(args.Node.LocalName == "location") { throw new XmlException("Location darf nicht " + "gelscht werden!", null); } } } Listing 4.12: Abbrechen von nderungen im DOM
Nach der Exception befindet sich die XML-Struktur in der XmlDocumentInstanz in einem stabilen Zustand wie vor der Aktion. Wre im Code statt der Schleife durch die Unterelemente die Methode RemoveAll aufgerufen worden, htte die Exception beim Element <location> dafr gesorgt, dass gar keines der Unterelemente gelscht worden wre, da
51
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
dann der komplette Aufruf von RemoveAll zurckgerollt worden wre. Dies lsst sich bei Bedarf gezielt dafr einsetzen, komplette Knoten zu schtzen, aber nur ein Unterelement zu prfen.
4.5 Zusammenfassung
In diesem Kapitel haben Sie eine bersicht ber die verschiedenen Klassen und Methoden des DOM im .NET-Framework erhalten. Vergleicht man die Anforderungen und Mglichkeiten mit denen im Kapitel ber die Streaming-Klassen XmlReader und XmlWriter, dann lsst sich auch einordnen, wann am besten welche Methode zum Einsatz kommt. Sollten Sie eine groe Anzahl von Dokumenten in einer Art Stapelbetrieb verarbeiten mssen oder bentigen Sie aus einem umfangreichen XML-Dokument nur eine kleine Anzahl von Elementen (z.B. um aus einer Liste von Teilen die Gewichte fr den Versand zu berechnen), dann ist der Streaming-Ansatz wesentlich ressourcenschonender. Sollten Sie aber die volle Kontrolle ber die XML-Struktur bentigen oder beim Aufbau im Speicher noch nicht die endgltige Reihenfolge der Elemente wissen (weil diese z.B. erst whrend der Laufzeit Ihres Programms erzeugt werden), dann ist es besser, mit dem DOM zu arbeiten, auch wenn dadurch der komplette DOM-Baum im Speicher aufgebaut wird.
52
Sandini Bib
Essentials
.NET
XPath-Abfragen
5.2 Grundlagen
XPath-Ausdrcke
In der einfachsten Form beschreibt eine XPath-Abfrage den durch Schrgstriche getrennten Weg in der hierarchischen XML-Struktur bis zum Zielknoten. So liefert der XPath-Ausdruck weatherdata/station/temp alle Knoten unterhalb von <station>, wobei dieses Element ein Unterknoten von <weatherdata> sein muss.
53
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
5 XPath-Abfragen
Die folgende Abbildung zeigt die Ausgabe, wenn fr jeden Knoten die Eigenschaft OuterXml ausgegeben wird.
Der |-Operator
XPath-Ausdrcke lassen sich mit Hilfe des Operators "|" (in der Bedeutung von oder) verbinden. So liefert der Ausdruck /weatherdata/station/location | /weatherdata/station/temp beispielsweise einen Match fr entweder das <location>- oder das <temp>-Element. Da der XPath-Parser zuerst die Geschwisterknoten der gleichen Ebene durchsucht, erhalten Sie so auf einfachste Art eine Auflistung der Standorte mit der jeweiligen Temperatur. Hier das Listing und die Ausgabe des Programms dazu:
// kombinieren von XPath-Abfragen static void SampleSelectOr() { // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden der xml-datei thedoc.Load(@"h:\miniwetter.xml"); // abfragen per XPath XmlNodeList nl = thedoc.SelectNodes( "/weatherdata/station/location | " + /weatherdata/station/temp"); foreach(XmlNode n in nl) { Console.WriteLine(n.OuterXml); } } Listing 5.1: Kombination zweiter XPath-Ausdrcke
54
Sandini Bib
Grundlagen
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Der Kontextknoten
Wird eine XPath-Abfrage beispielsweise nach dem Knoten <name> durchgefhrt (name), hngt es davon ab, von wo die Suche gestartet wird. Ein Beginn an der Wurzel des Dokumentes liefert unter Umstnden ein komplett anderes Ergebnis als der Beginn an einem Unterknoten innerhalb der XML-Struktur. Daher verwendet XPath das Konzept eines sogenannten Kontextknotens. Dieser Kontextknoten ist der aktuelle Knoten, an dem die Suche gestartet wird (bei der Verwendung der Methode SelectNodes beispielsweise der XmlNode, fr den die Methode aufgerufen wird). Die Abkrzung fr den Kontextknoten ist der . (punkt)
Achsen
Fr die Durchfhrung einer XPath-Abfrage kann eine bestimmte Richtung definiert werden, die sog. Achse. Auch in einem hierarchischen Dateisystem beispielsweise kann ber die Notation .. eine Ebene hher gewechselt werden, um nach oben zu suchen. Bei der normalen Angabe wie /weatherdata/station/location ist die Achse immer child, also jeweils ein Unterknoten. Dies ist die Default-Achse, muss daher auch nicht angegeben werden. Wird hingegen eine Achse angegen, trennt man diese vom Rest der Abfrage durch einen doppelten Doppelpunkt (::). Einige Achsen werden (wie child) sehr hufig bentigt und besitzen eine eigene Abkrzung. Die wichtigsten Achsen zeigt die nachfolgende Tabelle. Startpunkt ist immer der Kontextknoten. Achse
child self descendant descedant-or-self parent
Bedeutung
Default, ein Nachkomme des Kontextknotens Der Kontextknoten (Abkrzung .) Irgendein Nachkomme des Kontextknotens, also z.B. auch ein Nachkomme ber zwei oder drei Ebenen Wie oben, allerdings unter Einbeziehung des Kontextknotens (Abkrzung // ) Elternknoten des Kontextknotens (Abkrzung ..)
55
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
5 XPath-Abfragen
Achse
following preceding attribute
Bedeutung
Alle nach dem Kontextknoten folgenden Knoten Alle vor dem Kontextknoten vorhandenen Knoten Attribut des angegebenen Knotens (Abkrzung @)
Eine vollstndige Liste der mglichen Achsen finden Sie auf der XPathHomepage im Web unter dem URL www.w3.org/TR/xpath.html . Verweis auf Elternknoten mit .. Um beispielsweise alle <temp>-Elemente zu selektieren, egal zu welchem Elternknoten diese gehren, kann der Ausdruck //temp benutzt werden. Der Ausdruck //location/.. liefert alle Elternknoten (in diesem Falle <station>), die ein <location>-Element als Kindknoten besitzen. Somit sind sehr leicht Abfragen in verschiedenen Richtungen mglich, die durch die Auswahl des Kontextknotens noch zustzlich beeinflusst werden knnen. Fr eine noch leichtere Abfrage fehlen jetzt nur noch Mglichkeiten, einen Vergleich durchzufhren, um nur ein bestimmtes Subset von passenden Knoten auszuwhlen. Dies geschieht bei XPath mit Hilfe von so genannten Prdikaten.
Prdikate
Prdikate entsprechen in etwa der WHERE-Klausel bei einer SQL-Abfrage, da sie das zurckgelieferte Set von Knoten durch Bedingungen noch weiter filtern knnen. Diese Prdikate werden an der gewnschten Stelle hinter das jeweilige Hierarchieelement in eckigen Klammern angefgt. Klingt kompliziert, ist es aber nicht. Hier ein Beispiel: //station[location = "Athens"] liefert das <station>-Element, welches ein Unterlement <location> besitzt, das den Inhalt Athens besitzt. Prfung auf vorhandene Attribute Der Prdikatwert muss nicht unbedingt einen Vergleich enthalten. Wird nur ein Unterelement oder ein Attribut angegeben, dann wird auf das Vorhandensein dieses Elementes geprft. Der nachfolgende Ausdruck liefert in der XmlNodeList alle <location>-Knoten, die als Elternknoten ein <station>-Element besitzen, das wiederum ein Attribut "status" enthlt. /weatherdata/station[@status]/location Wird mehr als ein Prdikat angegeben, was durchaus zulssig ist, besitzt die Reihenfolge dieser Prdikate eine entscheidende Bedeutung. Betrachten wir dazu die beiden folgenden XPath-Ausdrcke: 1. /weatherdata/station[2][@status] 2. /weatherdata/station[@status][2]
56
Sandini Bib
Grundlagen
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Fr den Ausdruck Nr. 1 ist das Ergebnis der zweite <station>-Knoten unterhalb von <weatherdata>, falls dieser ber ein Attribut (wie Sie an der Abkrzung @ fr die Attribut-Achse sehen) mit dem Namen status verfgt. Die Knotenliste wre hier leer, da der zweite Knoten in unserer Beispieldatei wetter.xml (fr die Station in Amsterdam) nicht ber das entsprechende Attribut verfgt. Der Ausdruck Nr. 2 liefert dagegen zuerst die Liste der Stationen mit einem Attribut status und whlt anschlieend davon den zweiten Knoten aus. Im Falle der Beispieldatei enthlt die Ergebnismenge eine Ausgabe:
<station status="timeout"> <location>Bukarest</location> <weather>light rain</weather> <temp units="Celsius">10</temp> <humidity>49%</humidity> <wind>W</wind> <windspeed>3</windspeed> <airpressure>1013</airpressure> <airtrend>raising</airtrend> </station> Listing 5.2: Die Ergebnismenge der zweiten Abfrage
Zur Kombination von Ausdrcken innerhalb der Prdikate knnen Sie mit den drei booleschen Operatoren and, or und not arbeiten (case-sensitive) bzw. Teilausdrcke in Klammern gruppieren. Denken Sie bei den relationalen Operatoren daran, das Zeichen "<" durch "<" und ">" entsprechend durch ein ">" zu quoten, schlielich befinden wir uns innerhalb der XML-Grenzen. Mehr dazu und zu den weiteren Mglichkeiten der Prdikate finden Sie in der Online-Dokumentation von .NET oder auf den Webseiten des W3C. Als letzten Bestandteil der Einfhrung in die XPath-Sprache fehlen nun nur noch die Funktionen, mit deren Hilfe noch flexiblere Abfragen mglich sind.
Prdikat-Operatoren
Funktionen
Funktionen innerhalb von XPath-Ausdrcken knnen einen der vier folgenden Datentypen zurckliefern: Boolsche Werte (true oder false), Zahlenwerte, Zeichenketten oder eine Knotenmenge. Wenn eine Funktion einen anderen Datentyp als eine Knotenmenge liefert, knnen natrlich die nachfolgend besprochenen Methoden SelectNodes und SelectSingleNode nicht benutzt werden. Verwenden Sie dafr die Methoden des XPathNavigators, der weiter unten vorgestellt wird. Funktionstypen
57
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
5 XPath-Abfragen
Mit Hilfe dieser Funktionen ist es sehr einfach mglich, Code zu vermeiden und die Arbeit einfach in einen XPath-Ausdruck auszulagern. Damit Sie die folgenden Beispiele nachvollziehen knnen, sollten Sie zuerst die Abschnitte ber SelectNodes und den XPathNavigator lesen und dann hierher zurckblttern. Aus der Sicht des Autors erschien es an dieser Stelle sinnvoller, die XPath-Einfhrung nicht zu zerreien, sondern linear aufzubauen. Sobald eine Funktion kein Set von Knoten mehr liefert, sind die blichen Selektierungsmethoden (wie SelectNodes oder Select) nicht mehr anwendbar. Benutzen Sie statt dessen die Methode Evaluate der Klasse XPathNavigator, welche als Rckgabetyp object besitzt und dementsprechend per Unboxing oder Konvertierung gewandelt werden kann. Evaluate-Funktion Eine der einfachsten Funktionen ist count(<nodeset>), die einfach die Anzahl der auf den Ausdruck <nodeset> passenden Knoten liefert. Damit lsst sich die Anzahl der in der Beispieldatei enthaltenenen Stationsmeldungen mit einer einzigen Zeile Code bestimmen.
int nCount = (int)xnav.Evaluate("count(//station)"); Listing 5.3: Zhlen von Knoten mit XPath-Funktionen
Es existiert eine recht beachtliche Liste von ntzlichen Funktionen, wobei sich Microsoft hier an den XPath-Standard hlt. Anstatt diese Liste einfach zu wiederholen, sei auf die Online-Hilfe von Visual Studio.NET verwiesen, in der Sie unter dem Indexbegriff XPath, Funktionen die entsprechende Liste finden. Nachfolgend noch einige Beispiele, die ein paar der untersttzten Funktionen demonstrieren:
Ausgabe aller Temperaturknoten, aber nur der Textinhalt des Elements: /weatherdata/station/temp/text() Ausgabe aller Stationen mit "P": /weatherdata/station[ starts-with(location,"P")]/location Ausgabe der Luftfeuchtigkeit fr alle Stationen, die eine Temperatur von mehr als 10 melden: /weatherdata/station/temp[text() > 10]/../humidity Alle Stationsdaten mit steigendem Luftdruck und mehr als 10: /weatherdata/station[(temp > 10) and (airtrend = "rising")]
58
Sandini Bib
SelectNodes und SelectSingleNode
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
SelectNodes
Damit ist auf einfache Art und Weise nahezu ohne Programmieraufwand das Durchsuchen von XML-Strukturen nach bestimmten Kritierien mglich. Soll ein ganz bestimmter Knoten (z.B. anhand einer ID) gefunden werden, kann dazu die Methode SelectSingleNode benutzt werden. So lassen sich mit der folgende Klasse die kompletten XML-Elemente fr einen Standort (also das <station>-Element) abrufen, in dem der Name des Standortes eingegeben wird. Wird kein passender Knoten gefunden, liefert die Methode eine Null-Referenz, auf die gestestet werden kann. SelectSingleNode
59
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
5 XPath-Abfragen
Im Beispiel wird ber ein XPath-Prdikat (s.o. bei den Grundlagen) der Name des Standortes gesucht, aber das <station>-Element zurckgeliefert.
// suchen eines einzelnen xml-nodes // per SelectSingleNode static void SampleSelectSingleNode() { string location; // der gesuchte name string xpath; // der XPath-Ausdruck // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden der xml-datei thedoc.Load(@"h:\wetter.xml"); // abfrageschleife do { Console.Write("Standort eingeben : "); location = Console.ReadLine(); // bei leerer eingabe schleife verlassen if(location.Length == 0) break; // abfrage durchfhren xpath = "/weatherdata/station[location = \"" + location + "\"]" ; XmlNode node = thedoc.SelectSingleNode(xpath); // wenn objektreferenz, dann ergebnis ausgeben if( node != null) Console.WriteLine(node.OuterXml); else Console.WriteLine( "Ort nicht in Daten enthalten!"); } while(true); } Listing 5.5: Suchen eines einzelnen Knotens per XPath
60
Sandini Bib
Nutzung des XPathNavigators
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
XPathDocument
XPathNavigator
Der Konstruktor von XPathDocument ist mehrfach berladen, so dass Sie natrlich auch auf andere Art und Weise XML-Daten bergeben knnen. Sie knnen eine Instanz des Dokumentes entweder als Stream, als UNC-Pfad, TextReader oder XmlReader erzeugen.
Beschreibung
Prft, ob der aktuelle Knoten dem angegebenen XPath-Ausdruck entspricht. Kann zum Testen einer bestimmten Position verwendet werden. Springt an die Knotenposition, die den Kontext fr den angegebenen XPathNavigator bildet. Bewegt den Navigator zum angegebenen Attribut, wobei ein Namensraum angegeben werden kann.
MoveTo MoveToAttribute
61
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
5 XPath-Abfragen
Methode
MoveToFirst MoveToFirstAttribute MoveToFirstChild MoveToFirstNamespace MoveToId MoveToNamespace MoveToNext MoveToNextAttribute MoveToNextNamespace MoveToParent MoveToPrevious MoveToRoot
Beschreibung
Geht zum ersten Geschwisterknoten des aktuellen Knotens (der erste Knoten auf der gleichen Ebene). Springt zum ersten Attribut. Springt zum ersten Unterknoten des aktuellen Knotens. Bewegt den Navigator zum ersten Namensraumknoten des aktuellen Knotens. Springt zu dem Knoten, der ein ID-Attribut mit dem angegebenen Zeichenfolgenwert besitzt. Bewegt den Navigator zum Namensraumknoten mit dem angegebenen lokalen Namen. Geht zum nchsten Geschwisterknoten des aktuellen Knotens (nchster Knoten der aktuellen Ebene). Springt zum nchsten Attribut. Springt zum nchsten Namensraumknoten. Bewegt den Navigator zum Elternelement des aktuellen Knotens. Springt zum vorherigen Geschwisterknoten des aktuellen Knotens. Springt zum Wurzelknoten, zu dem der aktuelle Knoten gehrt.
62
Sandini Bib
Nutzung des XPathNavigators
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// erstellen der XPathNavigator-Instanz XPathNavigator xnav = thedoc.CreateNavigator(); XPathNodeIterator iter = xnav.Select("//location | //weather"); while(iter.MoveNext()) { Console.Write("Wetter in {0}: ", iter.Current.Value); iter.MoveNext(); Console.Write("{0}", iter.Current.Value); Console.WriteLine(); } } Listing 5.6: Durchlaufen eines Knotensets mit dem Iterator
Sie knnen fr den Iterator die gleichen Methoden wie fr den Navigator verwenden, da die Eigenschaft Current einen auf den aktuellen Knoten positionierten XPathNavigator zurckliefert. Allerdings knnen Sie diesen Navigator nicht aus dem gelieferten Trefferset herausbewegen. Sie knnen statt dessen diesen Navigator klonen (ber die Methode XPathNavigator.Clone, die einen auf den gleichen Knoten positionierten Klon des fr den Aufruf verwendeten Navgators liefert) und dann mit dem Klon aus dem Trefferset herausnavigieren, falls Sie dies bentigen.
Nochmal Evaluate
allerdings wesentlich mehr Arbeit ntig. Das Abfragen der passenden Tagnamen, die Addition der Werte usw. wurde alles im Code erledigt. Mit Hilfe der Evaluate-Methode verkrzt sich der Code radikal:
// berechnungen als xpath-ausdruck static void SampleXPathDocument() { // erzeugen des XML-Dokumentes
63
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
5 XPath-Abfragen
XPathDocument thedoc = new XPathDocument(@"h:\wetter.xml"); // erstellen der XPathNavigator-Instanz XPathNavigator xnav = thedoc.CreateNavigator(); string xpr = "sum(//temp/text()) div count(//temp)"; double avg = (double)xnav.Evaluate(xpr); Console.WriteLine("{0:F2}", avg); } Listing 5.7: Durchschnittsberechnung mit XPath und Evaluate
Liefert eine Auswertung eines XPath-Ausdrucks ein Set von Knoten, dann wird eine XPathNodeIterator-Instanz geliefert (s. voriger Abschnitt), mit der Sie dann die einzelnen Knoten der Ergebnismenge durchlaufen knnen.
64
Sandini Bib
Zusammenfassung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
XPathExpression xpr = xnav.Compile( "sum(//temp/text()) " + "div count(//temp)"); double avg = (double)xnav.Evaluate(xpr); Console.WriteLine("{0:F2}", avg); } Listing 5.8: Kompilieren von Ausdrcken steigert die Leistung.
5.5 Zusammenfassung
Die Mglichkeit, innerhalb des DOM-Modells mit der XPath-Untersttzung von .NET zu arbeiten, erleichtert die Arbeit erheblich. Viele vorher manuell zu codierende Arbeiten knnen so an die XPath-Engine abgegeben werden und das Durchsuchen von komplexen XML-Strukturen wird durch die mchtigen XPath-Ausdrcke sehr erleichtert. Im bernchsten Kapitel werden Sie erfahren, wie mit Hilfe dieser Ausdrcke die Transformation von XML-Daten gesteuert werden kann.
65
Sandini Bib
Sandini Bib
Essentials
.NET
XML-Namensrume
6.1 Einfhrung
Wozu berhaupt Namensrume, wird sich mancher Einsteiger in die XML-Programmierung fragen. Die Antwort ist einfach: wie in jedem Namenssystem zur Vermeidung von Namenskonflikten. Ebenso wie es in einem Dateisystem eine Datei text.txt nur dann zweimal geben kann, wenn sich diese in zwei Verzeichnissen befinden (und damit im Pfadnamen einen anderen "Prfix" besitzen), knnen Elementnamen ohne Probleme mehrfach verwendet werden, solange sie zwei verschiedenen Namensrumen angehren. Zur Kennzeichnung eines Namensraumes dient ein uniform resource identifier (Details dazu finden Sie im RFC2396, der unter dem URL http://www.ietf.org/rfc/rfc2396.txt zu finden ist), der eine eindeutige Identifikation des Namensraumes darstellt. Obwohl viele NamensraumURIs einem Web-URL hneln, handelt es sich dabei nicht um einen Link (trotzdem aktivieren viele Firmen unter einem URL-URI oft eine Hinweisseite in HTML, z.B. auch das W3C). Wie der Name schon ausdrckt, geht es hier nur um eine eindeutige Kennzeichnung und da ein Domainname nur einmal vergeben wird, ist eine URL-URI eben einfach eindeutig zu erstellen. Nachdem die Angabe des URI bei jedem Element dieses Namensraums zu viel Aufwand wre, existiert jeweils zugeordnet zu einem Namensraum ein Prfix, das durch einen Doppelpunkt vom Elementnamen (dem local name) getrennt wird. Innerhalb eines Elementes ist auch die mehrfache Angabe von Namensrumen mglich. Wie das XML-Fragment unten zeigt, lsst sich mit Hilfe von XMLNamensrumen ein Konflikt zwischen den beiden Elementen mit dem lokalen Namen titel auflsen. Ohne die entsprechenden Namensrume wren die beiden Elemente fr eine verarbeitende Anwendung auch nicht voneinander zu unterscheiden gewesen.
<bk:buch xmlns:bk="urn:buch-uri" xmlns:au="urn:autor-uri"> <bk:titel>Alice im Windowsland</bk:>titel> <au:autor> <au:titel>Prof. Dr.</au:titel> <au:name>Franz Testhuber</au:name> </au:autor> </bk:buch> Listing 6.1: Ein XML-Fragment mit Namensrumen
67
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
6 XML-Namensrume
NamensraumDeklaration
Auch bei der Definition eines XML-Schemas sind Namensrume wichtig, da fr ein Schema definiert wird, fr welchen Namensraum-URI das im Schema definierte Inhaltsmodell gelten soll. Hierfr dient das Attribut targetNamespace des <schema>-Elementes. Sehen wir uns dazu im Schema meteo.xsd die Definition des <schema>-Elements an:
<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:wx="urn:meteo-demo" targetNamespace="urn:meteo-demo"> Listing 6.2: Kopf des meteo-Schemas
Hier wird als Zielnamensraum der URI "urn:meteo-demo" verwendet. Gleichzeitig wird ein Prfix wx fr den gleichen Namensraum vereinbart, so dass alle Elemente ohne Prfix und solche mit dem Prfix wx als zu diesem Namensraum gehrig angesehen werden. Zustzlich wird der Namensraum mit dem URI http://www.w3.org/2001/XMLSchema und dem Prfix xsd deklariert. Dieser enthlt das Schema fr die XSD-Schemata. Auch hier sollten Sie sich an die beiden Konventionen xsd oder xs fr das Schema-Prfix halten, um Ihren programmierenden Kollegen Verwirrung zu ersparen. Fr die Feststellung der Eindeutigkeit eines URI sei noch erwhnt, dass der RFC2396 festlegt, dass ein URI dann mit einem anderen URI identisch ist, wenn diese bei einem Zeichenvergleich keinerlei Unterscheide aufweisen. Achten Sie deshalb bei der bernahme bekannter URIs immer auf die richtige Schreibweise.
Fr die Beispiele in diesem Kapitel wird neben den Beispielen mit den Wettermeldungen die Beispieldatei nsdemo.xml verwendet, die den unten gezeigten Inhalt besitzt.
<?xml version="1.0"?> <root xmlns:radio="urn:radio-uri" xmlns:leute="urn:leute-uri"> <radio:eintrag code="WWW"> <radio:radioname>Wannsee-Wahnsinns-Welle</radio:radioname> <radio:frequenzplan> <radio:frequenz einheit="mhz">98.35</radio:frequenz> <radio:frequenz einheit="mhz">104.15</radio:frequenz> <radio:frequenz einheit="mhz">92.10</radio:frequenz> </radio:frequenzplan> <radio:sendung titel="Von Windows verweht"> <radio:progblock>Nightly Blues</radio:progblock> <radio:beginn>22:00</radio:beginn> <radio:ende>23:30</radio:ende>
68
Sandini Bib
Einfhrung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<leute:moderator email="jonny@radio-www.de">Jonny Setup </leute:moderator> <leute:tagesplan>MO MI FR SA</leute:tagesplan> <leute:moderatorcode code="JS-WWW"/> </radio:sendung> <radio:sendung titel="XML Top 20"> <radio:progblock>Office Charts</radio:progblock> <radio:beginn>10:00</radio:beginn> <radio:ende>11:00</radio:ende> <leute:moderator email="gabi@radio-www.de">Gabi Parser </leute:moderator> <leute:tagesplan>MO DI MI DO</leute:tagesplan> <leute:moderatorcode code="GP-WWW"/> </radio:sendung> </radio:eintrag> <radio:eintrag code="RB"> <radio:radioname>Radio Benchmark - die schnelle Welle </radio:radioname> <radio:frequenzplan> <radio:frequenz einheit="mhz">89.90</radio:frequenz> <radio:frequenz einheit="mhz">96.50</radio:frequenz> </radio:frequenzplan> <radio:sendung titel="Datenbankgalopp"> <radio:progblock>Rush Hour</radio:progblock> <radio:beginn>15:30</radio:beginn> <radio:ende>17:00</radio:ende> <leute:moderator email="sql@radio-b.de">Steve Q. Log </leute:moderator> <leute:tagesplan>MO DI MI DO FR</leute:tagesplan> <leute:moderatorcode code="RBL-SQ"/> </radio:sendung> </radio:eintrag> </root> Listing 6.3: Die Namensraum-Beispieldatei
69
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
6 XML-Namensrume
"Tiefe", "Tag", "Prfix", "Namespace"); while(rdr.Read()) { if(rdr.NodeType == XmlNodeType.Element) Console.WriteLine("{0}\t{1,-16}\t{2}\t{3}", rdr.Depth, rdr.LocalName, rdr.Prefix, rdr.NamespaceURI); } rdr.Close(); } Listing 6.4: Auslesen von Namensrauminformationen bei XmlReader
Beim Schreiben von Elementen mit einer Instanz von XmlTextWriter oder einer von XmlWriter abgeleiteten Klasse knnen Sie fr Elemente und Attribute ebenfalls eine Namensraumdefinition und ein Prfix angeben. Wird die Methode WriteStartElement in der berladung mit einem lokalen Namen und dem Namensraum (also ohne Prfix) aufgerufen, hngt das Ergebnis davon ab, ob dieser Namensraum bereits gltig und bekannt ist oder nicht. Falls ja, dann schreibt der XmlTextWriter automatisch das passende Prfix in die Ausgabedatei. Ist der Namensraum bisher unbekannt, wird fr das Element ein Verweis auf diesen Namensraum ohne Prfix erstellt (also der Default-Namensraum fr das Element auf den angegebene URI gesetzt). Die Methode im Beispiel unten zeigt das programmatische Erstellen einer XML-Datei mit der Angabe von Namensrumen.
70
Sandini Bib
Einfhrung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// schreiben von xml mit namensumen fr elemente public static void DemoNamespaceWriter() { string filename = @"c:\tmp\ausgabe.xml"; XmlTextWriter xw = new XmlTextWriter(filename, null); xw.Formatting = Formatting.Indented; xw.Indentation = 4; xw.IndentChar = (char)32; xw.WriteStartDocument(); xw.WriteStartElement("root"); // schreiben eines elements mit namensraum xw.WriteStartElement("aw","book", "urn:bookdemo-uri"); // attribut mit namensraumdaten schreiben xw.WriteAttributeString("aw", "isbn", "urn:bookdemo-uri", "0-0000-00000-0"); // element fuer bekannten namespace xw.WriteStartElement("titel", "urn:bookdemo-uri"); xw.WriteString("Demo-Titel"); xw.WriteEndElement(); // element fuer unbekannten namespace xw.WriteStartElement("autor", "urn:book-authors-uri"); xw.WriteString("An O. Nymous"); xw.WriteEndElement(); xw.WriteEndElement(); xw.Close(); Console.WriteLine("Datei {0} geschrieben", filename); } Listing 6.5: XmlTextWriter und Namensrume
71
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
6 XML-Namensrume
XmlNamespaceManager
Die Klasse XmlNamespaceManager dient der Verwaltung und der Auflsung von Namensrauminformationen und wird immer dann verwendet, wenn eine XML-Datei ber deklarierte Namensrume verfgt. Alle anderen XML-relevanten Klassen besitzen berladungen fr die bisher vorgestellten Methoden, bei denen eine XmlNamespaceManagerInstanz als Parameter angegeben werden kann. Namenstabellen verwalten Prfix- und Elementnamen Bei der Instantiierung eines XmlNamespaceManager wird eine Tabelle als Parameter angegeben, der sogenannte name table. Hierbei handelt es sich um eine Tabelle mit atomisierten Zeichenfolgen fr die Verwaltung der Elementnamen in der XML-Datei. Atomisiert deshalb, da jeder Name in dieser Tabelle nur einmal gespeichert wird, auch wenn es mehr als ein Element mit diesem Namen gibt. Nachdem Strings in der .NET-Umgebung nicht mehr verndert werden knnen (dies ist nur ber die StringBuilder-Klasse mglich), kann somit auch ein Vergleich auf Gleichheit ber die Objektreferenz erfolgen, der wesentlich schneller als ein Zeichenkettenvergleich durchgefhrt werden kann. Mehr zur Stringverarbeitung inklusive Beispielen und Performancevergleichen zwischen Stringallozierung und StringBuilder in .NET finden Sie in meinem Buch "Goto C#", ebenfalls bei Addison-Wesley. Das folgende Code-Fragment erzeugt eine Instanz von XmlNamespace Manager und fgt eine Definition fr einen Namensraum hinzu.
XmlDocument thedoc = new XmlDocument(); thedoc.Load(@"c:\tmp\nsdemo.xml"); XmlNamespaceManager nsmgr = new XmlNamespaceManager(thedoc.NameTable); nsmgr.AddNamespace("radio", "urn:radio-uri"); Listing 6.7: Erzeugen einer XmlNamespaceManager-Instanz
Hier wird fr die Instantiierung die vorhandene Namenstabelle des XmlDocuments benutzt. Nach der Erzeugung trgt der NamespaceManager automatisch drei Namensrume ein:
Namespace:http://www.w3.org/XML/1998/namespace, Prefix:xml Namespace:http://www.w3.org/2000/xmlns/, Prefix:xmlns
72
Sandini Bib
Einfhrung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Auerdem wird ein Leerstring (String.Empty) fr ein leeres Prfix eingetragen, also der Standardnamespace sozusagen gelscht. Elemente ohne Prfix sind damit keinem Namensraum zugeordnet. Mit Hilfe der Methode AddNamespace fgen Sie eine zustzliche Namensraumdeklaration hinzu. Dabei geht der Namespace-Manager davon aus, dass die Gltigkeit des Prfixes und des Namensraum-URI bereits geprft wurde. Es wird hier keine weitere berprfung durchgefhrt. Die Klasse XmlNamespaceManager unersttzt Auflistungen ber eine Implementierung der IEnumerable-Schnittstelle. Sie knnen also mit einer foreach-Schleife die Liste der eingetragenen Prfixe durchlaufen:
Console.WriteLine("Folgende Prfixe sind eingetragen:"); foreach(string s in nsmgr) Console.WriteLine("Prfix \"{0}\" ", s); Listing 6.8: Auflisten aller eingetragenen Namensrume
AddNameSpace
Fr die einzelnen Aufgaben der Verwaltung von Namensrumen sind in der Klasse eine ganze Reihe von Methoden und Eigenschaften definiert, mit der z.B. eine Zuordnung von Namensraum-URI zu Prfix in einer Zeile erledigt ist. Aufgabe
Den Namespace-URI finden, der als Standardnamespace definiert wurde. Den Namespace-URI finden, der fr ein Prfix deklariert wurde und im Gltigkeitsbereich liegt. Das Prfix finden, das fr einen NamespaceURI deklariert wurde und im Gltigkeitsbereich liegt. Dem XmlNamespaceManager weitere Namespaces hinzufgen. Namespaces aus dem XmlNamespaceManager entfernen. Einen Gltigkeitsbereich fr einen Namespace festlegen. berprfen, ob im aktuellen Gltigkeitsbereich ein Prfix definiert ist. Den Namen der NameTable finden, die gegenwrtig in der Lookup- und in der Add-Methode verwendet wird.
LookupPrefix-Methode
Tabelle 6.1: Aufgaben im Bereich Namensrume und die passenden Methoden dazu
73
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
6 XML-Namensrume
74
Sandini Bib
Einfhrung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Sie sehen die Definition eines Standardnamensraums fr Elemente ohne Prfix in der vorletzten Zeile und in der letzten Zeile der Verweis, wo fr diesen Namensraum das entsprechende Schema zu finden ist. Im Schema selbst erfolgt zuerst die Definition fr den xsd-Namensraum, den Schemadefinitionsnamensraum. Anschlieend wird das Namensraum-Prfix wx mit dem gleichen URI wie in der XML-Datei deklariert und danach der targetNamespace fr das Schema ebenfalls auf diesen URI gesetzt, so dass das Dokument gegen dieses Schema geprft werden kann. Bei beiden Angaben fr elementFormDefault und attributeFormDefault entsprechen der Standardeinstellung und sind hier nur der Vollstndigkeit halber aufgefhrt. Deren Inhalt legt fest, dass Angaben unqualifiziert, also ohne Angabe des Prfix in der Datei erfolgen.
<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:wx="urn:meteo-demo" targetNamespace="urn:meteo-demo" elementFormDefault="unqualified" attributeFormDefault="unqualified"> Listing 6.11: Das <schema>-Element mit Namensrumen
Fr die Validierung besteht der einzige Unterschied zur Validierung mit einem XSD-Schema darin, dass bei der Methode XmlSchemaCollection.Add nun die Angabe des Prfix zu einem Namensraum-URI erfolgt (ohne einen Namensraum war dies jeweils ein leerer String). Der Rest entspricht dem normalen Ablauf. Hier nochmal die komplette Klasse, damit Sie nicht zurckblttern mssen:
XmlSchema Collection
75
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
6 XML-Namensrume
// annahme
// die ereignisbehandlungsroutine public void ValidationSink(object sender, ValidationEventArgs args) { // nur fehler ausgeben, warnungen ignorieren if(args.Severity == XmlSeverityType.Error) { bValidated = false; Console.WriteLine("Fehler: {0}", args.Message); } } // prfen mit dem angeforderten schematyp public bool Validate(string url, ValidationType vt) { // schema collection mit schema fuellen XmlSchemaCollection xsc = new XmlSchemaCollection(); try { xsc.Add("urn:meteo-demo", @"c:\tmp\meteo.xsd"); //XSD schema } catch(Exception e) { Console.WriteLine("Exception thrown! {0}", e.Message); } // textreader erzeugen XmlTextReader txtrdr = new XmlTextReader(url); // den validatingreader erzeugen XmlValidatingReader vrdr = new XmlValidatingReader(txtrdr); vrdr.ValidationType = vt; // schemas zum validatingreader hinzufgen vrdr.Schemas.Add(xsc); // eintragen eventhandler vrdr.ValidationEventHandler += new ValidationEventHandler(this.ValidationSink); // jetzt keine exception mehr bei fehler
76
Sandini Bib
Zusammenfassung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
while(vrdr.Read()) { } Console.WriteLine(vrdr.Schemas.Count); // ergebnis zurckliefern return bValidated; } } Listing 6.12: berprfung mit XSD-Schema und Namensrumen
6.2 Zusammenfassung
Namensrume sind fr XML mittlerweile unverzichtbar, um die Vielfalt der gleichlautendenden Elementnamen auseinander halten zu knnen. Mit Hilfe eines URI sind sie leicht eindeutig zu spezifizieren. ber ein Prfix, der durch einen Doppelpunkt vom lokalen Namensteil des Elements oder Attributes getrennt wird, ist die Verwendung kein Problem. Einsteiger sollten bei der manuellen Erstellung eines Schemas auf die richtige Deklaration der Namensraum-URIs achten und sich nach Mglichkeit anfangs der Hilfe einer XML-Entwicklungsumgebung bedienen. Nach Mglichkeit sollten Sie auf die Deklaration eines Default-Namensraums (ohne Prfix) verzichten, wenn Sie mehr als einen Namensraum verwenden, da die Lesbarkeit und die Zuordnung der Elemente durch das Prfix erleichtert wird.
77
Sandini Bib
Sandini Bib
Essentials
.NET
XSL-Transformationen
7.1 Grundlagen
XSLT ist wohl fr viele Entwickler der komplizierteste Teil der XMLTechnologien und wird daher noch nicht berall in dem Ma eingesetzt, das der Bedeutung von XSL-Transformation gerecht wrde. Eine komplette Einfhrung in die Thematik wrde an dieser Stelle zu weit fhren, aus Platzgrnden werde ich mich auf die wichtigsten Punkte beschrnken, so dass Sie schnell zu Ergebnissen kommen. Details und Weiterentwicklungen (wie die XSL-Formatting Objects) finden Sie bei den diversen Titeln zum Thema XSLT. Wie der Name bereits ausdrckt, handelt es sich hier um eine Stylesheet-Language, d.h. um das Anwenden von Formatierungsregeln auf alle in einem Stylesheet definierten Elemente des geparsten XML-Baumes. Das Zusammenwirken der einzelnen Elemente zeigt die Abbildung eines Transformationsvorgangs. Statt XSLT wird oft auch XSL als Abkrzung verwendet
Eine Eingabestruktur in XML wird mit Hilfe eines Stylesheets, das die Formatierungsregeln enthlt, zu einer Ausgabestruktur umgewandelt. Das Ergebnis dieser Transformation muss brigens nicht unbedingt wieder eine XML-Datei sein, sondern kann durchaus HTML oder sogar Flatfile sein. Nur nebenbei: Sie bentigen nicht unbedingt .NET fr die Nutzung von XSLT, die XML Core Services von Microsoft (der MSXML) sind mittlerweile in der Version 4 erhltlich und bieten auch in der alten COM-Welt die Untersttzung der W3C-Empfehlungen.
79
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
7 XSL-Transformationen
Das obige Stylesheet enthlt ein Template mit dem Wurzelelement als bereinstimmungsausdruck und eines, das fr alle <station>-Elemente als Kontextknoten oder dessen Nachfahren eine bereinstimmung liefert. Fr das Wurzelelement erfolgt nur die Ausgabe eines Absatz-Tags in HTML, gefolgt von einer rekursiven Anwendung aller anderen definierten Templates im Stylesheet (<xsl:apply-templates />), danach wieder ein schlieendes Tag fr einen Absatz.
80
Sandini Bib
Stylesheets laden
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Die Schablone fr alle <station>-Elemente zeigt die Ausgabe von Textinformation, die unverndert in den Ausgabestrom geschrieben werden sollen (per <xsl:text>) und das Einsetzen von Elementinhalten ber die Anweisung <xsl:value-of>, die ebenfalls einen XPath-Ausdruck verwendet. Beispiele fr komplexere Stylesheets finden Sie noch weiter unten in diesem Kapitel oder in einem der vielen Einfhrungen in das Thema XSLT.
81
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
7 XSL-Transformationen
new NetworkCredential("usr","pwd","domain"); resolver.Credentials = nc; // stylesheet laden. xslt.Load("http://kiste/xsl/wetter1.xsl", resolver); // hier dann transformation durchfhren } Listing 7.3: Laden von Ressourcen ber einen Resolver
Diese Art des Zugriffs bentigen Sie insbesondere dann, wenn innerhalb des Stylesheets (oder des XML-Dokumentes) auf eine externe Datei verwiesen wird, da dann der Resolver die einzige Mglichkeit darstellt, diese Verweise unter Sicherheitsaspekten aufzulsen. Der XmlUrlResolver ist die Standardklasse (abgeleitet von XmlResolver) fr diesen Zweck, Sie knnen allerdings auch eigene, spezielle Resolver programmieren. Weitere Hinweise dazu finden Sie in der Online-Hilfe von Visual Studio .NET.
gangsdaten verbunden werden. Auch diese Methode ist wieder mehrfach berladen, so dass fr jeden Zweck die passende Liste an Parametern zur Verfgung steht. So wird als erster Parameter die XMLStruktur bergeben, wobei Sie die Wahl zwischen einer Klasse haben, die die Schnittstelle XPathNavigable implementiert (XmlNode, XmlDocument oder XPathDocument) oder einer Instanz eines XPathNavigators. Der zweite Parameter ist eine Referenz auf eine Liste von Parameterersetzungen fr das Stylesheet (siehe weiter unten) und der dritte Parameter gibt das Ziel der Transformation an, wobei hier ein Stream-Nachfolger, ein TextWriter oder ein XmlWriter benutzt werden knnen. Das folgende Listing ist der komplette Code fr die Transformation einer XML-Datei mit Hilfe eines XSL-Stylesheets. Das Ergebnis der Transformation wird dann in die Standardausgabe geschrieben. Nach dem Listing folgt das Listing des verwendeten Stylesheets und in der Abbildung die Ausgabe des Programms.
// XSL-Transformationen in .NET using using using using System; System.XML; System.XML.XPath; System.XML.XSL;
82
Sandini Bib
Transformation durchfhren
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
namespace XSLDemo { class XSLDemos { static void SampleSimpleTransform() { XslTransform xslt = new XslTransform(); // stylesheet laden xslt.Load(@"h:\wetter1.xsl"); // XPathDocument erzeugen und die // xml-daten laden XPathDocument thedoc = new XPathDocument(@"h:\miniwetter.xml"); // XmlTextWriter fuer die ausgabe // erzeugen XmlTextWriter writer = new XmlTextWriter(Console.Out); // transformation durchfhren // ausgabe geht nach Console.Out, wie // durch XmlTextWriter-Erzeugung festgelegt xslt.Transform(thedoc,null,writer); } static void Main(string[] args) { SampleSimpleTransform(); Console.WriteLine(); Console.Write("Press a key ...."); Console.ReadLine(); } } } Listing 7.4: Transformation eines XML-Dokumentes per XSL
83
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
7 XSL-Transformationen
</p> </html> </xsl:template> <xsl:template match="//station"> <p> <xsl:text>The weather in </xsl:text> <xsl:value-of select="location" /> <xsl:text>: </xsl:text> <xsl:value-of select="weather" /> </p> </xsl:template> </xsl:stylesheet> Listing 7.5: Demo-Stylesheet wetter1.xsl
84
Sandini Bib
Transformation durchfhren
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/ Transform"> <xsl:template match="/"> <xsl:element name="weatherdata"> <xsl:apply-templates /> </xsl:element> </xsl:template> <xsl:template match="station"> <xsl:element name="station"> <!-- attributliste fuer station --> <xsl:attribute name="id"> <xsl:value-of select="location" /> </xsl:attribute> <!-- ab hier die neuen elemente --> <xsl:element name="sky"> <xsl:value-of select="weather" /> </xsl:element> <xsl:element name="temp"> <xsl:attribute name="units"> <xsl:value-of select="temp/@units" /> </xsl:attribute> <xsl:value-of select="temp" /> </xsl:element> <xsl:element name="humidity"> <xsl:attribute name="units"> <xsl:text>percent</xsl:text> </xsl:attribute> <xsl:value-of select="substring-before(humidity,'%')" /> </xsl:element> <xsl:element name="wind"> <xsl:attribute name="speed"> <xsl:value-of select="windspeed" /> </xsl:attribute> <xsl:attribute name="units"> <xsl:text>knots</xsl:text> </xsl:attribute> <xsl:value-of select="wind" /> </xsl:element> <xsl:element name="airpressure"> <xsl:attribute name="trend"> <xsl:value-of select="airtrend" /> </xsl:attribute> <xsl:attribute name="units"> <xsl:text>hpa</xsl:text> </xsl:attribute> <xsl:value-of select="airpressure" /> </xsl:element>
85
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
7 XSL-Transformationen
86
Sandini Bib
Zusammenfassung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
XmlTextWriter writer = new XmlTextWriter(Console.Out); // Zwischenergebnis in einen XmlReader stecken XmlReader temprdr = xslt1.Transform(thedoc, null); // XPathDocument aus diesem Reader erzeugen XPathDocument doc2 = new XPathDocument(temprdr); // nochmal transformieren und an die konsole xslt2.Transform(doc2,null,writer); } Listing 7.7: Mehrfache Transformationen per XSL
XPathNavigable-Implementierungen nutzen
Aus Grnden der Performance sollte fr die Transformation nach Mglichkeit die XML-Struktur zuerst in eine XPathDocument-Instanz geladen werden, da diese die Schnittstelle XPathNavigable implementiert und fr die Verarbeitung von Stylesheets optimiert wurde. Das obige Listing zeigt diesen Ansatz. Sie knnen natrlich auch einfach der URL fr die Eingabe- und die Ausgabedatei angeben, wobei fr kleinere Dateien der Performanceunterschied kaum ins Gewicht fllt. Ganz anders sieht die Sache dagegen aus, wenn Sie eine 15 Mbyte groe XML-Struktur mit zwei Stylesheet-Transformationen in eine andere XML- oder Editfact-Datei berfhren.
7.5 Zusammenfassung
Mit nur wenigen Methoden (hautpschlich Load und Transform) bietet die XSLT-Untersttzung von .NET eine mchtige Mglichkeit, beliebige XML-Strukturen programmgesteuert zu transformieren und sogar die Stylesheets selbst als XML-Dokumente zuerst programmatisch zu erzeugen. Die sich bietenden Mglichkeiten werden nur durch die Fantasie des Entwicklers begrenzt. Entwerfen Sie doch einfach eine XMLNotation fr Klassen oder benutzen Sie eine der verfgbaren und schreiben sich dann dazu ein XSL-Stylesheet, das je nach Auswahl entweder C#- oder Visual Basic .NET-Code erzeugt!
87
Sandini Bib
Sandini Bib
Essentials
.NET
89
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
<!ATTLIST speed units <!ELEMENT <!ATTLIST trend units <!ELEMENT <!ATTLIST <!ELEMENT
wind CDATA #REQUIRED CDATA #REQUIRED> airpressure (#PCDATA)*> airpressure CDATA #REQUIRED CDATA #REQUIRED> station ((sky|clouds),temp,humidity,wind,airpressure)> station id CDATA #REQUIRED> weatherdata (station)+>
listet. Da in der Datei entweder das Tag <sky> oder die Bewlkung mit <clouds> vorkommen darf, wird diese Auswahl in der DTD ber den choice operator "|" festgelegt. Dieser arbeitet wie ein logisches Oder und kann in einer lngeren Liste auch mehrfach wiederholt werden, wie Sie bei den Attributdefinitionen noch sehen werden. Fr das Auftreten von Elementen kann angegeben werden, ob und wie oft ein Element als Unterelement auftreten darf. In der Beispieldatei muss innerhalb des <weatherdata>-Elementes mindestens ein <station>Element vorhanden sein, was in der DTD durch das nachgestellte "+" definiert wird. Wer bereits mit regulren Ausdrcken gearbeitet hat, kennt die mglichen Modifikatoren bereits:
Zeichen
? * + |
Bedeutung
Optionales Element, muss nicht vorhanden sein Dieses Element kann 0-mal oder fter auftauchen Dieses Element muss mindestens einmal vorhanden sein Choice operator, eines der Elemente aus der Liste
90
Sandini Bib
Warum ein Schema?
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Das <!DOCTYPE>-Element gibt nach dem Namen des Wurzelelementes (hier <weatherdata>) in eckige Klammern eingeschlossen die Document Type Definition an. Dies ist nicht immer wnschenswert. Soll beispielsweise mehr als eine Dokumenteninstanz die gleiche DTD benutzen, wre dies erstens Platzverschwendung und zweitens wren nderungen wesentlich aufwndiger. Daher ist auch die Angabe einer externen DTD mglich. Hier wird im DOCTYPE-Element anstelle der direkten Angabe der DTD einfach ein Verweis auf eine Betriebssystemdatei aufgefhrt. Um unsere interne in eine externe DTD umzuwandeln, markieren Sie den kompletEine externe DTD verwenden
91
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
ten Text zwischen den beiden eckigen Klammern und speichern diesen in eine Textdatei (per Konvention mit der Erweiterung .dtd) ab. Anschlieend ndern Sie das DOCTYPE-Element wie folgt ab:
<!DOCTYPE rootelement SYSTEM "dtdpfadname">
Auf diese Weise beziehen Sie sich bei der Validierung auf eine externe Datei. Erfolgt der Zugriff auf die XML-Datei ber einen URL, bentigen Sie fr das Laden der XML-Struktur einen Resolver (siehe Kapitel 5, "Resolver"), der sich um die Sicherheitsinformationen fr den Zugriff auf externe Verweise (Benutzer, Password, Domain) kmmert.
92
Sandini Bib
Warum ein Schema?
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
private string fFilename; private XmlTextReader txtrdr = null; // der konstruktor public DTDSchemaDemo(string filename) { fFilename = filename; txtrdr = new XmlTextReader(fFilename); } // prfen mit dem angeforderten schematyp public bool Validate(ValidationType vt) { // den validatingreader erzeugen XmlValidatingReader vrdr = new XmlValidatingReader(txtrdr); vrdr.ValidationType = vt; // durchlaufen, wenn keine exception, // dann ist das dokument gltig try { while(vrdr.Read()) { } return true; } // verloren, doch ein fehler catch(Exception e) { Console.WriteLine(e.Message); return false; } } static void Main() { // instanz der demo-klasse erzeugen DTDSchemaDemo sd = new DTDSchemaDemo(@"c:\tmp\meteo.xml"); // validieren und ergebnis ausgeben if(sd.Validate(ValidationType.DTD)) Console.WriteLine("Keine Fehler, " + " Dokument gltig."); else Console.WriteLine("Dokument nicht " + "gltig."); // den benutzer das // konsolenfenster schliessen lassen
93
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Console.WriteLine(); Console.Write("Press a key ...."); Console.ReadLine(); } } } Listing 8.3: Prfen eines Dokumentes mit Hilfe einer DTD
94
Sandini Bib
Warum ein Schema?
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
bValidated = false; Console.WriteLine("Fehler: {0}", args.Message); } } // prfen mit dem angeforderten schematyp public bool Validate(ValidationType vt) { // den validatingreader erzeugen XmlValidatingReader vrdr = new XmlValidatingReader(txtrdr); vrdr.ValidationType = vt; // eintragen eventhandler vrdr.ValidationEventHandler += new ValidationEventHandler(this.ValidationSink); // jetzt keine exception mehr bei fehler while(vrdr.Read()) { } // ergebnis zurckliefern return bValidated; } static void Main() { // instanz der demo-klasse erzeugen DTDSchemaDemo sd = new DTDSchemaDemo(@"c:\tmp\meteo.xml"); // validieren und ergebnis ausgeben if(sd.Validate(ValidationType.DTD)) Console.WriteLine("Keine fehler, " + "Dokument gltig."); else Console.WriteLine("Dokument nicht " + "gltig."); // den benutzer das // konsolenfenster schliessen lassen Console.WriteLine(); Console.Write("Press a key ...."); Console.ReadLine(); } } } Listing 8.4: Validierung mit einer Ereignisbehandlungsroutine
95
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Solange Sie einfach nur wissen mchten, ob das Dokument gltig ist oder nicht, reicht auch die einfache Variante, bei der nur geprft wird, ob eine XmlException aufgetreten ist. Die Definition einer Ereignisbehandlungsroutine (event sink) bietet dagegen mehr Flexibilitt bei der Reaktion auf das Ereignis.
Keine Einschrnkung fr Inhalte (CDATA heit wirklich: alle Zeichen) Keine Defaults fr Elemente, nur fr Attribute Definition der Attributwerte erlaubt nur Aufzhlungen als komplexere Typen Keine Namensraumuntersttzung Aufwndige Definition bei komplexeren Inhaltsstrukturen Nicht modularisierbar (nur ber entities und das nur begrenzt) Keine Wildcards fr Elemente oder Attribute Keine Vererbung oder Erweiterung von DTDs
Jeder Hersteller von XML-Produkten hatte bis zur Verabschiedung der XS-Empfehlung durch das W3C eigene Vorschlge entwickelt. Bei Microsoft war dies das "XML Data Reduced-Schema" (XDR), das ebenso wie DTD heute eigentlich nur noch historischen Wert hat, da .NET die XSD-Schemata untersttzt und damit den optimalen Weg fr die Definition der Struktur von XML-Dateien bietet.
96
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Definition im XML-Format Selbstbeschreibend und fr Menschen lesbar Klar, einfach und modular strukturiert Von mglichst vielen XML-Anwendungen nutzbar Zusammenarbeit mit anderen Standards (z.B. XPath) Mglichst schnell verfgbar Ausfhrlich beschrieben mit vielen Beispielen
Das 2001 verabschiedete Ergebnis erfllt viele, aber nicht alle der Wnsche der XML-Gemeinde. Insbesondere des Punkt der Einfachheit, Konsistenz und hohen Verstndlichkeit wurde klassisch verfehlt. Die XML-Schemadefinition ist wohl eines der komplexesten Dokumente aus der Feder des W3C (manche behaupten, eindeutig zu komplex), so dass vor das eigentliche Dokument (mehrere hundert Seiten in zwei Teilen) eine umfangreiche, mit Beispielen versehene Einfhrung gestellt werden musste. Auch wenn Sie hier einige Beispiele fr das Erstellen von Schemas mit den Werkzeugen von Visual Studio .NET finden, ist die Erstellung eines Schemas fr den produktiven Einsatz keine leichte Aufgabe. In der Regel werden Sie mit einem bereits vorhandenen Schema arbeiten, fr das Instanzdokumente validiert werden mssen. Dennoch sollten Ihnen die Grundlagen der Schema-Erstellung vertraut sein. Die Startseite fr die Dokumente, Tools und Verweise auf den Seiten des W3C findet sich unter dem URL http://www.w3.org/XML/Schema. Der eigentliche Standard besteht aus drei Teilen (Einfhrung, Strukturen, Datentypen): XML Schema Part 0: Primer (http://www.w3.org/TR/xmlschema-0/) XML Schema Part 1: Structures (http://www.w3.org/TR/xmlschema-1/) XML Schema Part 2: Datatypes (http://www.w3.org/TR/xmlschema-2/) An dieser Stelle seien alle XML-Profis gleich vorsorglich um Verzeihung fr eine ganze Reihe von Vereinfachungen und Detailunterlassungen gebeten, aber fr eine wirklich fundierte Einfhrung htte der gesamte Umfang des Buches diesem einen Thema gewidmet werden mssen. XSD ist nicht leicht verstndlich
97
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Zur Erstellung eines Schemas fr diese XML-Struktur stehen mehrere Mglichkeiten zur Verfgung:
Manuelle Erstellung eines Schemas Verwenden einer XML-Entwicklungsumgebung Verwenden des Tools xsd.exe Benutzen des Schema-Editors von Visual Studio .NET
Der rein manuelle Weg ist ideal fr Leute, die heute ihren Quellcode immer noch mit vi oder notepad schreiben. Alle anderen (einschlielich des Autors) drften einen etwas beqeuemeren Weg vorziehen. Die Verwendung einer der auf dem Markt erhltlichen XML-Entwicklungsumgebungen ist zwar recht komfortabel, die Bedienung unterscheidet sich aber deutlich von Produkt zu Produkt und eine Vorstellung der verschiedenen Werkzeuge ist auch nicht Thema des Buches.
98
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
xsd.exe - Utility to generate schema or class files from given source. xsd.exe xsd.exe xsd.exe xsd.exe <schema>.xsd /classes|dataset [/e:] [/l:] [/n:] [/o:] [/uri:] <assembly>.dll|.exe [/outputdir:] [/type: [...]] <instance>.xml [/outputdir:] <schema>.xdr [/outputdir:]
- OPTIONS /classes Generate classes for this schema. Short From is '/c'. /dataset Generate sub-classed DataSet for this schema. Short From is '/d'. /element:<element> Element from schema to process. Short From is '/e:'. /language:<language> The language to use for the generated code. Choose from 'CS', 'VB', 'JS' or provide a fully-qualified name for a class implementing System.CodeDom.Compiler.CodeDomProvider. The default is 'CS' (CSharp). Short form is '/l:'. /namespace:<namespace> The namespace for generated class files. The default namespace is the global namespace. Short form is '/n:'. /nologo Suppresses the banner. /out:<directoryName> The output directory to create files in. The default is the current directory. Short form is '/o:'. /type:<type> Type from assembly to generate schema for. Multiple types may be provided. If no types are provided, then schemas for all types in an assembly are generated. Short form is '/t:'. /uri:<uri> Uri of elements from schema to process. Short From is '/u:'. - ARGUMENTS <schema>.xsd Name of a schema containing elements to import <assembly>.dll|exe Name of an assembly containing types to generate schema for. <instance>.xml Name of an xml file to infer xsd schema from. <schema>.xdr Name of an xdr schema to convert to xsd. Multiple file arguments of the same type may be provided.
99
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Fr die Erstellung eines XSD-Schemas aus dem XML-Fragment ergnzen wir dieses um die XML-Verarbeitungsanweisung und speichern die Datei unter dem Namen eingabe.xml ab. Anschlieend wird xsd.exe mit der folgenden Befehlszeile aufgerufen:
xsd.exe eingabe.xml
Das Programm schreibt dann eine Datei eingabe.xsd im gleichen Verzeichnis mit folgendem Inhalt:
01 <?xml version="1.0" encoding="utf-8"?> 02 <xs:schema id="NewDataSet" 03 xmlns="" 04 xmlns:xs="http://www.w3.org/2001/XMLSchema" 05 xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> 06 <xs:element name="station"> 07 <xs:complexType> 08 <xs:sequence> 09 <xs:element name="location" 10 type="xs:string" 11 minOccurs="0" /> 12 <xs:element name="weather" 13 type="xs:string" 14 minOccurs="0" /> 15 <xs:element name="temp" 16 type="xs:string" 17 minOccurs="0" /> 18 <xs:element name="humidity" 19 type="xs:string" 20 minOccurs="0" /> 21 <xs:element name="wind" 22 type="xs:string" 23 minOccurs="0" /> 24 <xs:element name="airpressure" 25 type="xs:string" 26 minOccurs="0" /> 27 </xs:sequence> 28 </xs:complexType> 29 </xs:element> 30 <xs:element name="NewDataSet" 31 msdata:IsDataSet="true" 32 msdata:Locale="de-DE"> 33 <xs:complexType> 34 <xs:choice maxOccurs="unbounded"> 35 <xs:element ref="station" />
100
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
36 </xs:choice> 37 </xs:complexType> 38 </xs:element> 39 </xs:schema> Listing 8.6: Das automatisch erstellte Schema
Nach der XML-Verarbeitungsanweisung in Zeile 1 erfolgt in den Zeilen 2 bis 5 die Definition des <schema>-Elementes und der entsprechenden Namensrume (mehr zu Namensrumen erfahren Sie im Kapitel 6). Die Zeilen 6 bis 29 definieren das Element <station> und seine darin enthaltenen Unterelemente, whrend die Zeilen 30 bis 38 die Verwendung dieses Elementes regeln. Die meisten der Elemente und Attribute drften selbsterklrend sein. So wird mit Hilfe des Attributes type festgelegt, um welchen Datentyp es sich beim Inhalt dieses Elementes handelt. Sollten Sie sich jetzt fragen, warum dann hier berall der Wert xs:string enthalten ist, dann deshalb, weil aus der XML-Datei selbst keine weiteren Informationen aus den Elementinhalten ber deren Datentyp gewonnen werden knnen. Hier wre in einem Produktivschema also bereits manuelle Nacharbeit angesagt. Das Attribut minOccurs (zu dem auch ein Pendant maxOccurs existiert) gibt an, wie oft das Element mindestens vorkommen muss (auch hier wre ein Wert von "1" die richtige Einstellung). ber das Element <xs:sequence> wird definiert, dass es sich bei diesem Typ um eine Sequenz handelt, also alle angegebenen Unterelemente in genau dieser Reihenfolge auftreten mssen (natrlich unter Beachtung von minOccurs und maxOccurs). Wie oft darf ein Element vorkommen?
101
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Fr die Datei meteo.xml soll nun mit Hilfe des Schema-Designers ein XSD-Schema erstellt werden. Visual Studio .NET bietet dafr eine automatisch arbeitende Funktion an, welche ein Schema im so genannten russian doll design erzeugt. Laden Sie dazu die Datei meteo.xml in Visual Studio .NET und whlen Sie anschlieend aus dem Men XML die Option SCHEMA ERZEUGEN aus. Wenn Sie nun im automatisch erzeugten Schema auf die XML-Ansicht umschalten, erkennen Sie sofort den Bezug zu den ineinander geschachtelten russischen Babuschka-Puppen. Sie knnen mit diesem Designer auch komplett neue Schemata manuell erstellen. Die ntigen ersten Schritte dazu sollen am Beispiel eines neu erstellten Schemas fr die Datei meteo.xml gezeigt werden. Dazu wird ber das DATEI-Men eine neue Datei vom Typ XML-SCHEMA angelegt, die ber die unten gezeigte Toolbox aus der Entwicklungsumgebung mit Inhalt gefllt wird.
Zuerst wird ein Root-Element bentigt. Ziehen Sie dazu ein Element auf die Arbeitsflche. Geben Sie im linken Eingabefeld den Inhalt weatherdata ein (dies wird der Elementname). Im rechten Eingabefeld (dem Typ des Elements) knnen wir keinen der vordefinierten einfachen Datentype wie string oder positiveInteger benutzen, sondern geben den Text weatherType ein (diesen Datentypen werden wir gleich definieren). Der Datentyp fr den Inhalt des <weatherdata>-Wurzelelements besteht aus einer Abfolge von mindestens einem <station>-Element mit den entsprechenden Unterelementen <sky> | <clouds>, <temp>, <humidity>, <wind> und <airpressure>.
102
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Erstellen Sie dazu ber die Toolbox einen complexType mit dem Namen weatherType und einem Element station sowie einen complexType mit dem Namen stationType und den Elementen <sky>, <clouds>, <temp>, <humidity>, <wind> und <airpressure>.
103
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Bis jetzt sind alle Typen fr die Elementinhalte noch vom Datentyp string und darber hinaus muss fr die Auswahl zwischen <sky> und <clouds> noch Vorkehrung getroffen werden. Dies geschieht durch das Austauschen des Elementes <sky> durch eine Gruppe. Lschen Sie das Element <sky>, fgen Sie (ber die Toolbox oder die rechte Maustaste) eine choice-Group ein (ber Ausschneiden und Einfgen bei markierten Elementzeilen knnen Sie die Reihenfolge ndern, ebenso natrlich ber die XML-Ansicht direkt im Code) und geben Sie dort die beiden Elemente <sky> und <clouds> an. Jetzt sollte Ihr Designerbildschirm der Abbildung 8.5 gleichen. Fr einzelne Elemente der Datei existieren auch Attribute (beispielsweise das Attribut units fr das <temp>-Element). Um diese Attribute in das Schema aufzunehmen, muss aus dem einfachen Typ string, der fr die Elementinhalte eingetragen war, ein sogenannter komplexer Typ gemacht werden. Das XML-Schema kennt zwei grundlegende Inhaltstypen fr ein Schema: simpleType und complexType. Whrend ein simpleType nur einen der vordefinierten Datentypen aus dem SchemaNamensraum und keine Unterelemente oder Attribute beinhalten darf, kann ein complexType sowohl gemischten Inhalt, Unterlemente oder auch Attribute beinhalten. Fr die Definition von Attributen zu einem Element muss also ein complexType her. Dazu stellen Sie den Typ fr ein Element, das Attribute haben soll (z.B. <wind>) auf die Einstellung UNNAMED COMPLEXTYPE.
104
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Daraufhin wird ein neuer complexType unterhalb des <wind>-Elements im Schema angelegt, den Sie mit den beiden Attributen units und speed versehen knnen. Wie Sie sehen, ist die komplett neue Erstellung eines etwas komplexeren Schemas keine leichte Aufgabe. Besser ist meist die Verwendung eines Generators wie xsd.exe und das anschlieende Abndern. Wollen Sie einen definierten Typ wiederverwenden, knnen Sie durch Anklicken mit der rechten Maustaste und die Auswahl TYP GLOBAL DEKLARIEREN eine Deklaration als Nachfolger des <schema>-Elements erzeugen und so diesen Typ per Verweis an mehr als einer Stelle wiederverwenden.
105
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
106
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Visual Studio .NET geht dabei davon aus, dass fr jede Spalte ein entsprechendes Element in der Datei vorhanden ist und die Tabelle so heit wie das Wurzelelement. Ist dies nicht der Fall, knnen Sie mit Hilfe des Schema-Designers dieses Schema jederzeit umbauen, um einzelne Werte beispielsweise in Attribute zu verlagern.
107
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Anschlieend wird eine Datei schema0.xsd im Verzeichnis abgelegt, in der ein Schema fr den entsprechenden Typ vorhanden ist. xsd generiert Schemadateien
<?xml version="1.0" encoding="utf-8"?> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="SimpleDemo" nillable="true" type="SimpleDemo" /> <xs:complexType name="SimpleDemo"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="1" name="Kennzeichen" type="xs:string" /> <xs:element minOccurs="1" maxOccurs="1" name="KmStand" type="xs:int" /> <xs:element minOccurs="1" maxOccurs="1" name="Verbrauch" type="xs:double" /> </xs:sequence> </xs:complexType> </xs:schema> Listing 8.8: Das generierte Schema
brigens lsst sich aus einem vorliegenden Schema mit Hilfe von xsd.exe auch eine Klasse erzeugen, so dass Sie einen anderen Weg gehen und fr ein erhaltenenes Schema eine C#-Klasse erzeugen lassen knnen.
108
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Mit diesen Eintrgen wird deklariert, dass das Schema fr alle Elemente, die zu keinem Namensraum gehren, in der Datei zu finden ist, auf die das Attribut noNamespaceSchemaLocation verweist. Soll das Schema fr Elemente in einem Namensraum angegeben werden, dann wird statt dessen das Attribut SchemaLocation benutzt. Diese Angabe bedeutet noch nicht, dass das Dokument notwendigerweise gltig ist, sondern dass das Dokument eine Validierung gegen dieses Schema berstehen sollte. Die Gltigkeit steht also genau wie bei einer DTD erst nach einem erfolgreichen Durchlauf mit der XmlValidatingReader-Instanz fest. Unterbleibt diese Eintragung des Schemaverweises, wird bei der Validierung mit allen passenden Prfixen fr die geladenen Namensrume geprft.
noNamespaceSchemaLocation
XSD-Validierung
Die Validierung mit Hilfe eines Schemas unterscheidet sich (mit Ausnahme der unterschiedlichen Attribute noNamespaceSchemaLocation und SchemaLocation kaum. Weitere Details zu Namensrumen und ihrer Rolle finden Sie im Kapitel ber die Namensrume. Hier ein komplettes Listing mit einer Klasse fr die Validierung eines Dokumentes mit Hilfe eines XSD-Schemas. Nachdem hier kein Namensraum definiert wurde, wird beim Aufruf der Methode XmlSchema Collection.Add als erster Parameter ein leerer String (oder String. Empty) bergeben, so dass das als zweiter Parameter angegebene Schema zur Validierung aller Elemente ohne einen Namensraumprfix benutzt wird. Der restliche Code ist fast der gleiche wie bei einer Validierung mit Hilfe einer DTD.
// validierung mit hilfe eines xsd-schemas // die namensrume using System; using System.XML; using System.XML.XPath; using System.XML.Schema;
XmlSchema Collection
109
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
namespace SchemaSamples { // die validierungsklasse class XSDSchemaDemo { private bool bValidated = true; // annahme // die ereignisbehandlungsroutine public void ValidationSink(object sender, ValidationEventArgs args) { // nur fehler ausgeben, warnungen ignorieren if(args.Severity == XmlSeverityType.Error) { bValidated = false; Console.WriteLine("Fehler: {0}", args.Message); } } // prfen mit dem angeforderten schematyp public bool Validate(string url, ValidationType vt) { // schema collection erzeugen und // mit schema und namensraum-URI fuellen XmlSchemaCollection xsc = new XmlSchemaCollection(); try { // "" bezeichnet standard-namensraum // fuer alle elemente ohne prfix xsc.Add("", @"c:\tmp\meteo.xsd"); } catch(Exception e) { Console.WriteLine("Exception thrown! {0}", e.Message); } // textreader erzeugen XmlTextReader txtrdr = new XmlTextReader(url); // den validatingreader erzeugen XmlValidatingReader vrdr = new XmlValidatingReader(txtrdr); vrdr.ValidationType = vt; // schemas zum validatingreader hinzufgen vrdr.Schemas.Add(xsc);
110
Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// eintragen eventhandler vrdr.ValidationEventHandler += new ValidationEventHandler(this.ValidationSink); // jetzt keine exception mehr bei fehler while(vrdr.Read()) { } Console.WriteLine(vrdr.Schemas.Count); // ergebnis zurckliefern return bValidated; } } // die testklasse class TestClass { static void Main() { // instanz der demo-klasse erzeugen XSDSchemaDemo sd = new XSDSchemaDemo(); // validieren und ergebnis ausgeben if(sd.Validate(@"c:\tmp\meteo.xml", ValidationType.Schema)) Console.WriteLine("Keine fehler, " + "Dokument gltig."); else Console.WriteLine("Dokument ist nicht gltig."); // den benutzer das konsolenfenster // schliessen lassen Console.WriteLine(); Console.Write("Press a key ...."); Console.ReadLine(); } } } Listing 8.10: Prfen von XML-Dateien mit einem XSD-Schema
ber die Auflistung Schemas der XmlValidatingReader-Klasse haben Sie Zugriff auf die einzelnen geladenen Schemata. Jeder Eintrag ist eine Instanz einer XmlSchema-Klasse und kann ber ein eigenes Obektmodell (das schema object model, SOM) verwaltet werden. Dieses Objektmodell erlaubt den programmgesteuerten Aufbau eines Schemas und hnelt sehr dem Document Object Model fr Instanzdokumente.
111
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
8.3 Zusammenfassung
Validierung ist ein wichtiges Thema fr XML-Dokumente, um sicherzustellen, dass fr eine Weiterverarbeitung alle bentigten Elemente und Attribute in der definierten Folge und mit den korrekten Datentypen vorhanden sind. Obwohl das .NET-Framework nach wie vor DTDs und XDR-Schemas untersttzt, sollten Sie Ihre Schemas nach Mglichkeit als XSD-Dateien erstellen, um alle Vorteile der XML-Werkzeuge nutzen zu knnen. Im Web finden Sie eine ganze Reihe von bereits fertigen Schemas, mit denen sich Industriebranchen oder Institutionen auf ein gemeinsames XML-Vokabular geeinigt haben (ein guter Ansatzpunkt ist beispielsweise die XML-Registry unter http://www.xml.org).
112
Sandini Bib
Essentials
.NET
9.1 Einfhrung
Thema dieses Kapitels ist die Behandlung von XML als Datentabellen. Zusammen mit der DataSet-Klasse aus System.Data bietet das XmlData Document aus dem Namensraum System.XML das Beste aus beiden Welten, relationalen Zugriff und XML-Flexibilitt. Da es zum umfangreichen Thema ADO.NET einen eigenen Band dieser Reihe geben wird, beschrnkt sich dieses Kapitel auf die XML-Seite von ADO.NET und die Kopplung des Zugriffs als relationale Sicht ber das DataSet und die DOM-Sicht ber ein XmlDataDocument. Das Beste aus zwei Welten
Besonderheit SQLServer
113
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
DataSet erstellen
Auch hier wird fr die Beispiele wieder eine XML-Datei verwendet, die eine XML-Sicht zweier verknpfter Tabellen darstellt. Da der Autor seit Jahren Sammler von Single Malt Whiskies ist, fiel die Wahl auf eine kleine Liste von Destillerien und Abfllungen. Eine DataSet-Instanz ist unabhngig von der fr die Fllung verwendeten Technologie immer eine im Speicher gehaltene, gecachte relationale Darstellung der verwendeten Tabellen. In seiner Funktionalitt noch am ehesten mit dem alten RecordSet von ADO verwandt, bietet es in Wirklichkeit eine wesentlich hhere Funktionalitt und vor allem die Mglichkeit der Beibehaltung von Relationen zwischen Datentabellen auch nach dem Schlieen der Datenbankverbindung (was beim flachgeklopften RecordSet immer ein Problem war). Anlegen eines DataSets Bevor wir also XML-Daten speichern, muss zuerst ein DataSet angelegt und mit Inhalt gefllt werden. Dies geschieht entweder ber manuelle Aufrufe zum Hinzufgen von Datenzeilen oder beispielsweise ber den Zugriff auf einen SQL-Server. Fr alle Leser, die ber keinen installierten SQL-Server verfgen, hier der Code fr die manuelle Erzeugung des DataSets, der Datentabellen und der Spalten pro Tabelle. Aus dem Code ist so leicht ersichtlich, wie Sie sich ein DataSet erstellen. Weitere Details finden Sie im Band zu ADO.NET.
static DataSet BuildDataSet() { // neue leere dataset-instanz DataSet ds = new DataSet("DataSet"); // die tabellen des datasets DataTable tblDist = new DataTable("Distillery"); DataTable tblBott = new DataTable("Bottling"); // aufbauen der ersten tabelle tblDist.Columns.Add("DistilleryID", typeof(System.Int32)); tblDist.Columns.Add("Name", typeof(System.String)); tblDist.Columns.Add("Region", typeof(System.String)); tblDist.Columns.Add("Status", typeof(System.String)); tblDist.PrimaryKey = new DataColumn[] { tblDist.Columns["DistilleryID"] }; // aufbauen der zweiten tabelle tblBott.Columns.Add("Name",
114
Sandini Bib
DataSet und Co.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
typeof(System.String)); tblBott.Columns.Add("Age", typeof(System.Int32)); tblBott.Columns.Add("Distillery", typeof(System.Int32)); tblBott.Columns.Add("Notes", typeof(System.String)); // tabellen zum dataset hinzufgen ds.Tables.Add(tblDist); ds.Tables.Add(tblBott); // relation zwischen den spalten aufbauen // und erzwingen (parameter "true") ds.Relations.Add("BottlingToDistillery", tblDist.Columns["DistilleryID"], tblBott.Columns["Distillery"], true); // das fertige dataset zurckgeben return ds; } Listing 9.1: Programmgesteuerter Aufbau eines DataSets
WriteXmlSchema
115
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
<xs:element name="Name" type="xs:string" minOccurs="0" /> <xs:element name="Region" type="xs:string" minOccurs="0" /> <xs:element name="Status" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Bottling"> <xs:complexType> <xs:sequence> <xs:element name="Name" type="xs:string" minOccurs="0" /> <xs:element name="Age" type="xs:int" minOccurs="0" /> <xs:element name="Distillery" type="xs:int" minOccurs="0" /> <xs:element name="Notes" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> <xs:unique name="Constraint1"> <xs:selector xpath=".//Distillery" /> <xs:field xpath="DistilleryID" /> </xs:unique> <xs:keyref name="BottlingToDistillery" refer="Constraint1"> <xs:selector xpath=".//Bottling" /> <xs:field xpath="Distillery" /> </xs:keyref> </xs:element> </xs:schema> Listing 9.2: Das XSD-Schema fr das Beispiel-DataSet
116
Sandini Bib
DataSet und Co.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Soll das DataSet mit Hilfe dieses Schemas erstellt werden, reicht ein Methodenaufruf aus:
static DataSet DataSetFromSchema(string filename) { DataSet ds = new DataSet(); ds.ReadXmlSchema(filename); return ds; }
Das Schema kann allerdings auch beim Lesen der Daten automatisch hergeleitet oder aus einem in der XML-Datei vorhandenen InlineSchema gelesen werden, wie der nchste Abschnitt und das nchste Listing zeigen werden.
XML-Daten laden
Jetzt kann das DataSet mit Daten gefllt werden. Nachdem das Thema dieses Bandes XML ist, werden wir das DataSet nicht per Datenbankabfrage fllen, sondern aus einer XML-Datei laden, deren Aufbau dem Schema entspricht. Dazu wird die Methode ReadXml benutzt. Anschlieend wird eine Liste der Tabellen mit der Anzahl der enthaltenen Zeilen ausgegeben
static void Main() { // dataset erstellen aus einem xsd-schema DataSet dsdemo = DataSetFromSchema("datasetdemo.xsd"); // die daten aus der xml-datei einlesen dsdemo.ReadXml("datasetdemo.xml", XmlReadMode.IgnoreSchema); // ausgabe der tabellen Console.WriteLine("Liste der Tabellen"); foreach(DataTable tbl in dsdemo.Tables) { Console.WriteLine("{0,-32} => {1} Zeilen.", tbl.TableName, tbl.Rows.Count); } Console.Write("\nPress a key ...."); Console.ReadLine(); } Listing 9.3: Fllen des DataSets aus einer XML-Datei
117
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Der letzte Parameter der Methode ReadXml verdient eine etwas genauere Erluterung. Mit diesem Parameter XmlReadMode legen Sie fest, wie die Behandlung der Schemadaten erfolgen soll. Folgende Werte sind laut Online-Dokumentation mglich:
Membername
Auto
Beschreibung
Standardeinstellung. Fhrt die am besten geeignete dieser Aktionen aus: Legt XmlReadMode auf DiffGram fest, wenn es sich bei den Daten um ein DiffGram handelt. Legt XmlReadMode auf ReadSchema fest, wenn das Dataset bereits ber ein Schema verfgt oder das Dokument ein Inlineschema enthlt. Legt XmlReadMode auf InferSchema fest, wenn das Dataset noch kein Schema aufweist und das Dokument kein Inlineschema enthlt.
DiffGram
Liest ein DiffGram, wobei die nderungen aus dem DiffGram auf das DataSet angewendet werden. Die Semantik ist identisch mit der einer Merge-Operation. Wie bei der Merge-Operation werden die RowState-Werte beibehalten. Die Eingabe in ReadXml mit DiffGrams sollte nur unter Verwendung der Ausgabe von WriteXml als DiffGram abgerufen werden. Liest XML-Dokumente, z.B. solche, die durch Ausfhren von FOR XML-Abfragen generiert werden, fr eine Instanz von SQL Server. Wenn XmlReadMode auf Fragment festgelegt ist, wird der Standardnamespace als Inlineschema gelesen. Ignoriert alle Inlineschemas und liest Daten in das vorhandene DataSet-Schema. Wenn Daten dem vorhandenen Schema nicht entsprechen, werden sie verworfen (auch die Daten aus anderen fr das DataSet definierten Namespaces). Wenn es sich bei den Daten um ein DiffGram handelt, hat IgnoreSchema dieselbe Funktion wie DiffGram.
Fragment
IgnoreSchema
118
Sandini Bib
DataSet und Co.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
Membername
InferSchema
Beschreibung
Ignoriert alle Inlineschemas, leitet das Schema von den Daten her und ldt die Daten. Wenn das DataSet bereits ein Schema enthlt, wird das aktuelle Schema durch Hinzufgen neuer Tabellen oder neuer Spalten zu vorhandenen Tabellen erweitert. Eine Ausnahme wird ausgelst, wenn die hergeleitete Tabelle bereits mit einem anderen Namespace vorhanden ist, oder wenn bei hergeleiteten Spalten ein Konflikt mit vorhandenen Spalten auftritt. Liest jedes Inlineschema und ldt die Daten. Wenn das DataSet bereits ein Schema enthlt, knnen diesem evtl. neue Tabellen hinzugefgt werden. Es wird jedoch eine Ausnahme ausgelst, wenn Tabellen im Inlineschema bereits im DataSet vorhanden sind.
ReadSchema
XML-Daten schreiben
Genauso einfach wie das Laden einer bestehenden Datei ist das Schreiben von XML-Daten mglich. Dazu wird die Methode WriteXml benutzt, bei der ber einen Parameter angegeben werden kann, ob nur die Daten oder auch das Schema als Inline-Schema geschrieben werden soll. Mchten Sie nur das Schema allein schreiben, benutzen Sie dazu die Methode WriteXmlSchema.
static void Main() { // dataset erstellen aus einem xsd-schema DataSet dsdemo = DataSetFromSchema("datasetdemo.xsd"); // die daten aus der xml-datei einlesen dsdemo.ReadXml("datasetdemo.xml", XmlReadMode.IgnoreSchema); // ausgabe der tabellen Console.WriteLine("Liste der Tabellen"); foreach(DataTable tbl in dsdemo.Tables) { Console.WriteLine("{0,-32} => {1} Zeilen.", tbl.TableName, tbl.Rows.Count); } // jetzt xml in eine andere datei schreiben dsdemo.WriteXmlSchema("ausgabe.xsd"); dsdemo.WriteXml("ausgabe.xml", XmlWriteMode.IgnoreSchema);
119
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Console.Write("\nPress a key ...."); Console.ReadLine(); } Listing 9.4: Schreiben des DataSet-Inhalts in eine Datei
Soweit die kurze Betrachung der DataSet-Klasse unter dem Gesichtspunkt XML und Schema. Als nchstes folgt die XmlDataDocument-Klasse, mit der Sie eine Kombination aus relationalem Zugriff und DOMModell erhalten.
Typisierte DataSets
Eine weitere Mglichkeit fr den Zugriff auf XML-Daten und relationale Daten ist ein streng typorientiertes DataSet, bei dem der Zugriff nicht ber die oben beschriebenen Auflistungen wie Tables erfolgt, sondern durch streng typisierte Namen. Dazu wird mit den Daten aus dem Schema eine eigene Klasse von DataSet abgeleitet und verwendet. Neben dem Vorteil der Fehlervermeidung ist der Code auch lesbarer und schneller, da auf den Zugriff ber einen Stringindex verzichtet werden kann. xsd erstellt auch DataSets Um ein solches DataSet zu erstellen, bentigen Sie zuerst das Schema. Hier wird das in Listing 9.2 gezeigte Schema benutzt. Mit Hilfe des Hilfsprogramms xsd.exe wird daraus eine Dataetklasse erzeugt: xsd /d /l:cs /n:Datasamples datasetdemo.xsd Das Tool erstellt (standardmig im gleichen Verzeichnis) eine Datei mit dem Namen datasetdemo.cs. Diese Datei ist mehrere hundert Zeilen lang und enthlt den kompletten Code fr eine abgeleitete DataSetKlasse mit dem Namen, der im Schema angegeben wurde (hier DemoData).
Abhngig davon, ob Sie mit Visual Studio .NET arbeiten oder nicht, ergeben sich nun zwei Wege: In Visual Studio .NET nehmen Sie diese Datei einfach in das Projekt auf und beim nchsten Build wird diese Datei mitbersetzt (achten Sie darauf, den korrekten C#-Namensraum anzugeben, wie oben Datasamples, der C#-Namensraum der Beispieldateien). Ohne Visual Studio .NET lassen Sie den C#-Compiler einfach ein Assembly als Bibliotheks-DLL erzeugen und referenzieren dieses dann: csc /target:library /r:system.dll,system.data.dll datasetdemo.cs Nun knnen Sie einfach eine Instanz der Klasse erzeugen und damit arbeiten. Das folgende Beispiel (diesmal nicht nur die Methode, sondern der komplette Code) ldt zuerst die Datendatei in diese Klasse, suchst dann darin nach einer bestimmten Datenzeile und fgt in der verbundenen Tabelle eine neue Zeile ein. Anschlieend wird die gesamte so erstellte XML-Struktur auf die Konsole ausgegeben.
120
Sandini Bib
XmlDataDocument
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// typisiertes dataset nutzen using System; using System.Data; using System.Data.SqlClient; namespace Datasamples { class DataSetDemo { static void Main(string[] args) { DemoData dd = new DemoData(); try { dd.ReadXml("datasetdemo.xml", XmlReadMode.Auto); } catch(Exception e) { Console.WriteLine("Exception: {0}", e.Message); } DemoData.DistilleryRow row = dd.Distillery.Select("name = 'Bowmore'")[0] as DemoData.DistilleryRow; dd.Bottling.AddBottlingRow("Bowmore Darkest", 17, row , ""); Console.WriteLine(dd.GetXml()); Console.Write("\nPress a key ...."); Console.ReadLine(); } } } Listing 9.5: Streng typisierte DataSets sind leichter lesbar.
9.3 XmlDataDocument
Die Klasse XmlDataDocument bietet eine Erweiterung von XmlDocument, um beim Zugriff auf Daten sowohl die Mglichkeiten der DataSetKlasse nutzen zu knnen als auch den Zugriff ber das Document Object Model der XML-Klassen.
121
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Grundlagen
XmlData Document, Methode Load Nach dem Erstellen einer Instanz kann ber die Eigenschaft DataSet auf das integrierte DataSet zugegriffen werden, um beispielsweise ein Schema einzulesen, mit dem das DataSet dann seine Tabellen-Auflistung anlegt. Das folgende Fragment zeigt das Aufbereiten des DataSets ber das Einlesen des Schemas, das anschlieende Laden der Daten erfolgt allerdings ber die Load-Methode der XmlDataDocument-Instanz.
XmlDataDocument datadoc = new XmlDataDocument(); datadoc.DataSet.ReadXmlSchema("datasetdemo.xsd"); datadoc.Load("datasetdemo.xml");
Die Klasse hlt die Daten in beiden Zugriffspfaden synchron, so dass Sie je nach Bedarf die entsprechende Methode benutzen knnen, ohne sich Gedanken um den Datenabgleich zwischen relationalem und DOM-Zugriff machen zu mssen.
Spezielle XmlDataDocument-Methoden
GetElement FromRow GetRowFrom Element ber die beiden Methoden GetElementFromRow und GetRowFromElement lassen sich die Daten jeweils einander zuordnen. So knnen Sie fr ein bestimmtes Element die entsprechende Datenzeile anzeigen lassen und umgekehrt. Die folgende Methode arbeitet zuerst mit den DataSet-Methoden und legt nach dem Laden der Daten aus einer XML-Datei einen Primrschlssel fr die Tabelle Distillery fest, um dann ber diesen Schlssel auf eine Datenzeile zuzugreifen. Anschlieend wird mit der Methode Get ElementFromRow auf die gleichen Daten, nur ber das DOM, zugegriffen.
// demo fuer xmldatadocument static void DataDocumentDemo() { XmlDataDocument datadoc = new XmlDataDocument(); datadoc.DataSet.ReadXmlSchema(@"c:\tmp\datasetdemo.xsd"); datadoc.Load(@"c:\tmp\datasetdemo-dataonly.xml"); // zugriff ber dataset-methoden DataTable tbl = datadoc.DataSet.Tables["Distillery"]; // primary key fuer tabelle setzen tbl.PrimaryKey = new DataColumn[] { tbl.Columns["DistilleryID"] };
122
Sandini Bib
XmlDataDocument
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
// zugriff auf eine zeile ber key DataRow row = tbl.Rows.Find(4); // ausgeben mit dataset-methoden Console.WriteLine("\nDatenzeile"); foreach(DataColumn c in tbl.Columns) Console.Write("{0} ", row[c]); Console.WriteLine(); // element zu dieser zeile holen Console.WriteLine("\nXml-Inhalt"); XmlElement elem = datadoc.GetElementFromRow(row); Console.WriteLine("Knotentyp: {0}", elem.NodeType.ToString()); Console.WriteLine(elem.OuterXml); Console.WriteLine(); } Listing 9.6: GetElementFromRow im Einsatz
Wird diese Methode ausgefhrt, zeigt die Ausgabe zweimal die gleichen Daten, nur in unterschiedlicher Darstellung (aus Grnden der besseren Lesbarkeit wurde die XMl-Darstellung umbrochen):
Datenzeile 4 Ardbeg Kildalton
Active
XML-Inhalt Knotentyp: Element <Distillery> <DistilleryID>4</DistilleryID> <Name>Ardbeg</Name> <Region>Kildalton</Region> <Status>Active</Status> </Distillery> Listing 9.7: Die Ausgabe der Methode aus Listing 9.6
123
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
static void XmlFormatDemo() { XmlDataDocument datadoc = new XmlDataDocument(); datadoc.DataSet.ReadXmlSchema("datasetdemo.xsd"); datadoc.PreserveWhitespace = true; datadoc.Load("datasetdemo.xml"); datadoc.Save("ausgabe-save.xml"); datadoc.DataSet.WriteXml("ausgabe-writexml.xml"); } Listing 9.8: Schreiben der XML-Daten auf verschiedene Weise
Preserve WhiteSpace
Je nach Einstellung der Eigenschaft PreserveWhitespace fr die Instanz von XmlDataDocument (beim Laden des Dokuments) wird nicht signifikanter Leerraum beibehalten oder nicht (die Standardeinstellung ist false). Die Methode WriteXml schreibt dagegen immer nur die signifikanten Daten ohne Leerraum. Hier ein Ausschnitt aus der mit Save geschriebenen Datei, der den in der Originaldatei vorhandenen Leerraum und Nichtdaten-Elemente beibehlt:
<!-- xml-kommentar --> <Distillery> <DistilleryID>2</DistilleryID> <Name>Laphroaig</Name> <Region>Kildalton</Region> <Status>Active</Status> </Distillery> <!-- noch ein xml-kommentar --> <Distillery> <DistilleryID>3</DistilleryID> <Name>Lagavulin</Name> <Region>Kildalton</Region> <Status>Active</Status> </Distillery>
Im Gegensatz dazu enthlt die mit der Methode WriteXml geschriebene Datei nur die Elemente, die fr den Aufbau des DataSets relevant sind. Auch beim Lesen per ReadXML wird brigens nur der Dateninhalt gelesen und ebenso Nichtdaten-Elemente und Leerraum entfernt.
124
Sandini Bib
Zusammenfassung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<Distillery> <DistilleryID>2</DistilleryID> <Name>Laphroaig</Name> <Region>Kildalton</Region> <Status>Active</Status> </Distillery> <Distillery> <DistilleryID>3</DistilleryID> <Name>Lagavulin</Name> <Region>Kildalton</Region> <Status>Active</Status> </Distillery>
9.4 Zusammenfassung
Die zentrale Rolle von XML im .NET-Framework kommt gerade bei ADO.NET deutlich zum Tragen. Als internes Format fr die Speicherung von nicht verbundenen DataSets und den Transport von Daten zwischen Maschinen und Prozessen ist XML das zentrale Format. Somit knnen Sie jede beliebige gltige XML-Datei als Tabelle laden und in Tabellenform bearbeiten oder Datentabellen als hierarchische XML-Daten ber eine Firewall hinweg per http versenden. Mit Hilfe der XmlDataDocument-Klasse sind Sie in der Lage, gleichzeitig relational mit ADO.NET-Methoden und ber das XML-Datenmodell auf ein und denselben Datenbestand zuzugreifen.
125
Sandini Bib
Sandini Bib
Essentials
.NET
10 XML-Dokumentation
C# ist derzeit die einzige Programmiersprache von Microsoft, die eine Mglichkeit zur Erstellung von XML-Kommentaren bietet. hnlich wie javadoc bei Java lassen sich somit bei Bedarf automatisch XML-Dateien erzeugen, die anschlieend mit Hilfe eines XSLT-Stylesheets in ein beliebiges Format (z.B. HTML) transformiert werden knnen. Zur Erstellung der XML-Datei mit den Dokumentationstags dient die Option /doc:<dateiname> des Compilers bzw. die Menoption ERSTELLEN VON KOMMENTARWEBSEITEN im Men EXTRAS, falls Sie Visual Studio .NET verwenden. In den Projekteinstellungen knnen Sie ebenfalls einen Namen eintragen, unter dem diese XML-Datei automatisch erstellt werden soll. C# als Vorreiter
10.1 XML-Kommentare
Erstellen von Kommentaren
Ein XML-Kommentar wird durch drei Schrgstriche (also den C#-Kommentar um einen weiteren Schrgstrich ergnzen) eingeleitet. Visual Studio .NET hilft auch hier wieder mit einem Automatismus: falls Sie den Kommantar beispielsweise ber einer Klasse oder Methode beginnen, werden automatisch Parameter ausgelesen und ein <summary>-Tag erzeugt. Sie knnen solche XML-Kommentare vor einer Klasse oder ein Mitglied der Klasse (Exception, Delegate, Methode, Eigenschaft) erstellen. XMLKommentare im Code eines Klassenmitglieds oder vor einem Namensraum werden nicht akzeptiert und der Compiler gibt eine Warnung aus:
C:\tmp>csc /doc:Class1.xml Class1.cs Microsoft (R) C#-Compilerversion 7.00.9466 fr Microsoft (R) .NET Framework Version 1.0.3705 Copyright (C) Microsoft Corporation 2001. Alle Rechte vorbehalten. Class1.cs(61,4): warning CS1587: Der XML-Kommentar ist auf keinem gltigen Sprachelement abgelegt Listing 10.1: XML-Kommentare drfen nicht berall stehen. /// startet einen XML-
Kommentar
Damit fehlt leider eine Mglichkeit, eigene XML-Tags an geeigneter Stelle im laufenden Code in die Datei einzubringen. Vielleicht integriert Microsoft diese Funktionalitt ja in die nchste Version des Frameworks.
127
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
10 XML-Dokumentation
Zur Verdeutlichung der Einsatzmglichkeiten zeigt das nachfolgende Listing einen Ausschnitt aus einer Klasse mit XML-Kommentaren:
/// <summary> /// Diese Methode fhrt die eigentliche /// Validierung durch. Fr jeden Namensraum, /// der benutzt wird, muss mit der Methode /// <c>xsc.Add("urn:meteo-demo", "meteo.xsd")</c> /// das entsprechende Schema geladen und der /// Prfix des Namensraums /// definiert werden. /// </summary> /// <param name="url">URL bzw. Dateiname der zu prfenden Datei /// </param> /// <param name="vt">Validierungstyp, entweder Auto, DTD, None, XDR /// oder Schema</param> /// <returns>true = Dokument wurde validiert, /// false = Fehler bei Validierung</returns> public bool Validate(string url, ValidationType vt) Listing 10.2: XML-Kommentare in Listings
Die Kommentarelemente
Folgende Kommentar-Tags sind im Code verwendbar
<c>
Kennzeichnet als Code zu formatierenden Text in einem Kommentar. Dieses Element ist fr Code im Flietext des Kommentars gedacht.
<code>
Kennzeichnet als Code zu formatierenden Text in einem Kommentar. Dieses Element ist fr mehrzeiligen Code und Listingsabschnitte im Kommentar gedacht.
<example>
Definiert ein Beispiel in einem Kommentar und wird meist in Kombination mit dem <code>-Element verwendet.
<exception>
Kommentiert die Exceptions, die eine Klasse auslsen kann und enthlt ein Attribut cref mit dem Inhalt einer im Kontext verfgbaren Exception-Klasse. Beispiel:
<exception cref="System.Exception"> Thrown when... </exception>
Erlaubt den Verweis auf eine andere Datei und die Einbindung von mit einem XPath-Ausdruck bereinstimmenden Elementen aus dieser Datei. Im nchsten Abschnitt finden Sie ein Beispiel zu diesem Tag (Syntax wird vom Compiler berprft).
128
Sandini Bib
XML-Kommentare
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<list>
Definiert einen Absatz. Damit lassen sich lngere Texte innerhalb des <remarks>- , <summary>- oder <return>-Elements besser strukturieren.
<param>
Bescheibt einen Parameter, der im Attribut name angegeben wird und in einfachen Anfhrungszeichen angegeben werden muss. Der Text des Elements ist die Beschreibung des Parameters (Syntax wird vom Compiler berprft).
<paramref>
Verweist auf einen Parameter im Code. Der Name des Parameters wird als Werts fr das Attribut name in doppelten Anfhrungszeichen angegeben (Syntax wird vom Compiler berprft).
<permission>
Dient der Dokumentation des Zugriffs auf ein Mitglied der Klasse und enthlt ein Attribut cref, dessen Wert in doppelten Anfhrungszeichen ein im Kontext ereichbares PermissionSet darstellt (Syntax wird vom Compiler berprft).
<remarks>
Dient der Beschreibung einer Klasse oder eines Mitglieds der Klasse und kann zustzlichen, lngeren Text enthalten, whrend <summary> eher fr eine kurze zusammenfassende Beschreibung ohne Beispiele oder Code gedacht ist.
<returns>
Definiert einen Link auf ein Mitglied der Klasse, das als Wert fr das Attribut cref in doppelten Anfhrungszeichen angegeben wird (Syntax wird vom Compiler berprft).
<seealso>
Definiert einen Link auf ein Mitglied der Klasse, das als Wert fr das Attribut cref in doppelten Anfhrungszeichen angegeben wird. <seealso> dient dazu, diesen Link unter dem Abschnitt "Siehe auch" auszugeben. Wenn Sie die XML-Datei selbst verarbeiten, knnen Sie <see> und <seealso> nach eigenen Wnschen aufteilen (Syntax wird vom Compiler berprft).
<summary>
bersichtsartige Beschreibung eines Klassenmitglieds, die von Visual Studio .NET auch fr die Anzeige von Quicktipps bei IntelliSense verwendet wird. Fr eine lngere Beschreibung des Datentyps selbst sollten Sie zustzlich <remarks> verwenden.
129
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
10 XML-Dokumentation
<value>
Dokumentiert eine Eigenschaft der Klasse. Geben Sie hier Informationen ber den Typ und die Verwendung der Eigenschaft an. Darber hinaus knnen Sie bei Bedarf eigene XML-Elemente benutzen. Solange es sich bei den verwendeten Konstrukten um wohlgeformtes XML handelt, sind Sie vllig frei in der Verwendung eigener Elemente wie z.B. <devname></devname>, <checked /> oder anderen Elementen, die natrlich auch Attribute beinhalten drfen.
130
Sandini Bib
XML-Kommentare
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
<members name="test2"> <summary> The summary for this other type. </summary> </members> </DemoClass> Listing 10.4: Eine reine Kommentardatei zur Einbindung per <include>
Damit ist unter Umstnden zwar wieder eine Trennung von Code und Dokumentation verbunden, was aus softwaretechnischer Sicht nicht optimal ist. Als Vorteil bietet sich hier aber die Mglichkeit, diesen Teil automatisiert zu generieren oder per XSLT aus einem XML-fhigen Case-Tool herzuleiten. Auch eine Weiterverarbeitung dieser Datei mit anderen Tools wie zur Erstellung von Hilfedateien (HTML Help Workshop) ist denkbar. Generell liegt der Vorteil der XML-Kommentare weniger in der Verwendung als im Code vorhandener Dokumentation fr den Endanwender der Applikation, sondern in einer Hilfestellung fr die Benutzer von Bibliotheken, die mit C# erstellt werden. Hier ist ein Entwickler, der Klassenbibliotheken benutzen mchte, auf eine gute und aktuelle Dokumentation der Schnittstellen angewiesen. Durch die Integration dieser Informationen in die Quellcodedatei wird es dem Programmierer leicht gemacht, diese aktuell und mit der Funktionalitt des Codes synchron zu halten. Auch wenn damit ein etwas hherer Aufwand bei der Erstellung des Codes verbunden ist, sollten Sie daran denken, dass Quellcode Dutzende Male fter gelesen als geschrieben wird und jede Zeile, die das Verstndnis beim Lesen erleichtert, effektiv Zeit einspart.
Kommentardatei erstellen
Mit Hilfe der Option /doc:<dateiname> wird die XML-Datei mit den Informationen generiert. Alternativ knenn Sie diese Option auch in Visual Studio .NET festlegen, indem Sie in den Eigenschaften des Projektes den Ordner KONFIGURATIONSEIGENSCHAFTEN anklicken und dort in der Seite ERSTELLEN das Feld XML-DOKUMENTATIONSDATEI eintragen. Die generierte XML-Datei lst bei den Elementen, fr die der Compiler die Syntax berprft, die Referenzen auf die Mitglieder der Klasse oder zu anderen Typen auf und generiert dazu eine eindeutige Bezeichnung des Typs, die Sie in einer weiterverarbeitenden Anwendung benutzen knenn. Datentypen erhalten eine ID
131
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
10 XML-Dokumentation
Diese ID ist wie folgt aufgebaut: Der erste Teil der ID-Zeichenfolge kennzeichnet die Art des zu identifizierenden Members durch ein einzelnes Zeichen, gefolgt von einem Doppelpunkt. Die folgenden Membertypen werden verwendet: Zeichen
N T F P M E !
Beschreibung
Namespace Typ: Klasse, Schnittstelle, Struktur, Auflistung, Delegat Feld Eigenschaft, einschlielich Indexer Methode, Konstruktoren, Operatoren usw. Ereignis Fehlerzeichenfolge; der Rest der Zeichenfolge stellt Informationen ber den Fehler bereit. Vom C#-Compiler werden Fehlerinformationen fr Links, die nicht aufgelst werden knnen, erstellt.
Beim zweiten Teil der Zeichenfolge handelt es sich um den voll gekennzeichneten Namen eines Elements, beginnend mit dem NamespaceStammverzeichnis. Der Name des Elements und die umschlieenden Typen sowie der Namensraum sind durch Punkte getrennt. Wenn der Name des Elements selbst Punkte enthlt, werden sie durch ein Nummernzeichen (#) ersetzt. Es wird vorausgesetzt, dass kein Element ein Nummernzeichen direkt im Namen aufweist. Der voll gekennzeichnete Name des String-Konstruktors wrde beispielsweise "System.String.#ctor" lauten. Wenn es sich bei Eigenschaften und Methoden um Argumente der Methode handelt, folgt die in Klammern eingeschlossene Argumentliste. Wenn keine Argumente vorhanden sind, werden keine Klammern verwendet. Die Argumente werden durch Kommas voneinander getrennt. Die Codierung jedes Arguments erfolgt genauso wie die Codierung in einer .NET Framework-Signatur. Hier ein Beispiel fr eine generierte Datei mit ID-Zeichenfolgen:
<?xml version="1.0"?> <doc> <assembly> <name>Class1</name> </assembly> <members> <member name="T:NamespaceSamples.XSDSchemaDemo"> <summary> Die Demo-Klasse fr die XSD-Validierung. Wird von <see cref="M:NamespaceSamples.TestClass.Main">Main()</see> aufgerufen.
132
Sandini Bib
XML-Kommentare
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
</summary> </member> <member name="F:NamespaceSamples.XSDSchemaDemo.bValidated"> <summary> privates Feld, gibt an, ob die validierung geglckt ist. </summary> </member> <member name="M:NamespaceSamples.XSDSchemaDemo.ValidationSink (System.Object,System.XML.Schema.ValidationEventArgs)"> <summary> Ereignisbehandlungsroutine fr die validierung der datei </summary> <param name="sender">das ereignisauslsende objekt</param> <param name="args"> <c>ValidationEventArgs</c>, enthalten die parameter fuer das ereignis <seealso cref="T:System.XML.Schema.ValidationEventArgs"/> </param> </member> <member name="M:NamespaceSamples.XSDSchemaDemo.Validate (System.String,System.XML.ValidationType)"> <summary> Diese Methode fhrt die eigentliche Validierung durch. Fr jeden Namensraum, der benutzt wird, muss mit der Methode <c>xsc.Add("urn:meteo-demo", "meteo.xsd")</c> das entsprechende Schema geladen und der Prfix des Namensraums definiert werden. </summary> <param name="url">URL bzw. Dateiname der zu prfenden Datei</param> <param name="vt">Validierungstyp, entweder Auto, DTD, None, XDR oder Schema</param> <returns>true = Dokument wurde validiert, false = Fehler bei Validierung</returns> </member> <member name="T:NamespaceSamples.TestClass"> <summary> Testklasse fr die Validierung mit XSD-Schema </summary> </member> <member name="M:NamespaceSamples.TestClass.Main"> <summary> Main-Methode fr die Testklasse, hier geht's los. </summary> <remarks> Der Code <code>
133
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
10 XML-Dokumentation
Console.WriteLine(); Console.Write("Press a key ...."); Console.ReadLine(); </code> dient nur dazu, das konsolenfenster solange offen zu halten, bis der benutzer mit ENTER das fenster schliesst. </remarks> </member> </members> </doc> Listing 10.5: Die erstelle XML-Dokumentationsdatei
Diese Datei kann nun mit Hilfe eines XSL-Stylesheets und einer Instanz der XslTransform-Klasse in einer nur wenige Zeilen langen Konsolenanwendung in eine optisch ansprechendere Form gebracht oder in ein Updategram zur Speicherung in einer Datenbank konvertiert werden. Auch hier automatisiert Visual Studio .NET mit dem Menpunkt ERSTELLEN VON KOMMENTARWEBSEITEN im Men EXTRAS den grten Teil der Arbeit.
10.2 Zusammenfassung
Obwohl noch einige Wnsche offen bleiben (wie eigene Tags oder die Einbeziehung von Kommentaren innerhalb des Codes eines Klassenmitglieds) ist die Mglichkeit zur Dokumentation des Codes mit Hilfe von XML ein guter Ansatz und erleichert das automatisierte Erstellen von Dokumentationen im XML-Format deutlich. ber XSL-Stylesheets ist zudem die Transformation der so gewonnen Daten in ein anderes Format sehr leicht mglich.
134
Sandini Bib
Essentials
.NET
11 Ausblick
Dieser Band sollte Ihnen als Entwickler einen kompakten Schnellstart in die produktive Arbeit ermglichen, wie der Titel Essentials nahelegt. Fr eine komplette und ausfhrliche Behandlung aller Aspekte von XML in .NET wre wohl der zehnfache Umfang notwendig. Natrlich fehlt noch eine ganze Menge: das Thema Web Services und SOAP nutzt XML als integralen Bestandteil, ADO.NET konnte nur kurz gestreift werden und die XML-Konfigurationsdateien und Sicherheitseinstellungen der Applikationen wren ebenso einen eigenen Band in dieser Reihe wert. XPointer und XQuery sind dem Schwerpunkt .NET-XML zum Opfer gefallen. Auch bei ASP.NET ist nicht alles HTML, sondern auch hier ist XML ein wichtiger Bestandteil. Fr ASP.NET Services und ADO.NET mchte ich an dieser Stelle an die entsprechenden Bnde meiner Autorenkollegen und -kolleginnen in der .NET-Essentials-Reihe verweisen. Fr die anderen Themen sind bereits weitere Ausgaben zu dieser Reihe in Planung. Da das Thema XML in all seinen Facetten in jedem Bereich von .NET erscheint, sei es nun die XML-Abfrage beim SQL-Server 2000 oder eine Sicherheitsrichtlinie fr .NET-Applikationen, hat auch Microsoft die immense Bedeutung erkannt und bietet in der Online-Dokumentation zum .NET-Framework und auch in der MSDN-Bibiothek (http:// msdn.microsoft.com) eine ganze Reihe von Grundlagenartikeln und weiterfhrenden Whitepapers an. Whrend der Arbeit an einem solchen Buch entwickeln sich auch die Standards im XML-Bereich weiter. XPath 2.0, XML 2.0 und die XQueryLanguage, die XSL Formatting Objects und andere neue Entwicklungen sind teilweise noch nicht einmal als Empfehlung des W3C verabschiedet worden. Im Grafikbereich existieren mit VML und SVG zwei Standards, die miteinander um den Platz als Vektorgrafikstandard fr das Web konkurrieren (wobei die persnliche Vorliebe des Autors SVG gilt). Das Thema XML-Schemas (XSD) wird von vielen Stellen als zu komplex und nicht die Vorgaben erfllend (leichtverstndlich, knapp) beurteilt und auch hier sind (beispielsweise mit Relax NG) alternative Entwicklungen im Gange. Dennoch wird sich der XSD-Standard nach Meinung des Autors durchsetzen, da mit Hilfe von annotated schemas und den Mglichkeiten von XSD, Vererbungen auszudrcken, eine grere Flexibilitt als bei reinen Mustergrammatiken oder DTDs besteht. In den Folgebnden der .NET-Essentials werden diese und weitere Themenkomplexe aufgegriffen. Die Autoren freuen sich darauf, Sie mit weiteren Informationen aus der Praxis in kompakter Form zu versorgen.
135
Sandini Bib
Sandini Bib
Essentials
.NET
Stichwortverzeichnis
! .NET-Namensrume 12 /doc 127 A AddNamespace 73 ADO.NET 113 Grundlagen 113 Programmiermodell 113 Attribute, XmlAttributeCollection 43 Attributes, Auflistung 43 C CDATA 10 CreateAttribute 46 CreateNavigator 61 D DataSet 113 erstellen 114 Tables-Auflistung 114, 120 typisiert 120 XML laden 117 XML schreiben 119 Deserialisierung 29 DOCTYPE 91 Document Object Model siehe DOM Dokumentationstags 127 Dokumentbaum 39 DOM 39 Inhalte ndern 44 DTD 89 Alternativen 96 Aufbau 89 intern, extern 91 validieren 92 E Elemente, DOM 40 Entitten siehe Entities Entities 10 Ereignisbehandlung, XmlDocument 48 Ereignisse Serialisierung 35
XmlDocument 48 XmlValidatingReader 94 Evaluate 63
G GetElementFromRow 122 GetElementsByID 42 GetRowFromElement 122 Gltigkeit, XML-Dokument 11 I IEnumerable 73 InnerText 41 IXPathNavigable 61 K Knoten, aktueller 16 Knotenmengen, auswhlen 62 Knotentypen 17 Kommentar, XML 10, 127 Kommentardatei 131 Kompilieren, XPath-Ausdrcke 64 Kontextknoten, XPath 55 L Leerraum, XML 9 Load, XmlDocument 39 LoadFromXml, komplexe Datentypen 33 LoadXml 40 N Namensrume 11 NodeChanged, XmlDocument 49 NodeInserted, XmlDocument 49 NodeType 40 noNamespaceSchemaLocation 109 O OuterXml 41 P Prfix, Namensrume 67
137
Sandini Bib
Essentials
.NET
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Stichwortverzeichnis
R ReadXML 124 ReadXml 118 RemoveAll 45, 52 RemoveAttribute 47 RemoveChild 45 S SaveToXml, komplexe Datentypen 33 SchemaLocation 109 SelectNodes, Funktionen 59 SelectSingleNode, Funktionen 59 Serialisierung 27 komplexe Datentypen 33 Steuerung der 32 XML 27 XML-Inhalte 29 SetContext 74 Streaming, XML lesen und schreiben 15 Stylesheet 79 System.Data.OleDb 113 System.Data.SqlClient 113 System.Xml 13 System.Xml.Schema 13 System.Xml.Serialization 13 System.Xml.XPath 13 System.Xml.Xsl 13 T targetNamespace 68 Transform 82 Transformationen, optimieren 86 Typisierte DataSets 120 U Unbekanntes XML, Serialisierung 35 UnknownAttribute, Serialisierung 35 UnknownElement, Serialisierung 35 UnknownNode, Serialisierung 35 URI 67 V Verarbeitungsanweisung, XML 10 W Wohlgeformtheit, XML-Dokument 11 WriteElementString 22 WriteEndDocument 22 WriteEndElement 22 WriteFullEndElement 23
X XDR 96 XML Baumstruktur 9 Dateien schreiben 21 Entity 10 Leerraum 9 Lesen von Dateien 15 und Daten 113 XmlAttributeCollection 43 XmlDataDocument 121 Load 122 Methoden 122 XmlDocument 39 XML-Dokumentation 127 XML-Dokumentationsdatei 131 XML-Dokumente 39 Streaming oder DOM 39 validieren 89 XmlElement, Attributbehandlung 47 XML-Kommentare 127 Datei erstellen 131 Dateien einbinden 130 Elemente 128 XML-Namensrume 12, 67 Grundlagen 67 URI 67 Validierung 75 XmlNamespaceManager 72 Namenstabellen 72 XmlNode 40 XmlNodeList 42 XPath 59 XmlReader 15 XmlReadMode 118 XmlResolver 82 XML-Schema 68, 96 attributeFormDefault 75 aus Tabellen 105 elementFormDefault 75 erstellen 98 Grundlagen 89 Namensrume 68 Visual Studio-Designer 101
138
Sandini Bib
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
Essentials
.NET
XmlSchemaCollection 75 Add 109 XmlSerializer 36 XML 27 XmlTextReader 16, 23 XmlTextWriter, Namensrume 70 XmlUrlResolver 81 XmlValidatingReader 92 Schemas-Auflistung 111 XmlWriter 15 Namensrume 70 XPath 53 Achsen 55 Ausdrcke 53 Evaluate 63 Funktionen 57 Grundlagen 53 Kontextknoten 55 Namensrume 74 Prdikate 56 Select-Methode 62 XPathNavigator 61 XPath-Abfrage, SelectNodes 59 XPath-Ausdrcke, kompilieren 64 XPathDocument 61 XPathExpression 64 SetContext 74 XPathNavigable 87 XPathNavigator 61 Clone 63 CreateNavigator 61 Matches 61 MoveTo 61 MoveToAttribute 61 MoveToFirst 62
MoveToFirstAttribute 62 MoveToFirstChild 62 MoveToFirstNamespace 62 MoveToId 62 MoveToNamespace 62 MoveToNext 62 MoveToNextAttribute 62 MoveToNextNamespace 62 MoveToParent 62 MoveToPrevious 62 MoveToRoot 62 Navigationsmethoden 61 XPathNodeIterator 62 Current 63 XSD 96 Grundlagen 96 xsd, Klassen erzeugen 30 xsd.exe Datenschema 105 Klassenschema 108 Schema erstellen 98 XSD-Schema 109 DataSet erstellen 115 XSD-Validierung 109 XSL 79 Stylesheet 79 Templates 80 XML-Strukturtransformation 84 XPath-Ausdrcke 80 XSL-Stylesheets 87 Aufbau 80 laden 81 XSLT 79 XslTransform 82 XSL-Transformationen 79 verketten 86
139
Sandini Bib
... aktuelles Fachwissen rund, um die Uhr zum Probelesen, Downloaden oder auch auf Papier. www.InformIT.de
InformIT.de, Partner von Addison-Wesley, ist unsere Antwort auf alle Fragen der IT-Branche. In Zusammenarbeit mit den Top-Autoren von Addison-Wesley, absoluten Spezialisten ihres Fachgebiets, bieten wir Ihnen stndig hochinteressante, brandaktuelle Informationen und kompetente Lsungen zu nahezu allen IT-Themen.
www.InformIT.de
Sandini Bib
Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen eBook-Zusatzdaten sind urheberrechtlich geschtzt. Dieses eBook stellen wir lediglich als persnliche Einzelplatz-Lizenz zur Verfgung! Jede andere Verwendung dieses eBooks oder zugehriger Materialien und Informationen, einschliesslich der Reproduktion, der Weitergabe, des Weitervertriebs, der Platzierung im Internet, in Intranets, in Extranets, der Vernderung, des Weiterverkaufs und der Verffentlichung
bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder nderung des vom Verlag vergebenen Passwortschutzes ausdrcklich untersagt! Bei Fragen zu diesem Thema wenden Sie sich bitte an: info@pearson.de Zusatzdaten Mglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfgungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen. Hinweis Dieses und viele weitere eBooks knnen Sie rund um die Uhr und legal auf unserer Website
http://www.informit.de herunterladen