copyright (c)2003-2005   useGroup
XSLT

66151@usegroup.de

Einführung in XML/XSLT

Schemata

nach untenWarum Schemata

nach untenEinbindung

nach untenTags

nach untenUntertags

nach untenInline Schemata

nach untenTags zur Auswahl stellen

nach untenminOccurs

nach untenmaxOccurs

nach untenTags in beliebiger Reihenfolge erlauben

nach untenAttribute

nach untenAttributaufzählungen

nach untenWertebereich einschränken

nach untenDatentypen

nach untenEigene Datentypen definieren

nach untenEntities

Warum Schemata

nach obenWarum Schemata 

Anders als DTDs werden Schemata in einem XML-Format definiert. Das ist an und für sich schonmal ein Vorteil, dazu kommt aber dass das u.A. so ist weil Schemata erst 2001 vom W3C verabschiedet worden sind und es deshalb erheblich mehr Werkzeuge gibt die auf Konformität mit einem DTD prüfen und Schemata noch nicht interpretieren. Ich persönlich nutze Schemata nur dort, wo ich deren Vorteil brauche und der ist: Daten und nicht Dokumentorientiert zu arbeiten.
Es gibt in Schemata verschiedene Datentypen, in DTDs gibt es diese nicht. Ich kann also sagen ein Tag darf nur ein Datum enthalten, bei DTDs muss ich damit leben dass die XML-Autoren in ein Feld namens Datum 1999, 1.10.1999, erster Oktober 1999 oder Mickey Mouse hat einen Bruder reinschreibt. Werden die XMLs automatisch verarbeitet, z.B. in eine Datenbank eingetragen wird das entsprechende Programm spätestens beim Mickey-Mouse-Satz seine helle Freude haben.



Einbindung

nach obenEinbindung 

Schemata werden in die XML-Datei eingebunden mit

<ROOTELEMENT xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SCHEMADATEINAME.xsd">

...

</ROOTELEMENT>



Tags

nach obenTags 

Tags werden mit dem xsd:element-Tag beschrieben. Ein sehr einfaches Schema wäre z.B.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" elementFormDefault="qualified">
	<xsd:element name="p" type="xsd:string"/>
</xsd:schema>
Ein leeres Root-Tag habe ich in der Praxis übrigens noch nie gesehen...
Der Typ ist übrigens mein XML-Lieblingstag: erstaunlich leicht zu programmieren lässt sich nämlich ein eigener Typ:



Untertags

nach obenUntertags 

mit

	<xsd:complexType name="wasbeliebt">
		<xsd:sequence>
			<xsd:element name="b" type="xsd:string"/>
			<xsd:element name="i" type="xsd:string"/>
  			<xsd:element name="u" type="xsd:string"/>
  		</xsd:sequence>
	</xsd:complexType>
definieren Sie den Typ "wasbeliebt", den Sie in p mit
	<xsd:element name="p" type="wasbeliebt"/>
einbinden. Er verpflichtet Sie zu einen b, einem i und einem u-Tag mit jeweils einem String als Inhalt.



Inline Schemata

nach obenInline Schemata 

Man kann die complexTypes übrigens auch gleich ins Element einbetten:

	<xsd:element name="p">
	<xsd:complexType name="wasbeliebt">
			<xsd:element name="i" type="xsd:string"/>
	</xsd:complexType>
	</xsd:element>
Wobei sich der complexType zwar mit einem Namen bezeichnen, aer nicht mehr ausserhalb des element-Tags als type="wasbeliebt" angeben lässt. Dass sicht kein element-type definieren UND gleichzeitig ein complexType einbetten lässt sollte sich von selbst verstehen.



Tags zur Auswahl stellen

nach obenTags zur Auswahl stellen 

Wenn Sie den DTD-Teil dieses Tutorials schon gelesen haben, wissen Sie aber, dass das nicht Sinn der Sache war. Es sollen beliebig viele und geschachtelte i us und bs möglich sein. Ein xsd:choice sieht zwar wie eine Lösung aus, ist aber keine

	<xsd:complexType name="wasbeliebt">
		<xsd:choice>
			<xsd:element name="b" type="xsd:string"/>
			<xsd:element name="i" type="xsd:string"/>
  			<xsd:element name="u" type="xsd:string"/>
  		</xsd:choice>
	</xsd:complexType>
weil es nur ein Tag erlaubt - immerhin kann das jetzt ENTWEDER b, u oder p sein. Die Lösung liegt in den Attributen:



minOccurs

nach obenminOccurs 

minOccurs und maxOccurs liegen in engem Wettstreit mit type um meine persönlichen XML-Lieblingsattribute. Während Type eine beinahe schon an PHP erinnernde intuitive (weil logische) Programmierung erlaubt sind minOccurs und maxOccurs in vielen Tags erlaubt und -- bedeuten immer das Gleiche (keine Ausnahmen, kein fehlersuchen, kein Referenzenwühlen).
minOccurs="n" bedeutet: Das in dem Tag spezifizierte Element muss mindestens n-mal vorkommen.



maxOccurs

nach obenmaxOccurs 

maxOccurs="n" verhält sich analog: Das in dem Tag spezifizierte Element darf höchstens n-mal vorkommen. Wobei jede Zahl für eine Zahl steht und "unbounded" für unendlich. Mit diesen beiden Elementen lässt sich dann auch unser ibu (italic/bold/underline)-Beispiel weiter bringen: durch ein ergänzen einer Zeile erhält man nämlich

		<xsd:choice minOccurs="0" maxOccurs="unbounded">
... die Möglichkeit, die Sequenz dreimal hintereinander zu schreiben. An sich hätte man auch die Möglichkeit, das minOccurs und maxOccurs hinter die einzelnen Elemente zu schreiben, etwa
	<xsd:element name="b" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
	<xsd:element name="i" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
	<xsd:element name="u" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
so, (diese 3 Zeilen würden übrigens auch in einer Sequenz das gewünschte Ergebnis bringen). Genaugenommen besteht ein ziemlich komplizierter Unterschied der sich ungefähr so erklären lässt: Entweder, man macht beliebig viele Choices die entweder aus i, b oder u bestehen oder man macht eine Choice die aus beliebig vielen i, bs und us besteht.
minOccurs="0" und maxOccurs="0" bei jedem Element machen die Sequenz übrigens de-facto zu einem Choice, das Problem ist, wenn die Sequenz nicht eingehalten wird (z.B. ein u vor einem b kommt), wird das Stylesheet invalid wenn nicht auch die Sequenz selbst als minOccurs="0" und maxOccurs="0" definiert wurde (denn dann könnte eine Sequenzdie nur aus u besteht vor einer Sequenz, die nur aus b besteht, existieren).
Lange Rede kurzer Sinn: obwohl es noch mindestens zwei andere Arten gibt definiert
	<xsd:element name="p" type="wasbeliebt"/>
	<xsd:complexType name="wasbeliebt">
		<xsd:choice minOccurs="0" maxOccurs="unbounded">
			<xsd:element name="b" type="xsd:string"/>
			<xsd:element name="i" type="xsd:string"/>
			<xsd:element name="u" type="xsd:string"/>
		</xsd:choice>
	</xsd:complexType>

die Sache. Basta.



Tags in beliebiger Reihenfolge erlauben

nach obenTags in beliebiger Reihenfolge erlauben 

Leichter als in DTDs kann man in Schemata Tags erlauben und von der Reihenfolge absehen: wie xsd:sequence und xsd:choice wird xsd:all definiert.

	<xsd:element name="p" type="wasbeliebt"/>
	<xsd:complexType name="wasbeliebt">
		<xsd:all>
			<xsd:element name="b" type="xsd:string"/>
			<xsd:element name="i" type="xsd:string"/>
			<xsd:element name="u" type="xsd:string"/>
		</xsd:all>
	</xsd:complexType>

Es arbeitet wie eine Sequence unabhängig von der Reihenfolge, mit jeweils maximal einem Auftreten eines Tags.



Attribute

nach obenAttribute 

Attribute werden in einem complexType mit xsd:attribute definiert (und dürfen im complexType immer erst NACH choices oder sequences definiert werden).

	<xsd:element name="p" type="wasbeliebt"/>
	<xsd:complexType name="wasbeliebt">
		<xsd:attribute name="ibu" type="xsd:string"/>
	</xsd:complexType>
oder
	<xsd:element name="p" type="wasbeliebt"/>
	<xsd:complexType name="wasbeliebt">
		<xsd:choice minOccurs="0" maxOccurs="unbounded">
			<xsd:element name="b" type="xsd:string"/>
			<xsd:element name="i" type="xsd:string"/>
			<xsd:element name="u" type="xsd:string"/>
		</xsd:choice>
		<xsd:attribute name="ibu" type="xsd:string"/>
	</xsd:complexType>
(als schema2.xml bzw. schema2.xsd) Da haben wir übrigens den Dokumenttyp, der nur das Top-Level-Tag beinhalten darf.
Mit dem Attribut use können Sie übrigens angeben ob das entsprechende Attribut definiert werden muss. Unterschieden wird zwischen "required" (muss angegeben sein), "optional" (kann angegeben sein), "default" (kann angegeben sein) und "prohibited" (darf nicht angegeben sein, was darauf hindeutet, dass in Schemata irgendwo ein "if" definiert sein muss). Ein min/maxOccurs verbietet sich deshalb, weil Attribute ja sowieso nur höchstens einmal den gleichen Namen haben dürfen.
default-Werte für Attribute gibt es in Schemas auch, soweit ich das verstanden habe werden sie mit use="default" und einem weiteren Attribut, value="Wert" gebildet. Das habe ich auch in schema3.xsd angedeutet und mit XMLSpy validieren lassen, aber mein Saxon 6.2.2 scheint es nicht auszuwerten. Genausowenig wie default-Werte für Tags nebenbei, die mit dem Attribut "default="Defaultwert"" möglich sein sollten.



Attributaufzählungen

nach obenAttributaufzählungen 

Sie können wie in DTDs die Auswahlmöglichkeiten bei einem Attribut gezwungenermaßen einschränken -- und zwar durch verwenden eines simpleTypes mit einer restriction:

		<xsd:attribute name="bio" use="required">
            	<xsd:simpleType>
                	<xsd:restriction base="xsd:string">
                    		<xsd:enumeration value="clear"/>
                    		<xsd:enumeration value="investigating"/>
                    		<xsd:enumeration value="suspicious"/>
                	</xsd:restriction>
            	</xsd:simpleType>
	        </xsd:attribute> 
Wie man sieht ist "base" der Datentyp, der eingeschränkt werden soll.



Wertebereich einschränken

nach obenWertebereich einschränken 

angenommen wir möchten zu p noch ein Attribut, Note. Diese Note soll eine ganze Zahl im Bereich von 1-6 sein (in der Schweiz von 6-1 ;)). Wir machen auch das mit einer restriction, geben aber ein minInclusive und ein maxInclusive vor.

<xsd:simpleType name="notentyp">
    <xsd:restriction base="xsd:integer">
        <xsd:minInclusive value="1"/>
        <xsd:maxInclusive value="6"/>
    </xsd:restriction>
</xsd:simpleType>



Datentypen

nach obenDatentypen 

Von Hause aus bieten Schemas die folgenden Datentypen:

