You are on page 1of 141

Sandini Bib

XML mit .NET

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

Grafikprogrammierung mit System.Drawing Vektorgrafiken, Bildbearbeitung, Texteffekte inkl. Farbteil

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

Weitere Informationen finden Sie unter www.dotnet-essentials.de.

Unser Online-Tipp fr noch mehr Wissen

... aktuelles Fachwissen rund um die Uhr zum Probelesen, Downloaden oder auch auf Papier.

www.InformIT.de

Sandini Bib

Essentials

.NET

Armin Hanisch

XML mit .NET


Programmierung und Basisklassen

An imprint of Pearson Education


Mnchen Boston San Francisco Harlow, England Don Mills, Ontario Sydney Mexico City Madrid Amsterdam

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

XmlReader und XmlWriter


Lesen von XML-Daten Schreiben von XML-Dateien Zusammenfassung

15
15 21 26

3
3.1 3.2

Serialisierung und XML


XML-Serialisierung im Detail Zusammenfassung

27
32 37

4
4.1 4.2 4.3 4.4 4.5

Document Object Model


Streaming oder DOM? XML-Dokumente laden und lesen ndern von XML-Dokumenten per DOM Ereignisbehandlung Zusammenfassung

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

Validieren von XML


Warum ein Schema? XSD der Standard Zusammenfassung

89
89 96 112

9
9.1 9.2 9.3 9.4

XML und Daten


Einfhrung DataSet und Co. XmlDataDocument Zusammenfassung

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.

Beispielcodes, Errata, Hinweise


Die Beispielcodes zu diesem Band der Reihe .NET-Essentials finden Sie im Internet unter dem URL http://www.DotNet-Essentials.de. Hier finden Sie auch zustzliche Hinweise, Ergnzungen und Korrekturen zu diesem und den anderen Bnden der Reihe. Alle Listings, Codeangaben und Verweise in diesem Buch wurden nach bestem Wissen und Gewissen auf Fehlerfreiheit geprft. Sollten Sie dennoch einen Fehler finden oder Anregungen und Kommentare zu diesem Buch haben, freut sich der Autor auf Ihr Feedback.

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

XML-Zeichen und XML-Einheiten


Eine XML-Datei besteht aus verschiedenen Einheiten: Kommentaren, Leerraum, Verarbeitungsanweisungen oder Elementen. Auch hier gelten einige Regeln, ebenso wie fr die Angabe von bestimmten Zeichen innerhalb einer XML-Datei. Leerraum wird innerhalb einer XML-Datei ignoriert oder beim Parsing mit beachtet, abhngig von der Einstellung der entsprechenden Klasse. Im .NET-Framework geschieht dies ber eine Eigenschaft mit dem Namen PreserveWhitespace. Ist Leeraum innerhalb eines Elements von Bedeutung, beispielsweise fr die Einrckung in einem Listing, dann sollten Sie das Attribut xml:space verwenden und einen Wert von "preserve" setzen. Der Defaultwert "default" legt fest, dass die Einstellungen des Parsers verwendet werden. Leerraum

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

PIs <? ?>

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
&amp; &lt; &gt; &quot; &apos; &#00; &#x00;

Bedeutung
Das &-Zeichen Das <-Zeichen Das >-Zeichen Das "-Zeichen Das '-Zeichen Das Zeichen mit dem Code 00 Das Zeichen mit dem hexadezimalen Code 00

Tabelle 1.1: Vordefinierte Entittszeichen in XML

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

Gltig oder wohlgeformt


Im Gegensatz zum butterweichen HTML-Standard mssen XMLStrukturen wesentlich strikteren Regeln folgen. Dabei wird zwischen einem gltigen und einem wohlgeformten Dokument unterschieden. Wir kommen gleich auf diesen Unterschied zurck. Generell gelten fr XML-Strukturen die folgenden Regeln:

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 &gt;. 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

1.3 Die .NET-Namensrume


Die gesamte Funktionalitt der XML-Basisklassen ist in dem ffentlichen Assembly System.Xml.dll enthalten, das im globalen Assemblycache liegt. Aus Grnden der bersichtlichkeit wurden die einzelnen Funktionsblcke in verschiedene Namenspaces unterteilt. System.Xml Hier finden sich die allgemeinen Klassen und Typen wie XmlReader und XmlWriter. System.Xml.XPath Dieser Namensraum beinhaltet alle Typen, die fr die Abfrage von Xml-Strukturen mit Hilfe der XPath-Sprache bentigt werden. System.Xml.Xsl Die Transformation von Xml-Strukturen in andere Formate oder einen anderen Aufbau der Xml-Struktur wird durch die Datentypen in diesem Namensraum ermglicht. In der Literatur (und auch im .NET-Framework) finden Sie manchmal anstelle der Abkrzung XSL auch die Ablrzung XSLT. System.Xml.Schema In diesen Namensraum befinden sich die Datentypen zur Validierung von Xml-Strukturen auf Gltigkeit und die Klassen fr das Schema Object Model, das, hnlich wie das Document Object Model fr Dokumente, fr die Baumdarstellung von Schemas vorhanden ist. System.Xml.Serialization Hier finden Sie die Klassen fr die Serialisierung von Instanzen in eine XML-Datei. Auf eine Auflistung aller in den jeweiligen Namensrumen enthaltenen Klassen wird hier aus Platzgrnden verzichtet. Erstens macht es keinen Sinn, hier einfach Informationen zu wiederholen, die Sie genauso gut in der Online-Hilfe zum .NET-Framework finden, zum anderen ist auf Grund der Konzeption dieses Buches auch gar kein Platz fr ellenlange Tabellen.

1.4 Untersttzte Standards


Microsoft hat sich bei der Planung der .NET-Initiative bemht, bestehende und in Planung befindliche offene Standards so gut als mglich einzuhalten. Fr den Bereich XML finden Sie hier eine Liste der untersttzten Standards mit dem URL fr weitere Informationen:

13

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

1 XML-Basics

Die wichtigsten Standards

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

XmlReader und XmlWriter

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.

2.1 Lesen von XML-Daten


Die .NET-Laufzeitumgebung untersttzt fr den Zugriff auf XMLDateien sowohl den DOM-Ansatz als auch einen Streaming-Zugriff hnlich SAX. Mssen Sie innerhalb des Dokumentes navigieren oder wahlfrei schreiben, bleibt nur das Document Object Model, welches eine Baumstruktur aller Knoten im Speicher aufbaut. Sicherlich nicht gerade ressourcenschonend, aber mit allen Mglichkeiten der Manipulation der einzelnen XML-Elemente und ihrer Inhalte.

Die Arbeitsweise des XmlReaders


Der andere Ansatz ist eine Art Streaming der XML-Dokumente, eine Methode, die bereits seit lngerem von beipielsweise dem SAX-Protokoll verfolgt wird. Hier sind die Anforderungen an die Ressourcen wesentlich geringer. Im Gegensatz zu SAX implementiert XmlReader aber ein Pull-Modell, bei dem die Applikation die Daten abholt und daher auch uninteressante Teile der Datei berlesen lassen kann. Diese Art von Zugriff wird (beipielsweise in der Datenbankwelt) auch oft als Firehose Cursor bezeichnet, da nur vorwrts lesend durch die Datei gegangen wird und dies (analog dem Feuerwehrschlauch) die Methode mit dem besten Durchsatz darstellt. Von der abstrakten Klasse XmlReader abgeleitet existieren im .NETFramework drei Klassen: XmlTextReader, XmlNodeReader und die Klasse XmlValidatingReader, die eine Mglichkeit der berprfung auf Gltigkeit des Dokumentes erlaubt. Die Klasse XmlReader und die davon abgeleiteten Klassen arbeiten mit einem depth first-Ansatz, d.h. es wird zuerst innerhalb eines Knotens in die Tiefe gesucht und danach werden die Geschwisterknoten des aktuellen Knotens abgearbeitet. Firehose = Feuerwehrschlauch, Fachausdruck fr schnellsten Zugriff

15

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

2 XmlReader und XmlWriter

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.

Das Konzept des aktuellen Knotens


Die .NET-Laufzeitumgebung implementiert das Konzept eines aktuellen Knotens. Beim Lesen mit einer XmlReader-Instanz wird dieser aktuelle Knoten ber die verschiedenen Methoden immer weiter nach vorne bewegt, bis das Ende einer Datei erreicht wird. Dieser aktuelle Knoten ist nicht notwendigerweise immer ein XML-Element. Die Eigenschaft NodeType des XmlReaders enthlt einen der folgenden Werte, die im Namensraum System.XML in der Aufzhlung XmlNodeType definiert 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>

Comment Document DocumentFragment DocumentType Element EndElement

Tabelle 2.1: Die von XmlReader gelieferten Knotentypen

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. &auml; 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.

Tabelle 2.1: Die von XmlReader gelieferten Knotentypen (Fortsetzung)

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

2 XmlReader und XmlWriter

<airtrend>rising</airtrend> </station> </weatherdata> Listing 2.2: Die Beispieldatei mit XML-Inhalt

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

2 XmlReader und XmlWriter

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

Fehlerbehandlung beim Lesen


Wird die Wohlgeformtheit des Dokuments durch eine ungltige XMLKonstruktion verletzt, wird eine XmlException ausgelst und der Lesevorgang abgebrochen.

Lesen bestimmer Elemente und Datentypen


Leere Elemente finden Fr viele Anwendungszwecke muss sichergestellt werden, dass der aktuelle Knoten ein bestimmtes Element enthlt. Hierzu exisitieren weitere Methoden der XmlReader-Klasse, die ein bestimmtes Element erwarten. So kann mit der Methode IsStartElement festgestellt werden, ob der aktuelle Knoten ein Starttag ist, whrend beispielsweise IsEmptyElement dann true liefert, wenn es sich um ein leeres Element in der Form <tagname /> handelt. Die Methode ReadStartElement erlaubt das Lesen ganz bestimmter Elemente und ein manuelles Parsing der Datei, so dass eine Exception ausgelst wird, wenn das Element nicht den erwarteten Namen besitzt.

20

Sandini Bib
Schreiben von XML-Dateien
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

2.2 Schreiben von XML-Dateien


Das Schreiben von XML-Daten als Strom erfolgt mit Hilfe einer von der abstrakten Klasse XmlWriter abgeleiteten Klasse. In der aktuellen Version des .NET-Frameworks existiert eine Implementierung in der Klasse XmlTextWriter, die auch fr die folgenden Beispiele benutzt wird.

Instantiierung der Klasse


Der Konstruktor der Klasse XmlTextWriter ist dreifach berladen. Sie akzeptiert entweder einen vorhandenen TextWriter, einen Stream oder einen Dateinamen als Parameter, wobei fr den Dateinamen und den IO-Stream als zweiter Parameter noch die Codierung der Zeichen angegeben werden kann (wird dieser auf null gesetzt, erfolgt die Ausgabe mit der Standardcodierung UTF-8).
// instanz per dateinamen erzeugen // die datei wird bei existenz neu berschrieben XmlTextWriter xtw = new XmlTextWriter(@"c:\tmp\ausgabe.xml", null); Listing 2.5: Beispiel-Instantiierung per Dateinamen fr XmlTextWriter

Schreiben von Elementen und Attributen


Die Methoden zum Erstellen des Inhaltes sind leicht zu finden und anzuwenden, deren Namen sind ebenfalls weitestgehend selbsterklrend. Das folgende Beispiel zeigt eine Methode zum Schreiben einer einfachen XML-Datei.
public static void DemoXmlTextWriter() { // instanz erzeugen XmlTextWriter xtw = new XmlTextWriter(@"c:\tmp\ausgabe.xml", null); // inhalte schreiben xtw.WriteStartElement("buecher"); xtw.WriteElementString("titel", "Von Windows verweht ..."); xtw.WriteStartElement("preis"); xtw.WriteAttributeString("waehrung","EUR"); xtw.WriteString("14.55"); xtw.WriteEndElement(); xtw.WriteEndElement(); // writer schliessen

21

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

2 XmlReader und XmlWriter

xtw.Close(); Console.WriteLine("Datei geschrieben."); } Listing 2.6: Schreiben von XML, die erste Version

WriteStartElement vs. WriteElement String

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.

XML mit XmlWriter und XmlReader modifzieren


Als Abschluss fr dieses Kapitel ein kleines Beispiel, wie mit Hilfe dieser Streamingklassen auch groe Dateien ressourcenschonend verarbeitet werden knnen. Nehmen wir an, in einer als XML-Datei vorliegenden Bcherliste soll die Umstellung von DEM auf EUR vorgenommen werden (gut, dass wir das schon alle hinter uns haben!). Mit einem XmlTextReader werden die einzelnen Knoten gelesen und ber eine XmlTextWriterInstanz in die Ausgabedatei geschrieben. Wird ein Element mit dem Namen Preis angetroffen, wird dessen Textinhalt von Mark nach Euro

23

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

2 XmlReader und XmlWriter

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

2 XmlReader und XmlWriter

<?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

Serialisierung und XML

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

Serialisierung mit XmlSerializer


Die Klasse XmlSerializer ist fr die Serialisierung einer Instanz in eine XML-Datei bzw. den umgekehrten Weg zurck zu einer Instanz zustndig. In der einfachsten Form erhlt der Konstruktor einen Parameter mit dem Typ des Objekts, fr das er zustndig sein soll. Hier eine sehr einfache Demoklasse, die in eine XML-Datei serialisiert werden soll:
// eine einfache demo-klasse public class SimpleDemo { public string Kennzeichen; public int KmStand; public double Verbrauch; } Listing 3.1: Die erste Demoklasse

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

3 Serialisierung und XML

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).

Deserialisierung mit XmlSerializer


Um aus einer XML-Datei eine Instanz einer Klasse zu laden, gehen sie einfach den umgekehrten Weg.
class TestClass { static void Main(string[] args) { XmlSerializer ser = new XmlSerializer(typeof(SimpleDemo)); // diesmal einen reader einsetzen XmlTextReader rdr = new XmlTextReader("ausgabe.xml"); SimpleDemo d; // klasseninstanz aus dem serializer d = ser.Deserialize(rdr) as SimpleDemo; rdr.Close(); // instanzdaten ausgeben Console.WriteLine("Objekt deserialisiert:"); Console.WriteLine(d.Kennzeichen); Console.WriteLine(d.KmStand); Console.WriteLine(d.Verbrauch); Console.Write("\nPress a key ...."); Console.ReadLine(); } } Listing 3.4: Deserialisierung aus einer XML-Datei

Abbildung 3.1: Die Ausgabe des Deserialisierungsbeispiels

29

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

3 Serialisierung und XML

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.

Ungleiche Dokumente und Klassen


Falls ein Schema vorliegt, knnen Sie mit dem folgenden Aufruf aus dem Schema eine passende Klasse erstellen lassen, um dieses Problem zu vermeiden. Das Tool xsd.exe xsd schema0.xsd /classes Anschliessend wird eine Datei schema0.cs erzeugt, die eine Klasse mit den aus dem Schema gewonnen Feldern enthlt.
//----------------------------------------------------// <autogenerated> // This code was generated by a tool. // Runtime Version: 1.0.3705.0 // // Changes to this file may cause // incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //----------------------------------------------------// // This source code was auto-generated by xsd, Version=1.0.3705.0. // using System.XML.Serialization;

/// <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

Zustzlicher Inhalt in der XML-Datei

Bei der Ausfhrung des Programms erfolgt keine Fehlermeldung und die Ausgabe zeigt das Standardverhalten bei der Behandlung unbekannter Elemente in der XML-Datei:

Abbildung 3.2: Deserialisierung mit den genderten Daten

31

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

3 Serialisierung und XML

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.

3.1 XML-Serialisierung im Detail


Steuerung der XML-Struktur
Den Serialisierungsprozess, genauer die Erstellung der XML-Datei, knnen Sie ber den Einsatz verschiedener Attribute steuern. So mchten Sie vielleicht einige Felder der Klasse nicht als eigene Unterelemente, sondern als Attribute des Klassenelementes rendern lassen oder fr einige Elemente den Datentyp ndern. Serialisierungs-Attribute Um das Wurzelelement der XML-Datei zu ndern, benutzen Sie vor der Klasse das Attribut [XmlRoot()]. Das Attribut [XmlElement] dient der Definition eines anderen Elementnamens, der vom Namen des Feldes abweicht. Mit Hilfe des Attributes [XmlAttribute] knnen Sie angeben, dass ein Feld nicht als eigenes Element, sondern als Attribut des umgebenden Elternelements gerendert wird.
// eine einfache demo-klasse [XmlRoot(ElementName = "root")] public class SimpleDemo { public string Kennzeichen; public int KmStand; [XmlIgnore] public double Verbrauch; [XmlAttribute(AttributeName = "marke")] public string Hersteller; } Listing 3.8: Die Klasse mit XML-Steuerungsattributen

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

Serialisierung komplexerer Datentypen


Fr die Serialisierung von Datentypen wie Eigenschaften, Arrays, geschachtelten Objekten usw. gilt im Prinzip das bereits weiter oben gesagte. Fr die folgenden Beispiele wird eine etwas erweiterte Klassendefinition benutzt, die ber eine ffentliche Eigenschaft, ein Array und Konstruktoren verfgt. Hier der Teil der Klassendefinition mit den entsprechenden Feldern:
// demo-klasse fr die serialisierung public class DemoClass { // private felder der klasse private int fID; private int fIndentLevel = 0; // ffentliche felder public string StrField = "Nur ein String"; public System.UInt32[] liste = {1,3,5,7,11,13,17,19}; // konstruktoren public DemoClass() { } public DemoClass(int theID) { fID = theID; } // eine ffentliche eigenschaft public int IndentLevel { get { return fIndentLevel; } set { fIndentLevel = value; } } Listing 3.10: Der erste Teil der erweiterten Klassendefinition

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

3 Serialisierung und XML

// 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.

Unbekannten XML-Inhalt behandeln


Sollte in der XML-Datei zustzlicher Inhalt vorhanden sein (in Form von Elementen, Attributen oder z.B. CDATA-Knoten), dann knnen Sie ber Ereignisbehandlungsroutinen das Standardverhalten der Deserialisierung ndern. Sind keine solchen Eventhandler definiert, wird zustzlicher Inhalt in der XML-Datei einfach ignoriert und fr Felder der Klasse, fr die kein Element in der Datei vorhanden ist, wird keine Zuweisung durchgefhrt. Fr die Steuerung dieses Verhaltens definiert die Klasse XmlSerializer drei Ereignisse: UnknownElement, UnknownAttribute und UnknownNode. Erstellen Sie eine Ereignisbehandlungsroutine fr das gewnschte Ereignis, wird diese Methode dann aufgerufen. Fr eine Demonstration erweitern wir die Datei aus Listing 3.3 um zustzliche Elemente.
<?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> <Hersteller>Renault</Hersteller> <KmStand>45800</KmStand> <Verbrauch>7.85</Verbrauch>

Unknown-Ereignisse

35

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

3 Serialisierung und XML

<Klimaanlage /> </SimpleDemo> Listing 3.13: Der neue Inhalt der XML-Datei

Jetzt wird dafr eine Ereignisbehandlungsroutine definiert:


public void XmlElementEventHandler(object sender, XmlElementEventArgs args) { Console.Write("Bei der Deserialisierung von {0} ", args.ObjectBeingDeserialized.ToString()); Console.Write("wurde ein Element <{0}> gefunden.", args.Element.LocalName); Console.WriteLine(); } Listing 3.14: Der EventHandler fr unbekannte Elemente

Diese Methode wird dem XmlSerializer nach der Instantiierung eingetragen.


static void Main(string[] args) { XmlSerializer ser = new XmlSerializer(typeof(SimpleDemo)); XmlTextReader rdr = new XmlTextReader(@"c:\tmp\ser.xml"); ser.UnknownElement += new XmlElementEventHandler(DoUnknownElement); SimpleDemo sd = (SimpleDemo)ser.Deserialize(rdr); rdr.Close(); Console.WriteLine("KmStand: {0}", sd.KmStand); Console.Write("\nPress a key ...."); Console.ReadLine(); } Listing 3.15: Eintragen der Ereignisbehandlung

36

Sandini Bib
Zusammenfassung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

Hier das Ergebnis des Programmablaufs:

Abbildung 3.3: Die unbekannten XML-Elemente werden gemeldet.

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

Document Object Model

4.1 Streaming oder DOM?


Whrend sich der Zugriff auf XML-Dateien per Streaming durch einen geringen Verbrauch an Ressourcen auszeichnet, besitzt diese Methode doch den einen oder anderen Nachteil in bestimmten Situationen. Wie Sie im Kapitel ber XmlReader und XmlWriter (und den davon abgeleiteten Klassen) nachlesen knnen, ist nur ein vorwrtsgerichtetes Arbeiten mglich. Dies bedeutet, dass die Informationen in der XML-Datei in der Reihenfolge gelesen werden mssen, in der diese im Dokument auftauchen, whrend beim Schreiben bereits die endgltige Reihenfolge der Knoten feststehen muss. Besonders schwierig wird der Zugriff bei Zeigern (z.B. IDREF) innerhalb der Datei oder dem nachtrglichen Einfgen von Knoten. Aus diesem Grund ist auch bei .NET die Bearbeitung von XML-Dateien ber das Document Object Model mglich. Hier wird der komplette Dokumentbaum im Speicher aufgebaut, wobei jeder Knoten einer Instanz eines Nachfahren von XmlNode entspricht. Dieses Kapitel befasst sich mit den grundlegenden Mglichkeiten des .NET-Frameworks zur Bearbeitung von DOM-Strukturen. Die Methoden zur Selektion von Untermengen des Dokumentenbaumes mit Hilfe von XPath-Abfragen werden dann im nchsten Kapitel nach einer kurzen Einfhrung in das Thema XPath behandelt. IDREF

4.2 XML-Dokumente laden und lesen


Laden bestehender Dokumente
Das Laden bestehender Dokumente geschieht ber eine Instanz der Klasse XmlDocument und deren Methode Load. Nach der Erzeugung der Instanz wird also nur die Methode Load benutzt, um dem Dokument gleich einen Inhalt zuzuweisen.
// erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden einer bestehenden datei thedoc.Load(@"h:\wetter.xml"); // hier erfolgt die bearbeitung der Datei Listing 4.1: Das Laden von bestehenden XML-Dokumenten

XmlDocument

39

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

4 Document Object Model

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.

Knoten und Elemente


XmlNode Die einzelnen Elemente des Dokumentenbaums bestehen aus Knoten, die hier den einzelnen XML-Elementen entsprechen. ber die Eigenschaft NodeType eines XmlNode lsst sich feststellen, um welchen Knoten es sich handelt (Element, Kommentar, Verarbeitungsanweisung, etc.) und entsprechend kann Ihr Programmcode dann darauf reagieren. Zur Verdeutlichung des nchsten Listings hier nochmals ein Ausschnitt aus der Beispieldatei mit den Wetterdaten:
<?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> Listing 4.3: Ausschnitt aus der Beispieldatei

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

Abbildung 4.1: Die Ausgabe des Beispielprogramms

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

4 Document Object Model

Auswhlen einzelner Elemente


XmlNodelist Die Auswahl einzelner Knoten oder einer Liste von Knoten geschieht ber verschiedene Methoden, die eine Instanz von XmlNode (bzw. einer Ableitung davon) oder eine Auflistung in einer XmlNodeList liefern. Damit lsst sich die Baumstruktur bequem durchsuchen und filtern. Das folgende Beispiel liefert alle location-Elemente der Datei und gibt diese Auflistung in einer Schleife aus, um aufzulisten, fr welche Stationen Wetterdaten vorliegen.
using System; using System.XML; namespace DOMSamples { class ReadXML { static void Main(string[] args) { // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden einer bestehenden Datei thedoc.Load(@"h:\wetter.xml"); // auslesen aller location-tags XmlNodeList nl = thedoc.GetElementsByTagName("location"); // auflistung in schleife ausgeben foreach(XmlNode node in nl) { Console.WriteLine("Station location: {0}", node.InnerText); } Console.WriteLine("Total # of stations: {0}", nl.Count); } } } Listing 4.5: Auslesen aller benannten Tags eines XML-Dokumentes

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.

Zugriff auf Attribute


Fr den Zugriff auf eventuell vorhandene Attribute eines Elementes benutzen Sie zuerst die Eigenschaft Count der Auflistung Attributes des Knotens, um zu testen, ob diese einen Wert grer als 0 enthlt. Ist dies der Fall, liefert die Auflistung Attributes eine XmlAttribute Collection, deren Elemente aus XmlNodes bestehen. Damit lassen sich die einzelnen Unterelemente eines Knotens bequem nach vorhandenen Attributen durchsuchen, wie das nchste Beispiel zeigt. Hier wird fr das erste station-Element in der Beispieldatei jeweils ausgegeben, ob Attribute vorhanden sind, und deren Namen und Wert. Auch hier wird aus Platzgrnden wieder nur der Code fr die Klasse aufgelistet, der Aufruf in einer Testklasse sollte aber kein Problem darstellen.
// ausgabe von attributen aus xml-elementen static void SampleAttributes() { XmlNode node; // erzeugen eines neuen XML-dokumentes XmlDocument thedoc = new XmlDocument(); // laden einer bestehenden datei thedoc.Load(@"h:\wetter.xml"); // das erste element <station> holen node = thedoc.ChildNodes[1].ChildNodes[0]; // durch alle kindknoten des elementes laufen foreach(XmlNode n in node.ChildNodes) { // haben wir attribute? if(n.Attributes.Count > 0) { // dann durch alle attribute laufen foreach(XmlNode a in n.Attributes) { Console.WriteLine("Element <{0}> besitzt" + " Attribute:", n.Name); Console.WriteLine(" {0} = {1}", a.Name, a.Value); } } else // keine attribute, elementname ausgeben Console.WriteLine("Element <{0}> hat keine" +

Attributes und XmlAttribute Collection

43

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

4 Document Object Model

" Attribute.", n.Name); } } Listing 4.6: Ausgabe der Attribute und ihrer Werte

4.3 ndern von XML-Dokumenten per DOM


Hinzufgen von neuen Elementen
Das programmgesteuerte Hinzufgen neuer Elemente (Knoten) in die DOM-Struktur erlaubt den freien Auf- und Umbau eines XML-Dokumentes. Fr jeden mglichen Elementtyp existiert in der XmlDocumentKlasse eine eigene Methode, da die Konstruktoren nicht direkt instantiierbar sind, da Elemente immer zu einem bestimmten Dokument gehren. Das Beispiel unten erzeugt zuerst ein neues XML-Dokument und fllt dies dann durch die entsprechenden Methoden-Aufrufe mit Inhalten. Zuletzt wird durch das Speichern nach Console.Out der Inhalt im Konsolenfenster ausgegeben.
static void SampleNewContent() { XmlNode node1; XmlNode node2; // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // ein kommentarelement erzeugen thedoc.AppendChild(thedoc.CreateComment( "demo fuer .net-essentials")); // ein <weatherdata>-element erzeugen XmlElement elem = thedoc.CreateElement("weatherdata"); thedoc.AppendChild(elem); // ein station-element mit attribut erzeugen node1 = elem.AppendChild(thedoc.CreateElement("station")); (node1 as XmlElement).SetAttribute("id", "Irgendwo"); // einfuegen von text funktioniert // ueber die Methode "CreateTextNode" node2 = node1.AppendChild(thedoc.CreateElement("weather")); node2.AppendChild(thedoc.CreateTextNode("sunny"));

44

Sandini Bib
ndern von XML-Dokumenten per DOM
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

thedoc.Save(Console.Out); } Listing 4.7: Erzeugen von neuen Elementen per DOM

Hier die Ausgabe der Methode:

Abbildung 4.2: Die Ausgabe der neu erzeugten XML-Struktur

Lschen von Elementen


Um ein Element aus der Struktur zu entfernen, existiert die Methode RemoveChild, die als Parameter den zu entfernenden Unterknoten erwartet. Als Erweiterung zum DOM durch Microsoft existiert noch eine Methode RemoveAll, mit der sich in einem Aufruf alle Unterelemente und Attribute eines Knotens entfernen lassen. Der Aufruf der Methode SampleDeleteElements aus dem folgenden Beispiel entfernt aus allen <station>-Elementen den Unterknoten <airtrend>.
static void ProcessElementDelete(XmlNode theNode) { foreach(XmlNode n in theNode.ChildNodes) { if(n.HasChildNodes) ProcessElementDelete(n); } if(theNode.LocalName == "airtrend") { Console.WriteLine("Deleting a node ...."); theNode.ParentNode.RemoveChild(theNode); } } static void SampleDeleteElements() { // erzeugen eines neuen XML-Dokumentes

RemoveChild, RemoveAll

45

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

4 Document Object Model

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

Bearbeiten von Attributen


CreateAttribute Die Behandlung von Attributen erfolgt auf eine etwas abweichende Art und Weise, da die Methode CreateAttribute ein Mitglied der XmlDocument-Klasse ist. Um also ein neues Attribut zu erzeugen, whrend Sie nur auf den aktuellen Knoten Zugriff haben, gehen Sie folgendermaen vor:

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

4 Document Object Model

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)

Tabelle 4.1: Mgliche Ereignisse der XmlDocument-Klasse

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

4 Document Object Model

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

4 Document Object Model

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.1 Warum XPath?


Wie Sie in den vorherigen Kapiteln erfahren haben, bietet das .NETFramework eine ganze Reihe von Mglichkeiten, um XML-Strukturen zu lesen und zu schreiben. Allerdings ist der Weg zu einem bestimmten Knoten bzw. Element mehr oder weniger steinig. Das reine Abzhlen von Unterknoten funktioniert beispielsweise nur dann, wenn Sie sich sicher sind, dass die Reihenfolge der Knoten nicht verndert wurde. Wie Sie dies sicherstellen und auch bestimmte Elemente zwingend erforderlich machen, erfahren Sie im Kapitel ber die Validierung von XML-Dateien. Hier soll es aber zuerst darum gehen, eine sehr mchtige und flexible Mglichkeit zur Suche nach einem oder mehreren Knoten in einer DOMStruktur vorzustellen, nmlich den XPath-Standard. XPath ist eine Entwicklung des World Wide Web Consortiums (W3C) zur Lokalisierung von Knoten in XML-Strukturen, die normalerweise nicht allein genutzt wird, sondern dazu dient, zusammen mit anderen Standards benutzt zu werden. So bestehen zum Beispiel die Suchausdrcke der Schablonen fr die Transformation von XML aus XPath-Ausdrcken. XPath operiert auf der abstrakten, logischen Struktur eines XML-Dokuments, nicht auf seiner uerlichen Syntax. Seinen Namen erhlt XPath durch die Verwendung einer auch in URLs genutzten Pfad-Notation (path), mit der sich durch die hierarchische Struktur eines XML-Dokuments navigieren lsst. Fr eine erfolgreiche Arbeit mit XML ist daher eine eingehende Beschftigung mit XPath unabdingbar. Dieses Kapitel kann aus Platzgrnden nur eine kurze Einfhrung bieten, fr die detailliertere Beschftigung sei auf die Homepage fr XPath unter http://www.w3.org/TR/ xpath.html verwiesen. Das Prinzip von XPath

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.

Abbildung 5.1: Ausgabe aller <temp>-Knoten im XML-Baum

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

Abbildung 5.2: Ausgabe der kombinierten XPath-Abfrage

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 ..)

Tabelle 5.1: Die wichtigsten Achsen fr XPath-Ausdrcke

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 @)

Tabelle 5.1: Die wichtigsten Achsen fr XPath-Ausdrcke (Fortsetzung)

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 "&lt;" und ">" entsprechend durch ein "&gt;" 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() &gt; 10]/../humidity Alle Stationsdaten mit steigendem Luftdruck und mehr als 10: /weatherdata/station[(temp &gt; 10) and (airtrend = "rising")]

58

Sandini Bib
SelectNodes und SelectSingleNode
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

5.3 SelectNodes und SelectSingleNode


Mit der Methode SelectNodes lsst sich eine geladene DOM-Struktur mit Hilfe einer XPath-Abfrage durchsuchen und als XmlNodelist-Auflistung zurckgeben. Das folgende Beispiel liefert alle <temp>-Elemente unterhalb von /weatherdata/station und berechnet anschlieend die Durchschnittstemperatur der Wettermeldungen.
static void SampleSelectNodes() { double sum = 0.0; int count = 0; // erzeugen eines neuen XML-Dokumentes XmlDocument thedoc = new XmlDocument(); // laden der xml-datei thedoc.Load(@"h:\wetter.xml"); // abfragen per XPath XmlNodeList nl = thedoc.SelectNodes(" /weatherdata/station/temp"); // durchlaufen der nodelist foreach(XmlNode n in nl) { sum += double.Parse(n.InnerText); count++; } Console.WriteLine("{0} Werte. Schnitt = {1:F2} Grad", count, sum / count); } Listing 5.4: Auslesen von Knoten mit XPath-Abfragen

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

5.4 Nutzung des XPathNavigators


Anstelle der beiden Methoden der XmlDocument-Klasse kann man fr eine bessere Leistung bei der Verarbeitung von XPath-Abfragen auch eine Klasse nutzen, die eine Implementierung der Schnittstelle IXPathNavigable bereitstellt. Diese Klasse ist fr die Nutzung innerhalb der Transformation mit XSLT optimiert, kann aber auch als schnelle und optimierte Methode zum Suchen mit XPath in normalen Dokumenten verwendet werden. Die Klasse XPathNavigator selbst ist eine abstrakte Klasse, fr eigene Zwecke (z.B. das Bereitstellen von XPath-Abfragen fr ein hierarchisches Dateisystem) lsst sich eine entsprechende Ableitung von XPathNavigator implementieren. In der derzeitigen Version des .NET-Frameworks sind das die beiden Klassen XPathDocument und XmlNode. Hier wird der Navigator ber einen Aufruf der Methode Create Navigator erzeugt, wie die nachfolgenden Beispiele noch im Detail zeigen werden. Hier der Code zur Erzeugung einer XPathNavigator-Instanz, in dem in ein XPathDocument eine bestehende XML-Datei geladen wird.
// erzeugen des XML-Dokumentes XPathDocument thedoc = new XPathDocument(@"h:\wetter.xml"); // erstellen der XPathNavigator-Instanz XPathNavigator xnav = thedoc.CreateNavigator();

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.

Navigation mit dem XPathNavigator


Fr die Navigation mit dem XPathNavigator lassen sich die folgenden Methoden einsetzen, die eine direkte Navigation im Vergleich zu den nachfolgend beschriebenen Auswahlmethoden vornehmen. Methode
Matches

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

Tabelle 5.2: Die Navigationsmethoden fr den XPathNavigator

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.

Tabelle 5.2: Die Navigationsmethoden fr den XPathNavigator (Fortsetzung)

Auswhlen von Knotenmengen mit Select


XPathNodeIterator Mit Hilfe der Methode Select lassen sich XPath-Ausdrcke zur Filterung einer XML-Struktur benutzen, fr deren Treffer die Methode dann einen XPathNodeIterator zurckliefert. Die Methode Select liefert eine Iterator-Instanz, die zuerst auf dem Knoten positioniert ist, der als Kontext (und damit Startknoten) fr die XPath-Abfrage dient. Daher muss zuerst einmal MoveNext aufgerufen werden, um auf den ersten Knoten des ResultSets zu treffen. Das folgende Listing liefert einen kurzen Wetterbericht, in dem ber einen XPath-Ausdruck jeweils das <location>- und das <weather>Element gesucht und dann mit Hilfe des Iterators in einer Schleife ausgegeben werden.
// nutzung von XPathNodeIterator static void SampleXPathNodeIterator() { // erzeugen des XML-Dokumentes XPathDocument thedoc = new XPathDocument(@"h:\wetter.xml");

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.

Die Eigenschaft Current

Auswerten von Ausdrcken


Die Methode Evaluate des XPathNavigators bietet eine sehr flexible Mglichkeit, auch XPath-Ausdrcke auszuwerten, die einen anderen Datentyp als ein Knotenset liefern. In Kombination mit XPath-Funktionen und den Operatoren fr XPath-Ausdrcke lassen sich manche Aufgaben fast ohne Code erledigen, indem der XPath-Engine die Arbeit zugeschoben wird. Als Beispiel soll hier die Berechnung der Durchschnittstemperatur aller Wettermeldungen dienen. Im Kapitel ber die Nutzung der Streamingklassen XmlReader und XmlWriter finden Sie ein Listing, das die gleiche Aufgabe lst. Hier war

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.

Optimieren durch Kompilieren von Ausdrcken


Bei jeder Auswahl von Knoten mit Hilfe eines XPath-Ausdrucks muss der Parser jedesmal wieder die Analyse und Optimierung der Abfrage durchfhren, was bei wiederverwendeten Abfragen zu einer Leistungseinbue fhrt. Daher besitzen alle entsprechenden Methoden, die einen XPath-Ausdruck akzeptieren, auch eine berladung fr einen kompilierten Ausdruck. Dieser wird durch eine Instsanz der Klasse XPathExpression gebildet. Die Nutzung dieser Funktionalitt erfordert nur minimal mehr Code, bietet aber gerade bei komplexeren Ausdrcken eine deutliche Steigerung der Abfrageleistung. XPathExpressions bringen Performance Hier das Listing aus dem letzten Abschnitt, nur umgewandelt in eine Form, bei der der XPath-Ausdruck zuerst kompiliert und dann verwendet wird. Wie Sie sehen, kein Mehraufwand, aber eine gesteigerte Performance bei komplexen Abfragen (das Konzept ist hnlich SQL mit ad-hoc queries und stored procedures).
// berechnungen als xpath-ausdruck static void SampleXPathDocument() { // erzeugen des XML-Dokumentes XPathDocument thedoc = new XPathDocument(@"h:\wetter.xml"); // erstellen der XPathNavigator-Instanz XPathNavigator xnav = thedoc.CreateNavigator(); // jetzt zuerst kompilieren des ausdrucks

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

URI und URL

Prfixe und Namensraum-URIs

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

Namespaces bei XmlReader und XmlWriter


Beim Lesen von XML mit Hilfe des XmlReaders oder einer abgeleiteten Klassen knnen Sie auf verschiedene Eigenschaften zurckgreifen, um Informationen ber die Namensrume der einzelnen Elemente zu erhalten. Das folgende Beispiel zeigt eine Methodendefinition, mit der die Datei nsdemo.xml gelesen wird. Der Code listet die Informationen zur Schachtelungstiefe, dem Elementnamen, einem evtl. vorhandenen Prfix und dem dazugehrigen Namensraum-URI auf.
public static void DemoElementList() { XmlTextReader rdr = new XmlTextReader(@"c:\tmp\nsdemo.xml"); Console.WriteLine("{0}\t{1,-16}\t{2}\t{3}",

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

Hier die Ausgabe des Programms:

Abbildung 6.1: Die Ausgabe von Listing 6.4

XmlWriter und Namespaces

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

Hier das Ergebnis des Methodenaufrufs:


<?xml version="1.0"?> <root> <aw:book aw:isbn="0-0000-00000-0" xmlns:aw="urn:bookdemo-uri"> <aw:titel>Demo-Titel</aw:titel> <autor xmlns="urn:book-authors-uri">

71

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

6 XML-Namensrume

An O. Nymous</autor> </aw:book> </root> Listing 6.6: Die Ausgabedatei mit Namensraumdeklarationen

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.

Methode oder Eigenschaft


DefaultNamespace-Eigenschaft LookupNamespace-Methode

LookupPrefix-Methode

AddNamespace-Methode RemoveNamespace-Methode PushScope-Methode, PopScope-Methode HasNamespace-Methode NameTable-Eigenschaft

Tabelle 6.1: Aufgaben im Bereich Namensrume und die passenden Methoden dazu

73

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

6 XML-Namensrume

XPath und Namensrume


Fr die Selektierung von Elementen mit Hilfe einer XPath-Abfrage muss bei Namensrumen ebenfalls ein Namespace-Manager angegeben werden, der mit den entsprechenden Namensraumdeklarationen versorgt wurde. Anschlieend erfolgt die Abfrage wie bereits bekannt per XPath-Ausdruck. SetContext Es besteht allerdings ein Unterschied: es kann kein String als XPathAusdruck verwendet werden, sondern der Ausdruck muss vorher in eine Instanz einer XPathExpression kompiliert werden, da diese Klasse ber eine Methode SetContext verfgt, mit der XPath-Ausdruck und Namespace-Manager verbunden werden. Beim XPath-Ausdruck selbst, der der Methode XPathNavigator.Compile bergeben wird, mssen die entsprechenden Prfixe fr den Namensraum angegeben werden. Das Beispiel zeigt eine Methode mit diesen nderungen im Code, um auch bei XPath-Abfragen auf Namensrume zugreifen zu knnen.
public static void DemoNamespaceXPath() { XPathDocument thedoc = new XPathDocument(@"c:\tmp\nsdemo.xml"); XPathNavigator xnav = thedoc.CreateNavigator(); try { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); nsmgr.AddNamespace("radio", "urn:radio-uri"); nsmgr.AddNamespace("leute", "urn:leute-uri"); XPathExpression xpr = xnav.Compile("//leute:moderator/@email"); xpr.SetContext(nsmgr); XPathNodeIterator iter = xnav.Select(xpr); while(iter.MoveNext()) { Console.WriteLine(iter.Current.Value); } } catch(Exception e) { Console.WriteLine("Error: ", e.Message); } } Listing 6.9: XPath-Auswahl von Knoten mit Namensrumen

74

Sandini Bib
Einfhrung
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

Validierung und Namensrume


Bei der Validierung von XML-Daten, die Deklarationen fr einen Namensraum enthalten, ndert sich kaum etwas, nur dass die Elemente entsprechend qualifiziert angegeben weren. Ein Sonderfall ist eine XML-Datei mit Elementen ohne Prfix (unqualifiziert), die ber einen Standardnamensraum verfgen. Die Definition des Namensraums ist hier nochmals fr die Beispieldatei meteo.xml aufgefhrt:
<?xml version="1.0"?> <weatherdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:meteo-demo" xsi:schemaLocation="urn:meteo-demo c:\tmp\meteo.xsd"> Listing 6.10: Definition des Default-Namensraums (ohne Prfix)

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

elementForm Default und attributeForm Default

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

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 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

Abbildung 7.1: Ablauf einer XSL-Transformation

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

Aufbau eines Stylesheets


Ein XSL-Stylesheet (oder XSLT-Transformationsdatei, wie die deutsche Version des .NET-Frameworks diese Dateien nennt) ist selbst ebenfalls eine XML-Datei. Die fr XSLT ntigen Elemente werden im XSLNamensraum definiert, der durch den URI http://www.w3.org/1999/XSL/ Transform identifiziert wird und (per Konvention) das Prfix xsl trgt. Auch wenn theoretisch ein anderes Prfix ebenso gut mglich wre, sollten Sie sich doch an xsl halten. Wer wei schon, in wie vielen Anwendungen dieses Prfix fest eincodiert wurde XSL-Templates Innerhalb des Stylesheet-Rumpfes werden so genannte Schablonen (templates) definiert, die als Wert fr das Attribut match jeweils einen XPath-Ausdruck enthalten. Matcht dieser (wird ein bereinstimmendes Element gefunden), so wird dieses Template abgearbeitet und die darin enthaltenen Elemente in den Ausgabestrom geschrieben.
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <p> <xsl:apply-templates /> </p> </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.1: Eine sehr einfache XSLT-Datei

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.

7.2 Stylesheets laden


Zum Laden von Tranformations-Stylesheets benutzen Sie die Methode Load der Klasse XslTranform, die mehrfach berladen ist. So kann das Stylesheet nicht nur aus einer Datei, sondern auch von einem bereits geparsten XPathDocument oder einem XmlDocument oder einem XmlReader stammen. Damit knnen auch programmatisch erzeugte Stylesheets leicht geladen und fr die Transformation verwendet werden. Das folgende Beispiel ldt ein Stylesheet von einem URL:
XslTransform xslt = new XslTransform(); //Load the stylesheet. xslt.Load("http://localhost/demo/xsl/wetter1.xsl"); Listing 7.2: Laden eines bestehenden Stylesheets

XslTransform, Methode Load

Laden ber einen XmlUrlResolver


Wird ein Stylesheet (oder eine andere externe Ressource fr XML wie z.B. eine DTD, ein Schema u.a.) ber einen URL geladen, spielt die Berechtigung fr diesen Zugriff eine Rolle. Besteht fr das angegebene Vezeichnis auf dem IIS ein anonymer Zugriff, reicht die Angabe des URL aus. Fr alle anderen Flle muss ein sogenannter Resolver angegeben werden, der sich dann um die Weiterreichung der Benutzerinformationen kmmert. Die Klasse NetworkCredentials findet sich brigens im Namensraum System.Net, den Sie importieren mssen. Das Listing zeigt das Laden eines Stylesheets mit Hilfe eines Resolvers und der Angabe von Benutzername und Kennwort.
static void SampleResolverTransform() { XslTransform xslt = new XslTransform(); // neue resolver-instanz erzeugen XmlUrlResolver resolver = new XmlUrlResolver(); // benutzderdaten festlegen NetworkCredential nc =

Authentifizierung ber Network Credentials aus System.Net

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.

7.3 Transformation durchfhren


Methode Transform Die eigentliche Hauptarbeit fhrt die Methode Transform der Klasse XslTransform durch, durch deren Aufruf das Stylesheet und die XML-Ein-

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

Hier das verwendete Stylesheet:


<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/ Transform"> <xsl:template match="/"> <html> <p> <xsl:apply-templates />

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

Im Konsolenfenster wird die folgende Ausgabe erzeugt:

Abbildung 7.2: Die Ausgabe im Konsolenfenster

XML-Strukturen mit XSLT umformen


Xml-Editoren als sinnvolles Werkzeug Mit Hilfe von XSL-Stylesheet und der Klasse XslTransform lassen sich nicht nur XML-Daten in ein anderes Format berfhren. Eines der Haupteinsatzgebiete ist die Umformung einer XML-Struktur in eine andere Struktur, um Daten fr verschiedenene Anwendungen anzupassen. So ist die Beispieldatei meteo.xml mit Hilfe einer XSL-Transformation aus der Datei wetter.xml entstanden. Produkte wie z.B. der BiztalkServer haben diese Funktionalit als Grundlage. Visual Studio .NET bietet zwar eine Mglichkeit zur Erstellung von XSLT-Dateien, aber fr diese Stylesheets existiert in der aktuellen Version keine Untersttzung durch Autovervollstndigung, IntelliSense und all die anderen guten Dinge aus dem Code-Editor. Fr die Erstellung von komplexeren Stylesheets sollten Sie sich daher eine XML-Entwicklungsumgebung wie XMLSpy oder Stylus Studio ansehen. Das nachfolgende Stylesheet erzeugte aus der Datei wetter.xml die Dateo meteo.xml fr die weiteren Beispiele. Mit Hilfe der XSL-Funktionen lassen sich dabei auch Teile eines Elementinhaltes verwenden, wie die Funktion substring-before fr das Abschneiden des Prozentzeichens bei der Luftfeuchtigkeit zeigt.

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

</xsl:element> </xsl:template> </xsl:stylesheet> Listing 7.6: Komplexeres Beispiel fr eine XSL-Transformation

7.4 Transformationen verketten und optimieren


Transformationen verketten
Vermeiden Sie unntiges Parsing Nicht immer reicht eine einzelne Transformation aus. So sind durchaus Szenarien denkbar, bei denen zuerst eine XML-Datei mit Hilfe eines Stylesheets in ein Stylesheet transformiert wird und dann dieses Stylesheet benutzt wird, um eine XML-Datendatei zu transformieren. Oder eine Datei wird nacheinander von drei verschiedenen Stylesheets umgeformt. Dazu sollte nach Mglichkeit vermieden werden, einen neuen Parse-Vorgang zu starten. Dies ist beispielsweise dann der Fall, wenn das Ergebnis der ersten Transformation (das Zwischenergebnis) in einen Stream (z.B. eine Instanz von MemoryStream) geschrieben wird. Sinnvoller ist die Nutzung eines XmlReader, aus dem sich dann eine neue Instanz eines XPathDocument erzeugen lsst, die gleich die durch den Reader geparsen Inhalt bernimmt. Je nach Szenario und Dateistruktur lassen sich dadurch deutliche Performancesteigerungen erzielen. Hier ein Beispiel fr eine zweifache Transformation. Einsatzmglichkeiten in der Praxis bieten sich beispielsweise fr Redaktionssysteme, die XML-Content von XML nach XHTML rendern und danach in einem zweiten Durchlauf das nackte XHTML durch Formatierungen wie Inline-Styles oder andere Markup-Attribute ergnzen.
// mehrfache transformationen mit // koppelung ber einen XmlReader static void SampleChainedTranform() { XslTransform xslt1 = new XslTransform(); XslTransform xslt2 = new XslTransform(); // stylesheets laden xslt1.Load(@"h:\wetter1.xsl"); xslt2.Load(@"h:\wetter2.xsl"); // XPathDocument erzeugen und datei laden XPathDocument thedoc = new XPathDocument(@"h:\miniwetter.xml"); // XmlTextWriter fr den output erzeugen

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.

Mehrfaches Laden von Stylesheets vermeiden


Vermeiden Sie nach Mglichkeit das unntige Laden von Stylesheets, da hierbei jedesmal von neuem das Dokument geparst und eventuelle externe Referenzen aufgelst werden mssen. Werden mehrere Dokumente mit dem gleichen Stylesheet behandelt, sollte das Laden per Load auerhalb der Schleife erfolgen und nicht jedesmal neu in der Schleife.

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

Validieren von XML

8.1 Warum ein Schema?


In der Regel werden XML-Strukturen von Anwendungen weiterverarbeitet. Daher besteht ein Interesse daran, dass eine zur Bearbeitung vorliegende Datei in ihrem Aufbau vorhersagbar ist bzw. sich an einen vereinbarten Standard hlt. Ist dies nicht der Falls, kann die Datei unter Umstnden nicht verarbeitet werden (wenn z.B. bei einer Bestelldatei in XML die Angabe der Teilenummer fehlt). Daher wurden bereits zu Beginn der XML-Entwicklung Mglichkeiten von SGML bernommen, die Struktur der Datei zu beschreiben und so einen Test auf Einhaltung dieser Struktur zu ermglichen. Diese erste Variante eines Schemas war die Document Type Definition (DTD). Aus verschiedenen Grnden (die in den folgenden Abschnitten noch erlutert werden) ist eine DTD aber nicht das ideale Mittel zur Beschreibung der Grammatik einer XML-Datei. Standard ist derzeit die vom World Wide Web Consortium (W3C) als Empfehlung verabschiedete XMLSchema Definition (XSD), die das zweite hier erluterte Mittel zur Defintion einer XML-Grammatik darstellt. DTDs sind noch relativ hufig

Aufbau einer DTD


Aus Grnden des zur Verfgung stehenden Platzes und da DTD meist nur noch in Form von Portierungsquellen fr XSD-Schemata auftauchen, sind die nchsten Abschnitte nur eine kurze Einfhrung. Weitere Details zum Erstellen von DTD-Schemata finden Sie in den allgemeinen XML-Bchern zum Thema bzw. dem Internet. Anhand einer Document Type Definition lassen sich aber schn der Weg von der Struktur zum Dokument und auch die Nachteile eines Textansatzes zeigen, der schlielich zu den XSD-Schemata fhrte. Eine DTD beschreibt, welche Elemente und Attribute in welcher Reihenfolge auftreten, ob ein Attribut erforderlich ist und diverse weitere Details der XML-Struktur. Diese Beschreibung ist eine Textdatei (kein XML, was einen der Hauptnachteile der DTDs darstellt) und besitzt fr die Beispieldatei Meteo.xml folgenden Aufbau:
<!ELEMENT <!ELEMENT <!ELEMENT <!ATTLIST <!ELEMENT <!ATTLIST <!ELEMENT clouds (#PCDATA)*> sky (#PCDATA)*> temp (#PCDATA)*> temp units (Celsius|Fahrenheit|Kelvin) #REQUIRED> humidity (#PCDATA)*> humidity units CDATA #REQUIRED> wind (#PCDATA)*>

DTD: eine Grammatik fr eine XML-Struktur

89

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

8 Validieren von XML

<!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)+>

Listing 8.1: Eine Document Type Definition

Definition von Elementen


Wie sich relativ leicht erkennen lsst, werden mgliche Elemente mit dem Ausruck <!ELEMENT> definiert, der als Parameter den Namen des Elements und in runden Klammern die Liste der Unterelemente erhlt. Werden als Elementinhalt beliebige Zeichenketten an Stelle von weiteren Unterelementen akzeptiert, wird dies durch #PCDATA angegeben. Diese Abkrzung steht fr parsed character data und erlaubt beliebige Zeichenketten. Ein Beispiel fr Unterlemente finden Sie bei der Definition
<!ELEMENT station>, hier werden die notwendigen Unterlemente aufge-

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

Tabelle 8.1: Die mglichen Modifikatoren fr Elemente und Attribute

90

Sandini Bib
Warum ein Schema?
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

Definition von Attributen


Fr die Definition von Attributen dient das <!ATTLIST>-Statement, mit dem fr ein als Parameter angegebenes Element die Liste der mglichen Attribute definiert wird. Nach dem Namen des Elements folgt der Attributname und anschlieend der mgliche Inhalt, entweder CDATA fr Zeichenfolgendaten oder die direkte Angabe eines oder einer Reihe mglicher Werte mit dem choice-Modifikator. Fr Attribute existieren vier mgliche Instanztypen:
Fixed Implied Optional Required Das Attribut muss dem angegebenen Wert entsprechen und muss immer explizit angegeben werden Das Attribut ist optional, es existiert kein Defaultwert Das Attribut ist optional, wird kein Attribut angegeben, setzt der Parser den Default-Wert ein Es muss immer explizit ein Attributwert angegeben werden

Tabelle 8.2: Die mglichen Belegungstypen fr Attributinhalte

Interne und externe DTDs


Die obige DTD ist eine interne DTD, da dieser Text in der XML-Datei selbst enthalten ist:
<?xml version="1.0"?> <!DOCTYPE weatherdata [ (hier der Inhalt der DTD) ]> <weatherdata> <station id="Algeirs"> <!-- unterknoten --> </station> </weatherdata> Listing 8.2: Einbetten einer DTD in das XML-Dokument

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

8 Validieren von XML

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">

Eventuell bentigen Sie einen UrlResolver

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.

Validierung mit Hilfe einer DTD


Der grundlegende Ablauf ist fr eine DTD, ein XDR-Schema oder ein XSD-Schema der gleiche, da der zu verwendende Schematyp fr einen XmlValidatingReader einfach ber eine Eigenschaft eingestellt wird. XmlValidating Reader Fr die Prfung eines XML-Dokumentes auf Gltigkeit wird eine Instanz der Klasse XmlValidatingReader verwendet. Deren Konstruktor verfgt ber eine berladung, die entweder ein XML-Fragment als String oder Stream akzeptiert oder aber eine XmlReader-Instanz, was in den meisten Fllen sinnvoller sein drfte. Der XmlReader (genauer, eine Nachfolgeklasse wie XmlTextReader, da es sich bei XmlReader um eine abstrakte Klasse handelt) wird dem ValidatingReader-Konstruktor bergeben und in einer Schleife wird per Read solange gelesen, bis die gesamte XML-Struktur berprft wurde. Im einfachsten Fall mssen Sie wirklich nicht mehr tun, da ohne eine definierte Ereignisbehandlung der XmlValidatingReader eine Exception auslst, die Sie nur abzufangen brauchen, um festzustellen, ob in der XML-Struktur ein Fehler enthalten ist oder nicht. Das nachfolgende Listing zeigt diesen Ansatz, bei dem die Beispieldatei meteo.xml mit Hilfe einer internen DTD validiert wird.
// validierung mit hilfe einer internen dtd // die namensrume using System; using System.XML; using System.XML.XPath; using System.XML.Schema; namespace SchemaSamples { // die validierungsklasse class DTDSchemaDemo {

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

8 Validieren von XML

Console.WriteLine(); Console.Write("Press a key ...."); Console.ReadLine(); } } } Listing 8.3: Prfen eines Dokumentes mit Hilfe einer DTD

Validierung mit EventSink


Alternativ kann fr den ValidatingReader auch eine Ereignisbehandlungsroutine angegeben werden, die dann aufgerufen wird, wenn bei der Validierung ein Warnungs- oder Fehlerereignis auftritt. Dazu muss der obige Code nur um die entsprechende Routine ergnzt und dieser Delegate beim Handler eingetragen werden. Das folgende Listing zeigt die Unterschiede zur Version ohne Ereignisbehandlung:
// validierung mit hilfe einer internen dtd // die namensrume using System; using System.XML; using System.XML.XPath; using System.XML.Schema; namespace SchemaSamples { // die validierungsklasse class DTDSchemaDemo { private string fFilename; private XmlTextReader txtrdr = null; private bool bValidated = true; // annahme // der konstruktor public DTDSchemaDemo(string filename) { fFilename = filename; txtrdr = new XmlTextReader(fFilename); } // die ereignisbehandlungsroutine public void ValidationSink(object sender, ValidationEventArgs args) { // nur fehler ausgeben, warnungen ignorieren if(args.Severity == XmlSeverityType.Error) {

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

8 Validieren von XML

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.

DTDs und die Alternativen (XDR und andere)


Einer der Hauptnachteile einer DTD ist die Tatsache, dass es sich hierbei nicht selbst um eine XML-Datei handelt, so dass all die vorhandenen Werkzeuge und Mglichkeiten nicht auf eine DTD angewendet werden knnen. Darber hinaus existieren aber noch andere Nachteile, die Hersteller und Entwickler von XML-Lsungen bereits frhzeitig nach Alternativen suchen lieen. Hier eine (nicht vollstndige) Liste der Grnde, warum eine DTD nicht optimal fr die Erstellung eines Schemas geeignet ist:

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.

8.2 XSD der Standard


Einfhrung
Die Wnsche und Anforderungen an das W3C fr einen DTD-Nachfolger waren umfangreich und nicht leicht zu erfllen:

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

8 Validieren von XML

Erstellen eines XSD-Schemas


Angenommen, fr eine Datei mit Wettermeldungen wird ein Schema bentigt, um das Dokument validieren zu knnen. Aus Grnden der bersichtlichkeit beschrnken wir uns hier auf ein einzelnes, etwas vereinfachtes <station>-Element (die spteren Beispiele verwenden dann wieder die vollstndige Datei meteo.xml) Dieses Element besitzt folgenden Aufbau:
<station> <location>Athens</location> <weather>mostly cloudy</weather> <temp>16 Celsius</temp> <humidity>77%</humidity> <wind>SW, 2 knoten</wind> <airpressure>1024</airpressure> </station> Listing 8.5: Ein vereinfachtes XML-Fragment

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.

Schema-Erstellung mit xsd.exe


xsd.exe ist ein wichtiges Tool Wenden wir und also zuerst der Verwendung eines KommandozeilenTools aus dem .NET-Framework zu. Das Programm xsd.exe ist ein Werkzeug zum Erzeuen von Schemata, Datenbeschreibungen und Datendefinitionen per XML-Schema. Die mglichen Parameter entnehmen Sie bitte dem folgenden Kasten, der den Hilfetext wiedergibt, den xsd.exe bei einem Aufruf ohne Parameter ausgibt.

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

