Verwendung von XML-Schemas (XSD)
Geschrieben von: Frederic Ganner Dieser Artikel wird sich anhand eines praktischen Beispiels mit der Verwendung von XML-Schemas beschäftigen. Sowohl Datentypen als auch die Validation mit Schemas werden hier näher betrachtet. Eine Einleitung zu XML Schemas können Sie im Artikel Was sind XML Schemas? nachlesen. Um XML-Schemas mit ASP am Server verarbeiten zu können, wird die neueste Version des Microsoft XML Parsers benötigt. Zum Zeitpunkt des Erscheinens des Artikels war dies der Tech Preview des MSXML 4.0 Parsers. Diesen kann man bei msdn.microsoft.com/xml downloaden. Der Datenaustausch zwischen Anwendungen oder Systemen verlangt nach einem festen Muster wie die Daten auszusehen haben, die verarbeitet werden sollen. Betrachtet man das Beispiel einer Rechnungsstellung, so ergeben sich zum einen die Daten des Kunden, wie zum Beispiel Adresse oder Bankverbindung , und zum anderen die Leistungen selbst. Die Beschreibung solcher Daten verbessern Schemas durch die Möglichkeit Datentypen anzugeben, und auch durch die Einfachheit, die die Verwendung von XML-Syntax in Schemas mit sich bringt. Eine der wichtigsten Neuerungen in XSD ist die umfangreiche Unterstützung von Datentypen. Durch sie können beim Austausch von XML-Daten die Datentypen bewahrt werden: XSD stellt 42 Basistypen zur Verfügung. Neben Typen zur Beschreibung von Zahlenwerten (integer, decimal, float, double ...), werden mit XSD auch Möglichkeiten zur Angabe von Datumswerten und Zeitspannen (time, date, timeDuration ...) eingeführt. Aus diesen Basistypen läßt sich zum Beispiel durch Beschränkungen (constraints) eine unbegrenzte Anzahl an eigenen Datentypen definieren. Mögliche Beschränkungen beziehen sich auf die Länge (length, minLength, maxLength), auf Beschränkung durch Patterns nach der Syntax von Regular Expressions (pattern), auf vorgegebene Beispielwerte (enumeration) oder auch auf Grenzwerte bei Zahlen (maxInclusive, maxExclusive, minInclusive, minExclusive). Für die Übertragung von Postleitzahlen kann man zum Beispiel, auf Basis des Typs string, einen String definieren der den Eigenschaften einer Postleitzahl entspricht. Die Länge der Zeichenkette wird durch length auf "5" gesetzt, und ein Pattern stellt sicher, daß nur Zahlenwerte akzeptiert werden. <xsd:simpleType name="PLZ"> <xsd:restriction base="xsd:string"> <xsd:maxLength value="5"/> <xsd:pattern value="^[1-9]*$"/> </xsd:restriction> </xsd:simpleType> Im heutigen Beispiel werden die Typen string, date und decimal verwendet. Der Typ date ist ein Datum nach dem Format yyyy-mm-dd, decimal ist eine einfache Dezimalzahl.Über das folgende Formular der Datei entry.asp werden alle notwendigen Rechnungsdaten eingegeben. Die Anwendung besteht aus drei Dateien, der entry.asp, der Access Datenbank Rechnungen.mdb und dem XSD-Schema schema.xsd. In der entry.asp tragen die Mitarbeiter eines Unternehmens die Leistungen, die für Kunden erbracht werden, in ein HTML-Formular ein. Die Daten werden im folgenden Schritt in eine Access Datenbank eingetragen. Auf der betreffenden ASP-Seite stehen noch die Auswahlmöglichkeiten zur Verfügung, dem Kunden die Rechnungsdaten als XML-Datei auf dem Server bereitzustellen und sie als Word Dokument zu erstellen. Eintragen von LeistungenFür eine vollständige Rechnung müssen nicht nur die einzelnen Leistungen eingetragen werden, sondern auch die Daten des jeweiligen Kunden in die Datenbank eingefügt werden. Die folgende Grafik stellt die Struktur der Rechnungen.mdb dar. Für jeden Kunden besteht ein Datensatz der beim Erstellen einer Rechnung ausgelesen wird. Um einen neuen Kunden anzulegen, muß in dem Formular die Option "New Client" angewählt werden, und die entsprechenden Felder müssen mit den Kundendaten gefüllt werden. Wenn der Kunde ausgewählt, oder ein neuer angelegt wurde, kann in das Feld "Services" die Beschreibung der erbrachten Leistung, und in "Price", wie zu erwarten, der Preis eingetragen werden. Vor dem Absenden des Formulars stehen noch die Optionen "Leistung anfügen" und "Rechnung erstellen" zur Auswahl. Die Daten werden schließlich, wie im Artikel Einfügen eines Datensatzes mit dem INSERT Statement erklärt, eingefügt. strConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" & "DataSource=C:\Inetpub\wwwroot\aspheute\Rechnungen.mdb" Set conn = Server.CreateObject("ADODB.Connection") conn.Open strConnStr strNewClient = Request.Form("Clients") strClientName = Request.Form("ClientName") strStreet = Request.Form("Street") strZipCode = Request.Form("ZipCode") strCity = Request.Form("City") strCountry = Request.Form("Country") strService = Request.Form("Service") strPrice = Request.Form("Price") If strNewClient = "New" Then strNewClient = "INSERT INTO Clients " & _ (ClientName, Street, ZipCode, City, Country)" & _ "VALUES ('"&strClientName&"','"&strStreet&_ "','"&strZipCode&"','"&strCity&"','"&strCountry&"')" conn.Execute strNewClient End If strNewService = "INSERT INTO Services" & _ (ClientName, Service, Price )" & _ "VALUES ('" & strClientName & "','" & strService & _ "','" & strPrice & "')" conn.Execute strNewService Erstellen von RechnungenWenn die Rechnung als XML erstellt werden soll, liest die Anwendung die Rechnungsdaten aus der Datenbank aus und erstellt mit Hilfe des DOMs ein XML-Dokument. Der Artikel Auslesen von XML Dateien mit dem DOM bietet eine Einführung in die Arbeit mit dem DOM. Zuerst wird ein Recordset-Objekt erstellt, das Datensätze der erbrachten Leistungen enthält. Wie im angesprochenen Artikel wird nun mittels DOM ein XML-Dokument erstellt. Nur wird in diesem Fall kein XML-File geladen, sondern mit Hilfe der DOM-Methoden .AppendChild(), .SetAttribute(), und .CreateElement() ein neues kreiert. Nach dem Erstellen des Root-Elements wird es dem nächsthöheren Element angehängt (das Root Element an das DOM Dokument) und seine Eigenschaften werden definiert. Dieser Vorgang wiederholt sich entsprechend der Baumstruktur des zu erstellenden Files. Set Data = Server.CreateObject("ADODB.Recordset") Data.ActiveConnection = strConnStr Data.Source = "SELECT * FROM Services WHERE" &_ "ClientName LIKE '" & strClientName & "' " Data.CursorType = 0 Data.CursorLocation = 2 Data.LockType = 3 Data.Open Set XMLDoc = Server.CreateObject("Msxml2.DOMDocument") Set DocRoot = XMLDoc.CreateElement("Services") XMLDoc.AppendChild(DocRoot) DocRoot.SetAttribute "xmlns", "yournamespace" DocRoot.SetAttribute "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" DocRoot.SetAttribute "xsi:schemaLocation", "yournamespace C:\Inetpub\wwwroot\aspheute\schema.xsd" While Not Data.EOF dtEntry = CDate(Data.Fields("Date")) strBillService = Data.Fields("Service") intBillPrice = Data.Fields("Price") Set Entry = XMLDoc.CreateElement("Entry") DocRoot.appendChild (Entry) Set Datum = XMLDoc.CreateElement("Datum") If Len(CStr(Month(dtEntry))) = 1 Then Monat = "0"& Month(dtEntry) Else Monat = Month(dtEntry) End If If Len(CStr(Day(dtEntry))) = 1 Then Tag = "0"& Day(dtEntry) Else Tag = Day(dtEntry) End If BillDate = Year(dtEntry)&"-"& Monat &"-"& Tag Datum.Text = BillDate Entry.appendChild (Datum) Datum.SetAttribute "type", "date" Set Service = XMLDoc.CreateElement("Service") Service.Text = strBillService Entry.appendChild (Service) Service.SetAttribute "type", "string" Set Price = XMLDoc.CreateElement("Price") Price.Text = intBillPrice Entry.appendChild (Price) Price.SetAttribute "type", "decimal" Data.MoveNext Wend Data.MoveFirst Set Client = XMLDoc.CreateElement("Client") DocRoot.appendChild (Client) Set Name = XMLDoc.CreateElement("Name") Name.Text = strClientName Client.appendChild (Name) Name.SetAttribute "type", "string" Set Street = XMLDoc.CreateElement("Street") Street.Text = strStreet Client.appendChild (Street) Street.SetAttribute "type", "string" Set ZipCode = XMLDoc.CreateElement("ZipCode") ZipCode.Text = strZipCode Client.appendChild (ZipCode) ZipCode.SetAttribute "type", "string" Set City = XMLDoc.CreateElement("City") City.Text = strCity Client.appendChild (City) City.SetAttribute "type", "string" Set Country = XMLDoc.CreateElement("Country") Country.Text = strCountry Client.appendChild (Country) Country.SetAttribute "type", "string" Dieses XML-Dokument wird gegen das folgende Schema validiert (schema.xsd), und dann als XML-File gespeichert. <?xml version="1.0" ?> <xsd:schema targetNamespace="yournamespace" xmlns="yournamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="Date" type="xsd:date"/> <xsd:element name="Service" type="xsd:string"/> <xsd:element name="Price" type="xsd:decimal"/> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="Street" type="xsd:string"/> <xsd:element name="ZipCode" type="xsd:string"/> <xsd:element name="City" type="xsd:string"/> <xsd:element name="Country" type="xsd:string"/> <xsd:element name="Entry"> <xsd:complexType> <xsd:sequence> <xsd:element ref="Date" /> <xsd:element ref="Service" /> <xsd:element ref="Price" /> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="Client"> <xsd:complexType> <xsd:sequence> <xsd:element ref="Name" /> <xsd:element ref="Street" /> <xsd:element ref="ZipCode" /> <xsd:element ref="City" /> <xsd:element ref="Country" /> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="Services"> <xsd:complexType> <xsd:sequence> <xsd:element ref="Entry" /> <xsd:element ref="Client" /> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> Die Validierung stellt sicher, daß die Daten dem Schema entsprechen, und gewährleistet somit einen fehlerfreien Datenaustausch. Bei der Verwendung von XSD auf dem IIS geschieht dies durch den MSXML 4.0 Parser. Der XML-Parser der Version 3.0 unterstützt XSD nicht. Hier der Code zur Validierung eines XML Dokuments gegen unser Schema: Set xmlDom = Server.CreateObject("MSXML2.DOMDocument.4.0") Set xsc = Server.CreateObject("MSXML2.XMLSchemaCache.4.0") xsc.Add "http://www.w3.org/2001/XMLSchema", "C:\yourpath\schema.xsd" Set xmlDom.schemas = xsc xmlDom.async = False xmlDom.loadXML ("C:\yourpath\sample.xml") If xmlDom.parseError.errorCode <> 0 Then Response.Write("Error Reason: " & Space(3) & xmlDom.parseError.reason & "Source Text: " & Space(3) & xmlDom.parseError.srcText & vbCrLf & "Error Line: " & Space(3) & xmlDom.parseError.Line & vbCrLf & "Error Position: " & Space(3) & xmlDom.parseError.linepos & vbCrLf & "File Name: " & Space(3) & xmlDom.parseError.url) Else Response.Write("No Error") End If Der erste Schritt bei der Validierung ist das Erstellen eines SchemaCache-Objektes. Diesem wird mittels der Add()-Methode das Schema hinzugefügt. Dieses Objekt wird dann dem DOM-Objekt zugeordnet. Durch die Load()-Methode des DOM-Objektes werden die XML-Daten eingelesen. Bei diesem Vorgang findet die eigentliche Validierung der Daten statt. Wenn der Mitarbeiter X nun Daten in das Formular eingetragen hat, die nicht den Vorgaben des Schemas entsprechen (zB.: negativer Rechnungsbetrag), gibt der Parser einen Error zurück, der über die Error-Collection ausgewertet wird. Abschließend werden aus den Rechnungsdaten eine XML-Datei und/oder ein Word-Dokument erstellt. Die Verwendung des Word Objektes wird einführend in dem Artikel Mit ASP ein Word Dokument am Server generieren beschrieben. blxmlfile = Request.Form("makefile") blword = Request.Form("makeword") If blword Then Set ElemList1 = xmlDom.getElementsByTagName("Datum") Set ElemList2 = xmlDom.getElementsByTagName("Service") Set ElemList3 = xmlDom.getElementsByTagName("Price") Set ElemList4 = xmlDom.getElementsByTagName("Client") Dim WdApp,objDocument,objRange,objTable,i,header,sum 'Word Konstanten Const wdAlignParagraphCenter = 1 Const wdAlignParagraphLeft = 0 Const wdParagraph = 4 Const wdHorizontalPositionMargin = 0 Const wdTableLeft = -999998 Const wdCollapseEnd = 0 Set WdApp = Server.CreateObject("Word.Application") WdApp.Application.Visible = False Set objDocument = WdApp.Documents.Add("Vorlage.dot") Set objRange = objDocument.Range header = "Rechnung an" & vbCrLf For Each item in ElemList4.item(0).childNodes header = header & item.Text & vbCrLf Next With objRange .ParagraphFormat.Alignment = wdAlignParagraphCenter .Font.Size = 12 .Font.Name = "Arial" .InsertAfter(header) .MoveEnd(wdParagraph) .Collapse(wdCollapseEnd) End With Set objTable = WdApp.ActiveDocument.Tables.Add &_ (objRange, ElemList2.length, 3,1,1) sum = 0 For i = 0 To (ElemList2.length -1) objTable.Cell(i,1).Range.InsertAfter &_ (ElemList1.item(i).text) objTable.Cell(i,2).Range.InsertAfter &_ (ElemList2.item(i).text) objTable.Cell(i,3).Range.InsertAfter &_ (ElemList3.item(i).text) sum = sum + ElemList3.item(i).text Next objTable.Cell(ElemList2.length,1).Range.InsertAfter &_ ("Summe") objTable.Cell(ElemList2.length,2).Range.InsertAfter &_ (sum) objDocument.SaveAs Server.MapPath("C:\yourpath\Rechnung.doc") objDocument.Close WdApp.Application.Quit End If If blxmlfile Then XMLDoc.save("C:\yourpath\sample.xml") End If SchlußbemerkungDie Zukunft von Schemas liegt in der Standardisierung des Datenaustausches. Initiativen wie ebXML arbeiten daran allgemeine Beschreibungen von Daten zu etablieren. So wird es zB. ein standardisiertes Schema für Rechnungen geben, nach dem sich alle Anwendungen ausrichten lassen. In solchen Bereichen macht die Prüfung der Benutzereingaben einen großen Bestandteil der Anwendungen aus. Durch die Möglichkeiten der Validierung von Schemas kann diese Last von den Schultern solcher Anwendungen genommen werden. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Arbeiten mit dem SQL Server XML View Mapper Links zu anderen Sites
ebXML Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |