Donnerstag, 4. Dezember 2008





April 2006
aus XML & Web Services Magazin Ausgabe: 3.2003
Zimmer frei?
Dynamisch dynamische SVG Vektorgrafiken erstellen
von Alexander Roock

SVG Vektorgrafiken sind - als eine XML-Sprache - geradezu prädestiniert, über XSL-Transformationen aus XML-Quellen dynamisch erzeugt zu werden. Dieser Artikel beschreibt am Beispiel eines Raumbelegungsplans eine mögliche Vorgehensweise zur Erstellung einer interaktiven SVG-Anwendung mit datenbankgestützten Inhalten auf Basis der Microsoft-Technologien SQL Server 2000, Microsoft XML-Parser/XSLT-Prozessor und .NET.


Die Aufgabe war klar umrissen: Es sollte eine Visualisierung erstellt werden,
die die aktuelle Belegung der Seminarräume im Intranet verfügbar macht. Die Informationen,
die darzustellen waren, waren ziemlich umfangreich, so sollte zu jedem Raum die
Information über Seminartitel, Dozent und alle Teilnehmer verfügbar gemacht werden.
Aufgrund der Informationsmenge war es von vornherein klar, dass nicht alle Details
auf einmal präsentiert werden konnten. Vielmehr war gewünscht, eine gewisse Interaktivität
einzubauen, die es erlaubte, Seminarräume auszuwählen und somit die gleichzeitig
dargestellten Informationen überschaubar zu halten.


Zur Lösung der Fragestellung bot sich für uns SVG aus vielerlei Hinsicht an: SVG
unterstützt die Erstellung interaktiver Grafiken mittels eingebetteter ECMA-Scripts.
Des Weiteren lässt es sich aufgrund der Tatsache, dass es sich um XML handelt,
hervorragend mittels XSLT mit weiteren Daten anreichern. Der Nachteil, dass SVG
zurzeit noch nicht nativ durch die gängigen Browser unterstützt wird, hat sich
für uns nicht gestellt, da wir im Intranet das Adobe SVG Viewer Plugin problemlos
verteilen konnten.

Die Lösungsarchitektur
Grob gesehen ergibt sich damit die in Abbildung
1 veranschaulichte Lösungsarchitektur. Im Mittelpunkt steht eine XSL-Transformation,
die durch eine .NET-Applikation initiiert und mittels des Windows-Taskplaners
(ermöglicht das zeitgesteuerte Ausführen beliebiger Anwendungen) täglich in den
frühen Morgenstunden ausgeführt wird. Das Template (raumbelegung2svg.xslt,
siehe Begleit-CD) beschreibt dabei die Art und Weise, wie die XML-Daten vom Datenbankserver
in eine SVG-Vektorgrafik übersetzt werden. Um die Belegungsinformationen aus der
Datenbank nicht über einen Zwischenschritt selbst nach XML übersetzen zu müssen,
nutzen wir die XML-Fähigkeiten des Microsoft SQL Servers 2000. Die .NET-Applikation
regt dann lediglich noch den XSLT-Prozessor an, den XML-Datenbankstrom abzufragen,
mit Hilfe von XSLT zu transformieren und das Ergebnis in einem Verzeichnis auf
dem Webserver bereitzustellen.


Abb. 1: Die Lösung im Überblick

Um diese Lösungsarchitektur umzusetzen,
sind im Wesentlichen fünf Schritte nötig, die im Folgenden beschrieben werden.

Erstellen der SVG-Vorlage

Zunächst benötigen wir eine SVG-Vorlage, die einen Plan unserer Schulungsräume
darstellt. Da uns ein solcher Raumplan bereits als CAD-Datei vorlag, ergaben sich
mehrere Möglichkeiten, um zur gewünschten SVG zu kommen. Wir entschlossen uns
für die wahrscheinlich am wenigsten Nahe liegende Variante: Wir programmierten
die SVG von Hand in einem einfachen Editor. Verrückt?


Nun, die beiden anderen Varianten hatten für uns entscheidende Nachteile: Die
einfache Konvertierung (Import der CAD-Datei, Export als SVG) liefert zwar eine
schön anzusehende Grafik, die einzelnen Räume sind jedoch nicht als geschlossene
Objekte (Rechtecke oder Polygonzüge) in der Grafik vorhanden, was für uns das
spätere Umfärben auf einen Mausklick des Benutzers hin schwierig gestaltet hätte.
Die zweite Variante wäre das komplette Neuzeichnen des Raumplans z.B. mit Adobe
Illustrator oder Corel Draw gewesen, die in ihren aktuellen Versionen SVG exportieren
können. Wir entschieden uns trotzdem für die Editor-Variante, weil wir so zum
einen einen sehr viel saubereren SVG-Code erzeugen konnten und zum anderen der
Aufwand relativ gering war, da wir aus der CAD-Vorlage (bzw. einem GIF-Export)
die entscheidenden Koordinaten einfach ablesen und in den SVG-Code übernehmen
konnten. Einen Ausschnitt, der die Definition einiger Seminarräume darstellt,
sehen sie in Listing 1, das fertige Ergebnis finden sie in der Datei raumplan_basis.svg
auf der CD.


Listing 1

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
.
.
<!-- Seminarräume -->
<g id="seminarraeume" style="stroke:black;fill:red;fill-opacity:0.6;stroke-width:1px;">
<path id="r4" d="M 666,129 L 695,98 L 657,67 L 630,98 Z"/>
<path id="r5" d="M 630,98 L 657,67 L 627,54 L 619,88 Z"/>
<path id="r6" d="M 619,88 L 627,54 L 623,51 L 568,49 L 568,88 Z"/>
<rect id="r7" y="49" x="505" width="63" height="39"/>
<rect id="r8" y="49" x="459" width="46" height="39"/>
.
.
</g>
.
.
</svg>

Erweitern der SVG-Vorlage um Interaktivität
Die erste Hürde war genommen, wir
wollten jedoch eine Grafik, auf der der Benutzer die einzelnen Räume auswählen,
diese andersfarbig dargestellt und die Raumbelegungsinformationen angezeigt werden
konnten. Dazu haben wir die Vorlage um ECMA-Script-Anteile erweitert, die Benutzermausklicks
auswerten und die beschriebenen Änderungen vornehmen.


Das Scripting in SVGs ähnelt sehr stark dem in HTML. Kein Wunder, schließlich
ist ECMA-Script die standardisierte Variante von JavaScript. So ist die Vorgehensweise
dann auch praktisch identisch. Zunächst muss ein Event Handler registriert werden,
welcher auf den Objekten definiert wird, die auf das gewünschte Event reagieren
sollen. Beispielhaft folgt hier die notwendige Änderung für einen Raum:

<rect onactivate="splitter(7)" id="r7" y="49" x="505" width="63" height="39"/>


Des Weiteren fügen wir in das SVG für jeden Seminarraum noch einen Textbereich
ein, der zunächst nur den Raumnamen anzeigt, später jedoch um die weiteren Informationen
aus der Datenbank ergänzt wird. Dieser Textbereich ist standardmäßig ausgeblendet
(visibility-Eigenschaft auf hidden gesetzt) und wird bei Aktivierung
des jeweiligen Raumes eingeblendet:

<text visibility="hidden" id="t7" x="30" y="190">
<tspan font-size="120%" x="30" dy="2.5ex">Raum 7 / Friedrichshain</tspan>
</text>

Der onactivate-Event Handler
wird nun also aufgerufen, wenn das betreffende Objekt aktiviert, also z.B. per
Maus angeklickt wird. Aufgerufen wird eine Funktion namens splitter, der
die Raumnummer des ausgewählten Raums als Parameter mitgegeben wird. Die Funktion
und den Rest des Skripts finden Sie in Listing 2.


Listing 2

<svg xmlns="http://www.w3.org/2000/svg">
<script type="text/ecmascript"><![CDATA[
var state = new Array();
for ( var i = 0 ; i <= 35 ; i++ ){
state[i] = false;
}

function splitter(no)
{
if ( state[no] == false )
turnOn(no);
else
turnOff(no);
}

function turnOn(no){
turnAllOff();
var target = document.getElementById("r"+no);
target.getStyle().setProperty("fill-opacity","1");
target = document.getElementById("t"+no);
target.getStyle().setProperty("visibility","show");
state[no] = true;
}

function turnOff(no){
var target = document.getElementById("r"+no);
target.getStyle().setProperty("fill-opacity","0.6");
target = document.getElementById("t"+no);
target.getStyle().setProperty("visibility","hidden");
state[no] = false;
}

function turnAllOff(){
var target;
for ( var i = 0 ; i <= 35 ; i++ ){
if ( state[i] == true ){
target = document.getElementById("r"+i);
target.getStyle().setProperty("fill-opacity","0.6");
target = document.getElementById("t"+i);
target.getStyle().setProperty("visibility","hidden");
state[i] = false;
}
}
}]]></script>
.
.
.

Die durch den Event Handler aufgerufene Funktion
splitter überprüft im eigens dafür angelegten Feld state[] den Zustand
des Raumes (ein- oder ausgeschaltet) und verzweigt entsprechend in die Funktion
turnOn() oder turnOff(). Die Funktion turnOn() vollführt
folgende vier Schritte:
  • Deaktivieren aller anderen Räume und ausblenden aller Textbereiche (turnAllOff())
  • Aktivieren des zur Raumnummer passenden Raums durch Intensivierung der Füllfarbe
  • Einblenden des zum Raum gehörenden Textbereichs
  • Status des Raumes im state[]-Feld auf true setzen
Für die Punkte 2 und 3 muss sich das Skript
die entsprechenden Objekte des DOMs (Document Object Models) holen. Um diesen
Vorgang zu vereinfachen, tragen sowohl der Raum selbst, als auch der zum Raum
gehörende Textbereich eine eindeutige ID, die sich aus Raumnummer und einem Präfix
zusammensetzt.


Die beiden Funktionen turnOff() und turnAllOff() funktionieren prinzipiell
analog, deaktivieren jedoch Raum und zugehörigen Text. Das komplette, interaktive
SVG finden sie in der Datei raumplan_interaktiv.svg.


Das so entstandene SVG wird uns als Vorlage für das XSLT-Stylesheet dienen, welches
den XML-Datenbankstrom in eben jenes SVG transformiert. Bevor wir uns aber mit
dem Stylesheet beschäftigen, wollen wir einen Blick auf die Datenbank werfen.

SQL Server 2000 und XML

Sicherlich kann man auch den traditionellen Weg gehen und das Resultset der Datenbankabfrage
selbst in das gewünschte XML-Format wandeln. Ein komfortablerer Weg ist es, die
XML-Fähigkeit aktueller Datenbanksysteme wie MS SQL Server oder Oracle 9i zu nutzen.


Microsofts SQL Server z.B. bringt seit der Version 2000 eine native Unterstützung
für XML mit, die es uns unter anderem erlaubt, Ergebnisse auf SQL-Anfragen als
XML zu erhalten. Dazu kann jedes SQL-Statement um die Schlüsselwörter FOR XML
ergänzt werden, wobei durch verschiedene Modi die Art und Weise der XML-Generierung
beeinflusst werden kann. Durch das Zusammenspiel mit dem Microsoft Webserver IIS
wird es sogar möglich, Datenbankabfragen über HTTP an den SQL Server zu richten
und den XML-Ergebnisstrom so durch Firewalls zu schleusen.


Eine genaue Beschreibung der XML-Fähigkeiten des SQL Servers würde den Rahmen
dieses Artikels sprengen, hier sei nur so viel gesagt: In unserem Szenario wird
der SQL Server über den Microsoft IIS per HTTP abgefragt, wobei ein Datumswert
als URL-Parameter mitgegeben wird. Die SQL-IIS-Integration sorgt für den Aufruf
einer parametrisierten Stored Procedure auf dem SQL Server, welcher das Datum
mitgegeben wird. Das XML-Ergebnis der Datenbank wird noch mittels einer XSL-Transformation
(welche hier nicht näher beschrieben wird) in ein für uns besser zu verarbeitendes
XML-Format gewandelt, bevor der IIS es an uns weiterreicht (siehe auch Abb. 2).


Abb. 2: Zusammenspiel zwischen SQL Server und IIS


In den Beispieldateien auf der Heft-CD finden sie zum Nachvollziehen sowohl das
Schema, das die vom IIS gelieferte XML-Struktur beschreibt (raumbelegung.xsd),
als auch ein Beispieldokument für eine konkrete XML-Instanz (raumbelegung.xml).

SQLXML für SQL Server 2000

Die Fähigkeiten des SQL Server 2000 bezüglich XML sind bestimmt durch den technologischen
Stand zum Erscheinungstermin des SQL Servers. Mittlerweile haben sich einige XML-Standards
entscheidend geändert, sodass Microsoft Anpassungen und auch Erweiterungen an
die veränderten Standards als zusätzliches Paket für den SQL Server zur Verfügung
stellt. SQLXML in der aktuellen Version 3.0 SP1 finden sie unter folgendem Link:
msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/001/824/msdncompositedoc.xml

Das SVG Transformations Stylesheet

Aufgabe des Stylesheets ist die Transformation des eben beschriebenen XML-Stroms
in das beschriebene interaktive SVG. Listing 3 zeigt einen Ausschnitt aus dem
Stylesheet, das komplette Stylesheet finden sie als raumbelegung2svg.xslt
auf der CD.


Im Stylesheet sorgt das erste Template für die Erzeugung des Grundgerüsts der
SVG, wie wir es in raumplan_interaktiv.svg definiert haben. Dabei werden
im Wesentlichen zwei Informationen ergänzt: Zunächst wird jedem Raum (hier gezeigt
für den Raum mit der Nummer 7) ein Attribut hinzugefügt, welches die Raumfarbe
auf Grün stellt, falls in der Datenbankabfrage keine Informationen zu diesem Raum
enthalten sind. Diese Räume sind also frei, alle anderen Räume werden mit der
Standardfüllfarbe Rot gefüllt.


Die zweite Änderung bezieht sich auf die Belegungsinformationen zu den Räumen.
Zu jedem Raum existiert ein ausgeblendeter Textkasten, wobei die XSLT-Anweisung
überprüft, ob es Raumbelegungsdaten für diesen Raum im XML-Dokument gibt und gegebenenfalls
das zweite Template aufruft, welches dann aus dem XML-Strom Informationen wie
Dozent und Teilnehmernamen in das SVG übernimmt.


Eine wichtige Rolle nimmt noch die output-Anweisung (2. Zeile) ein, in
der wir die doctype-Deklaration für das Zieldokument vornehmen und das
script-Tag als CDATA-Abschnitt des Zieldokuments auszeichnen.


Listing 3

<xsl:stylesheet  xmlns:svg="http://www.w3.org/2000/svg" exclude-result-prefixes="svg">
<xsl:output doctype-public="-//W3C//DTD SVG 1.0//EN" doctype-system="http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" cdata-section-elements="svg:script" media-type="text/xml"/>

<xsl:template match="/">
<svg xmlns="http://www.w3.org/2000/svg">
.
.
<rect onactivate="splitter(7)" id="r7" y="49" x="505" width="63" height="39">
<xsl:if test="not(raumbelegung/raum[@nummer='07'])"><xsl:attribute
name="fill">green</xsl:attribute></xsl:if>
</rect>
.
.
<text visibility="hidden" id="t7" x="30" y="190">
<tspan font-size="120%" x="30" dy="2.5ex">Raum 7 / Friedrichshain</tspan>
<xsl:apply-templates select="raumbelegung/raum[@nummer='07']"/>
</text>
.
.
</svg>
</xsl:template>

<xsl:template match="raum" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<tspan font-weight="bold" x="30" dy="5ex">
<xsl:value-of select="seminar"/>
(<xsl:value-of select="seminar/@nr"/>)
</tspan>
<tspan stroke="red" x="30" dy="4ex">
<xsl:value-of select="dozent/vorname"/>
<xsl:value-of select="dozent/name"/>
</tspan>
<tspan>(Dozent)</tspan>
<xsl:for-each select="teilnehmerliste/teilnehmer">
<tspan x="30" dy="2.5ex">
<xsl:value-of select="vorname"/>
<xsl:value-of select="name"/>
</tspan>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Das Ergebnis der Transformation ist der fertige SVG-Raumbelegungsplan,
wie in Abbildung 3 zu sehen. Wir müssen nun lediglich dafür sorgen, dass die Transformation
täglich in den frühen Morgenstunden automatisiert durchgeführt wird, damit ein
täglich aktualisierter Plan vorliegt.


Abb. 3: Das Ergebnis

Steuerung der Transformation
Für die Transformation
haben wir eine kleine kommandozeilenbasierte .NET-Applikation geschrieben, die
den im .NET Framework enthaltenen XSLT-Prozessor nutzt. Die Applikation ruft über
HTTP das XML-Ergebnis der Datenbank ab und wendet darauf das gerade beschriebene
Stylesheet an, um das Ergebnis der Transformation im Filesystem abzulegen.


Die .NET-Applikation wird über den Windows-Taskplaner (zu finden in der Systemsteuerung)
täglich zu einer vorgegebenen Zeit ausgeführt, was für unser Szenario ausreicht,
da sich die Raumbelegung über den Tag hinweg nicht mehr ändert.


Zum einfacheren Nachvollziehen finden sie in den Beispieldateien auf der CD eine
.NET Windows-Applikation, mit der sie die Transformation der Beispieldaten durchführen
können, die Applikation setzt ein installiertes .NET-Framework auf ihrem Rechner
voraus.

Fazit
Dank Technologien wie SVG und der XML-Fähigkeiten moderner
Datenbanksysteme kann man mit minimalem Programmieraufwand und unter Zuhilfenahme
von XML-Technologien durchgehend - vom Datenspeicher bis zur Visualisierung -
XML-basiert entwickeln. Ohne Technologiebruch lassen sich Projekte dieser Art
in kürzester Zeit realisieren, so wurde dieses Projekt z.B. inklusive Konzeptionsphase
in lediglich zwei Mann-Tagen umgesetzt.

Links und Literatur


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.

zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen




Software & Support Verlag GmbH