8 Validieren von XML

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?

Der Schemadesigner von Visual Studio


Laden wir dieses Schema nun in den Schema-Editor von Visual Studio .NET. Dazu ffnen Sie die entsprechende XSD-Datei oder fgen Sie diese einem Projekt hinzu. Sollten Sie nicht mit Visual Studio .NET arbeiten, dann ist die Beschaffung eines XML-Editors mit einem Schemadesigner eine sinnvolle Investition. Andernfalls stehen Sie vor der doch etwas mhsamen Aufgabe, eine Schemadatei von Hand zu pflegen. Hier knnen Sie nun nderungen anbringen oder die Eigenschaften des Schemas betrachten. ber die Reiter am unteren Rand des Fensters knnen Sie zwischen dieser Designeransicht und der Darstellung des XML-Codes fr das Schema umschalten.

101

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

8 Validieren von XML

Abbildung 8.1: Der XML-Schemadesigner von Visual Studio .NET

Schemas mit Referenzen oder im BabuschkaDesign

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.

Definition des WurzelElements

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

Abbildung 8.2: XSD-Schema im Babuschka-Design

Abbildung 8.3: Die Toolbox fr XSD-Schemata

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

8 Validieren von XML

Der Designerbildschirm sollte (nach dem Speichern, sicherheitshalber) so aussehen:

Abbildung 8.4: Der erste Teil des Schemas ist angelegt.

Erstellen einer choice-Gruppe

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

