Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Verwendung von XML-Schemas (XSD)

Geschrieben von: Frederic Ganner
Kategorie: XML

This printed page brought to you by AlphaSierraPapa

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 Leistungen

Fü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 Rechnungen

Wenn 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ßbemerkung

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

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20010925.zip

Verwandte Artikel

Arbeiten mit dem SQL Server XML View Mapper
http:/www.aspheute.com/artikel/20020416.htm
Auslesen von XML Dateien mit dem DOM
http:/www.aspheute.com/artikel/20000417.htm
Einfügen eines Datensatzes mit dem INSERT Statement
http:/www.aspheute.com/artikel/20001107.htm
Mit ASP ein Word Dokument am Server generieren
http:/www.aspheute.com/artikel/20010319.htm
Was sind XML Schemas?
http:/www.aspheute.com/artikel/20010514.htm
XML-Daten verarbeiten mit XSLT
http:/www.aspheute.com/artikel/20020116.htm

Links zu anderen Sites

ebXML
http://www.ebxml.org
MSDN XML/XSL
http://msdn.microsoft.com/xml/
Oasis Schema Seiten
http://www.oasis-open.org/cover/schemas.html
Schema Validator
http://www.w3.org/2001/03/webdata/xsv/
XML Schema School
http://www.w3schools.com/schema/

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.