Name Beispiele Erklärung
String "Hallo Welt" Zeichenkette
boolean {true, false} entweder true oder false
decimal 42.9 Kommazahl
float 42.9, -12.4, 44, 2.03E5, 0, -0, INF, -INF, NAN INF=Unendlich, -INF=minus Unendlich, NAN=Not A Number, keine Zahl
duration P2Y5M4DT5H17M33.4S Anzahl Jahre, Anzahl Monate, Anzahl Tage, Trenner zwischen Datum und Zeit ("T"), Stunden, Minuten und Sekunden
dateTime 2001-06-08T18-46-02 Jahre, Monate, Tage, Trenner zwischen Datum und Zeit ("T"), Stunden, Minuten und Sekunden
time 19:12:00.03 Stunden,Minuten,Sekunden.Hundertstel
date 2001-06-08 Jahr-Monat-Tag
gYearMonth 2001-06 Jahre, Monate
gYear 2001 Jahre
gMonthDay 12-12 Monat, Tag
gDay 12 Tag
gMonth 5 Monat
hexBinary 12EAB0 Ein hexadezimaler Wert
anyURI http://www.usegroup.de/ Eine URI
Abgeleitete Datentypen
integer 12 Ganzzahlen
positiveInteger 12 positive Ganzzahlen
negativeInteger -12 Ganzzahlen kleiner Null
long 122 -9223372036854775808 bis 9223372036854775808
64-Bit Integer
int 122 -2147483648 bis 2147483647
32-Bit Integer
byte 122 -127 bis 128 8-Bit Integer



Eigene Datentypen definieren

nach obenEigene Datentypen definieren 

Mit

	<xsd:element name="plz" type="plz"/>	
	...
	<xsd:simpleType name="plz">
    		<xsd:restriction base="xsd:integer">
        <xsd:length value="5"/>
können Sie angeblich (XMLSpy interpretier offensichtlich falsch) den Taginhalt auf 5 Zahlen beschränken, spätestens bei dem Versuch, eine Telefonnummer mit Vorwahl zu verlangen, muss ich mangels Testumgebung aufgeben. Versuchen wollte ich
    <xsd:restriction base="xsd:integer">
      <xsd:pattern value="\d{5}\/d{5}"/>
    </xsd:restriction>
für ein Pattern aus 5 digits, einem /, den man bei regulären Ausdrücken mit dem \ maskiert (\/) und dann nochmals 5 digits. Genaugenommen ist das eher ein Beispiel für schlechte reguläre Ausdrücke; denn vierstellige Vorwahlen sollten im heutigen Handyzeitalter möglich sein und die Länge der Nummer auf keinen Fall nur 5 betragen dürfen.



Entities

nach obenEntities 

"Since XML Schema begins work on the infoset of a well-formed (perhaps valid) XML document, parsed entity definition substitution has already taken place. We decided a two-pass architecture was too clunky, and arguably impossible, and concluded the best thing was to leave XML 1.0 entities to XML 1.0 mechanisms (i.e. you can define entities in the internal subset) ", Henry S. Thompson.
Auf Deutsch: Da Schemata nur auf XML-Dateien anzuwenden sind, die schon well-formed sind, muss jeder sehen wo er bleibt.
Zum Beispiel hier:

<!DOCTYPE ROOTELEMENT [
<!ENTITY eacute "é">
]>
in jeder XML-Datei macht zwar keinen Spaß, funktioniert aber. Dahingegen muss ich leider zugeben, dass ich das W3C-Beispiel für Entityähnliche Elemente nicht zum laufen bekommen habe:
We can achieve a similar but not identical outcome by declaring an element in a schema, and by setting the element's content appropriately: 

<xsd:element name="eacute" type="xsd:token" fixed="é"/>

And this element can be used in an instance document: 

Using an element instead of an entity in an instance document. 
<?xml version="1.0" ?>
<purchaseOrder xmlns="http://www.example.com/PO1"
               xmlns:c="http://www.example.com/characterElements"
               orderDate="1999-10-20>
 <!-- etc. --> 
  <city>Montr<c:eacute/>al</city>
 <!-- etc. -->
</purchaseOrder>



copyright (c)2003-2005   useGroup