Abbildung 8.5: Einfgen der choice-Gruppe fr sky und clouds

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.

Schema-Generierung aus Datentabellen


ber den Serverexplorer lsst sich z.B. fr ADO.NET-Validierungen ein Schema fr eine Datentabelle erzeugen. Whlen Sie dazu aus dem Serverexplorer von Visual Studio .NET eine Tabelle aus und ziehen Sie diese auf ein neues XML-Schema (siehe Abbildung 8.6). Nach dem Ablegen auf der leeren Schemadesigner-Seite wird automatisch ein Schema fr die XML-Darstellung der Tabelle erzeugt (siehe Abbildung 8.7).

105

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

8 Validieren von XML

Abbildung 8.6: Der Serverexplorer in Aktion

Abbildung 8.7: Das automatisch erzeugte Schema

106

Sandini Bib
XSD der Standard
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

Essentials

.NET

Hier der Inhalt der erzeugten Schema-Datei:


<?xml version="1.0" encoding="utf-8" ?> <xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/ XMLSchema.xsd" xmlns:mstns="http://tempuri.org/XMLSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemasmicrosoft-com:xml-msdata"> <xs:element name="Document" msdata:Locale="de-DE"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="weatherdata"> <xs:complexType> <xs:sequence> <xs:element name="Station" type="xs:string" /> <xs:element name="Clouds" type="xs:string" /> <xs:element name="Temp" type="xs:decimal" /> <xs:element name="temp_units" type="xs:string" /> <xs:element name="humidity" type="xs:int" /> <xs:element name="hum_units" type="xs:string" /> <xs:element name="wind" type="xs:string" /> <xs:element name="windspeed" type="xs:decimal" /> <xs:element name="wind_units" type="xs:string" /> <xs:element name="airpressure" type="xs:decimal" /> <xs:element name="airtrend" type="xs:string" /> <xs:element name="air_units" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> <xs:unique name="DocumentKey1" msdata:PrimaryKey="true"> <xs:selector xpath=".//mstns:weatherdata" /> <xs:field xpath="mstns:Station" /> </xs:unique> </xs:element> </xs:schema> Listing 8.7: Das automatisch erzeugte Tabellenschema

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

8 Validieren von XML

Schema aus Klassen erstellen


Fr die Deserialisierung von Instanzen aus XML-Daten ist es wnschenswert, sicherzustellen, dass der Aufbau der Datei auch alle ntigen Informationen enthlt. Dazu wird mit Hilfe des xsd-Tools aus der Klasse ein Schema erstellt, mit dem dann eine Datei validiert werden kann. Dazu verwenden wir die einfache Beispielklasse aus dem Kapitel ber die XML-Serialisierung, SimpleDemo. Als Parameter fr xsd.exe wird dabei der Name des Assemblies angegeben, in dem der bersetzte Klassentyp enthalten ist, zusammen mit der Option /type: (oder /t:) und dem Namen des Typs, fr den das Schema erstellt werden soll. Wird kein Typ angegeben, werden Schemas fr alle Typen im Assembly erstellt.
xsd assemblyname.exe /T:SimpleDemo

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

Verweisen auf ein Schema


Im Dokument wird in der Regel noch der Verweis auf dieses Schema eingetragen werden:
<station xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="eingabe.xsd"> Listing 8.9: Verweis auf das Schema in der Datendatei

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

8 Validieren von XML

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 Validieren von XML

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

XML und Daten

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

9.2 DataSet und Co.


Das Programmiermodell von ADO.NET bietet zwei grundlegende Mglichkeiten zum Zugriff auf Daten. Einmal die Klasse DataSet als relationale Darstellung der Daten, frei navigierbar, ohne die Notwendigkeit einer Verbindung zur Datenbank und mit allen Mglichkeiten der Datenmanipulation. Diese Mchtigkeit kann allerdings auch zum Problem werden. Bei ADO war der relativ groe Overhead des RecordSet-Objektes immer ein Problem, wenn es nur darum ging, einfach eine Abfrage an den Server zu schicken und dann das Resultset ber eine ASP-Seite an den Client zurckzupumpen. Nur lesen, nichts ndern, immer vorwrts und wieder raus aus der Datenbank mit ADO.NET ist das ressourcenschonend mglich. Dazu dient der DataReader, der hnlich einem so genannten firehose cursor die schnellste Mglichkeit fr den Datenzugriff bietet. Nachdem Microsoft selbst eine der derzeit leistungsfhigsten Datenbanken anbietet, existiert dafr auch eine eigene Untersttzung ber die im Namensraum System.Data.OleDb vorhandene OLE DB-Anbindung hinaus. Der Namensraum System.Data.SqlClient bietet eigene Objekte, die direkt die TDS-Schnittstelle des SQL-Servers nutzen und so den geringstmglichen Overhead besitzen. Der Nachteil des DataReaders (und damit der Grund, warum er hier nicht weiter besprochen wird) ist die Tatsache, dass der Abruf der Daten nicht in XML erfolgt. DataSet

Schwergewicht RecordSet in ADO

Besonderheit SQLServer

113

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

9 XML und Daten

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

DataSet aus XSD-Schema


Natrlich muss dieses manuelle Aufbauen des DataSets nicht sein, wenn Sie Zugriff auf ein XML-Schema haben, das diese Daten bereits enthlt. Dies kann entweder mit Hilfe der Methode WriteXmlSchema durch ein anderes DataSet erstellt, von Hand gebaut oder durch eine XSLT-Transformation entstanden sein. Das passende XSD-Schema fr die beiden Tabellen aus dem letzten Beispiel hat den folgenden Inhalt:
<?xml version="1.0" standalone="yes"?> <xs:schema id="DemoData" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="DemoData" msdata:IsDataSet="true" msdata:Locale="de-DE"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="Distillery"> <xs:complexType> <xs:sequence> <xs:element name="DistilleryID" type="xs:int" minOccurs="0" />

WriteXmlSchema

115

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

9 XML und Daten

<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; }

DataSet ganz einfach

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

9 XML und Daten

Die Ausgabe der Methode sollte dann wie folgt aussehen:

Abbildung 9.1: Die Ausgabe der Tabllen mit der Zeilenzahl

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

Tabelle 9.1: Die mglichen Werte fr den XmlReadMode

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

Tabelle 9.1: Die mglichen Werte fr den XmlReadMode (Fortsetzung)

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);

WriteXml und WriteXmlSchema

119

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

9 XML und Daten

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

9 XML und Daten

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

XML speichern mit XmlDataDocument


Auch mit einer XmlDataDocument-Instanz knnen Sie die Daten wieder in eine XML-Datei schreiben. Hierbei existieren aber zwischen der Methode Save des XmlDataDocuments und der Methode WriteXml des DataSets einige Unterschiede in der Behandlung des XML-Stroms. Dazu eine kleine Methode, mit der zuerst eine XML-Datei geladen und dann mit den beiden Methoden jeweils in eine eigene Datei gespeichert wird.

123

Sandini Bib
Essentials

.NET

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

9 XML und Daten

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>

(Syntax wird vom Compiler berprft) Beispiel zu include weiter unten


<include>

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>

Dient der Erstellung von Listen oder Definitionslisten im Kommentar.


<para>

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>

Beschreibt den Rckgabewert einer Methode.


<see>

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.

Einbinden von externen Dateien


Mit Hilfe des Elements <include> ist es mglich, den XML-Kommentar von der Codedatei zu trennen und in der Klasse nur einen Verweis auf die Datei mit den Kommentaren anzugeben. Das Element <include> besitzt zwei Attribute, deren Werte in einfachen Anfhrungszeichen eingeschlossen werden mssen. Das erste Attribut file enthlt den Pfadnamen der XML-Datei mit den Kommentaren. Das Attribut path enthlt einen XPath-Ausdruck, mit dem innerhalb der Datei die Elemente selektiert werden, die an dieser Stelle eingefgt werden sollen. Der Kommentar in der Klasse DemoClass.cs lautet beispielsweise wie folgt:
class Test { /// <include file='DemoClass.inc' path='DemoClass/members[@name="test"]/*' /> public static void Main() { } /// <include file='DemoClass.inc' path='DemoClass/members[@name="DoIt"]/*' /> public void DoIt() { } } Listing 10.3: Verweis auf Includedateien in XML-Kommentaren

Hier die dazugehrige Datei Democlass.inc mit den Kommentaren


<DemoClass> <members name="test"> <summary> The summary for this type. </summary> </members>

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.

Externe Dateien besitzen Vor- und Nachteile

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.

Tabelle 10.1: Typkennzeichner fr ID-Zeichenfolgen in Kommentaren

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

Ohne Visual Studio mssen Sie die XSL-Stylesheets selbst entwerfen.

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

WriteStartDocument 22 WriteStartElement 22 WriteStartelement, Namensrume 70 WriteXml 119, 123 WriteXmlSchema 115

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.

wenn Sie mehr wissen wollen ...

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

You might also like