----
[[tustep:loesungen:tustep_und_xml|Zurück zur Übersichtsseite - TUSTEP und XML]]
----
====== Integration von XQuery in TUSTEP-Workflow ======
- {{files_open:benutzericons:chmoser-lg.jpg?nolink16x16|chmoser}} chmoser\\ \\
===== Ausgangslage =====
Beim Arbeiten mit Tustep an XML-Daten kann für spezifische Aufgaben schon einmal der Wunsch aufkommen, das Problem mit XQuery statt mit Tustep/Tuscript anzugehen. Gründe dafür könnten sein, dass sich die Aufgabe mit Tustep/Tuscript zwar lösen ließe, aber nur mit einem ungleich höheren Programmieraufwand im Vergleich zu XQuery. Weiter können - zum Beispiel im Umgang mit sehr großen Datenmengen - Performanzgründe für XQuery sprechen, das mit seinem funktionalen Zugang dem prozeduralen Zugang von Tuscript für gewisse Aufgabenstellungen (z.T. deutlich) überlegen ist.\\ Glücklicherweise offeriert Tustep die Möglichkeit, solche externen Prozesse aufzurufen, so dass XQuery-Operationen bequem in eine Tustep/Tuscript-Prozedur integriert und automatisiert aufgerufen werden können.\\ \\
===== Lösung =====
Der Aufruf von solchen externen Prozessen geschieht mit folgender Anweisung:\\
$$ EXECUTE "pfad" "parameter"
Die entsprechende Beschreibung im Tustep-Handbuch:\\
* "Unter Windows können mit der EXECUTE-Anweisung auch Programme, die in EXE- oder BAT-Dateien gespeichert sind, aufgerufen und in einem eigenen Fenster ausgeführt werden."
\\ Zu beachten ist also, dass die folgend beschriebenen Lösungen nur unter Windows Gültigkeit haben. (Außerdem wird eine Java-Installation vorausgesetzt).\\ \\ Was genau rufen wir aber von Tustep aus auf? Wir rufen die Windows-Kommandozeile (cmd.exe) auf, die wiederum einen XQuery-Prozessor aufruft und diesem gewisse Parameter übergibt.\\ Als XQuery-Prozessor bietet sich [[http://sourceforge.net/projects/saxon/|Saxon]] an, der in einer freien Version (Saxon-HE home edition) zur Verfügung steht ([[http://saxon.sourceforge.net/#F9.4HE|Download hier]]). In der XML-Entwicklungsumgebung [[http://www.oxygenxml.com/|Oxygen]] ist die Saxon Enterprise Edition bereits enthalten (Datei: Oxygen-Programmordner\lib\saxon9ee.jar). Wenn man diese über die Kommandozeile außerhalb von Oxygen aufruft, stehen zwar die lizenzpflichtigen Programmteile nicht zur Verfügung, die Basis-Komponenten reichen aber für die meisten Zwecke problemlos aus.\\ \\ Beim Aufruf von Saxon können dem Programm unzählige Parameter übergeben werden. Eine Übersicht finden sich [[http://www.saxonica.com/documentation/using-xquery/commandline.html|hier]]. Im Folgenden beschränken wir uns aber auf die notwendigen Parameter. Die Syntax mit den minimalen Angaben lautet:\\
java -cp Pfad\zu\Saxon net.sf.saxon.Query -s:Pfad\zu\Eingabedatei -qs:XQuery-Statement -o:Pfad\zu\Ausgabedatei
Wir brauchen also 1) den Pfad zu Saxon, 2) den Pfad zur Eingabedatei, 3) die eigentliche XQuery-Abfrage und 4) den Pfad zur Ausgabedatei.\\ \\ Beispiel:\\
java -cp "C:\Program Files\Oxygen XML Editor 15\lib\saxon9ee.jar" net.sf.saxon.Query -s:"C:\Users\CM\Documents\Tustep\beispiel\eingabe.xml" -qs:"//name" -o:"C:\Users\CM\Documents\Tustep\beispiel\ausgabe.xml"
Erläuterung:\\
* Saxon befindet sich in diesem Beispiel in der Datei: C:\Program Files\Oxygen XML Editor 15\lib\saxon9ee.jar. Der Pfad steht in Anführungszeichen, weil der Pfad Leerzeichen enthält.
* Die Eingabedatei heisst eingabe.xml und befindet sich im Ordner C:\Users\CM\Documents\Tustep\beispiel.
* Das XQuery-Statement ist simpel: "//name" bedeutet, dass schlicht alle Elemente ausgewählt werden sollen.
* Das Ergebnis der XQuery-Abfrage wird in der Datei C:\Users\CM\Documents\Tustep\beispiel\ausgabe.xml gespeichert. Falls die Datei nicht existiert, wird sie kreiert; falls sie existiert, wird sie überschrieben (auch wenn das Resultat der XQuery-Abfrage "leer" ist).
\\ Nun soll das Ganze nicht direkt über die Windows-Kommandozeile aufgerufen werden, sondern aus Tustep heraus, was dann folgendermaßen aussieht (der besseren Übersicht wegen werden die Pfadangaben einer Variablen zugewiesen, sie könnten aber auch direkt angegeben werden):\\ \\
#makro
$$ MODE TUSCRIPT
...
SET pfadsaxon = "C:\Program Files\Oxygen XML Editor 15\lib\saxon9ee.jar"
SET pfadinput = "C:\Users\CM\Documents\Tustep\beispiel\eingabe.xml"
SET pfadoutput = "C:\Users\CM\Documents\Tustep\beispiel\ausgabe.xml"
EXECUTE "C:\Windows\System32\cmd.exe" *
DATA /C java -cp "{pfadsaxon}" net.sf.saxon.Query -s:{pfadinput}
DATA -qs://name
DATA -o:{pfadoutput}
...
*eof
\\ **Variante 1: XQuery-Statement in eine Datei auslagern**\\ Statt über den Parameter "-qs" das XQuery-Statement direkt zu übergeben, kann mit dem Parameter "-q" eine Datei angegeben werden, die die entsprechende XQuery-Abfrage enthält:\\
#makro
$$ MODE TUSCRIPT
...
...
EXECUTE "C:\Windows\System32\cmd.exe" *
DATA /C java -cp "{pfadsaxon}" net.sf.saxon.Query -s:{pfadinput}
DATA -q:C:\Users\CM\Documents\Tustep\beispiel\abfrage.xquery
DATA -o:{pfadoutput}
...
*eof
\\
**Variante 2: Ausgabe in Zwischenablage umleiten**\\ Statt das Ergebnis in eine Datei auszugeben, kann es in die Zwischenablage kopiert werden. Dazu muss am Ende des Aufrufs statt der Ausgabedatei der Befehl ''| clip'' angegeben werden (dies ist eine Funktion der Windows-Kommandozeile, nicht des Saxon-Prozessors), also:\\
java -cp Pfad\zu\Saxon net.sf.saxon.Query -s:Pfad\zu\Eingabedatei -qs:XQuery-Statement | clip
Der Inhalt der Zwischenablage kann dann in Tustep mit\\
$$ FETCH/CLIPBOARD variablenname
in die Variable "variablenname" übernommen und weiterverarbeitet werden.\\ Dies zumindest in der Theorie: bei meinen Versuchen wurde die Ausgabe zwar korrekt in die Zwischenablage geleitet, allerdings konnte der Zwischenablageinhalt sodann nicht in Tustep übernommen werden.\\ \\ \\
===== Beispiel 1 =====
Nun soll das Ganze konkret an einem "realen" Beispiel durchgespielt werden.\\ Die Eingabedaten bestehen aus Informationen zu verschiedenen Konzerten:\\
1947-12-16
10. Volkskonzert
Sturzenegger, Max
Berlin
Musorgskij, Modest P.
"Ohne Sonne", sechs Gesänge mit Orchester
Ott, Mabella
Alt
Musorgskij, Modest P.
Persischer Tanz aus der Oper "Chowantschina"
Musorgskij, Modest P.
"Lieder und Tänze des Todes" für Alt und Orchester
Ott, Mabella
Alt
Cajkovskij, Pëtr I.
Sinfonie Nr. 4, in f moll, op. 36
1947-12-18
11. Volkskonzert
Sturzenegger, Max
Zürich
Musorgskij, Modest P.
"Ohne Sonne", sechs Gesänge mit Orchester
Ott, Mabella
Alt
Musorgskij, Modest P.
Persischer Tanz aus der Oper "Chowantschina"
Musorgskij, Modest P.
"Lieder und Tänze des Todes" für Alt und Orchester
Ott, Mabella
Alt
Cajkovskij, Pëtr I.
Sinfonie Nr. 4, in f moll, op. 36
1947-12-19
4. Jugend-Konzert
Hartogs, Eduard
Heidelberg
Mozart, Wolfgang Amadeus
Ouvertüre zu "Der Schauspieldirektor" (K.V. 486)
Mendelssohn Bartholdy, Felix
Violinkonzert in e-moll, op. 64
Jaques, Olivier
Violine
Schubert, Franz
Sinfonie Nr. 5, in B-dur
1947-12-26
Nachweihnachts-Konzert
Schmid, Erich
Zürich
Labole, P. N.
"Le Flambojant", Marsch
Sibelius, Jean
"Finlandia", Tondichtung
Scarlatti, Domenico
Aus dem Konzert für Oboe und Klavier
Blumer, Ernst
Oboe
Borodin, Aleksandr P.
"Im Kloster"
Dvorák, Antonín
"Legende Nr. 4"
Bergson, Michael
"Im Norden, im Süden", Scene und Arie für Klarinette und Klavier
Blumer, Fritz
Klarinette
Saint-Saëns, Camille
Marche Héroique
Eilenberg, Richard
Maienfest-Walzer
Silva, Cayetano Alberto
"San Lorenzo", Marsch
1948-01-06
12. Volkskonzert
Stoutz, Edmond de
Zürich
Torelli, Giuseppe
Concerto a due cori, in D-dur, Nr. 32
Purcell, Henry
Pavane und Chaconne, in g-moll, für Streichorchester
Stravinsky, Igor
Violinkonzert in D
Baumgartner, Paul
Violine
Mozart, Wolfgang Amadeus
Adagio in E-dur und Rondo in C-dur für Violine und Orchester
Baumgartner, Paul
Violine
Haydn, Joseph
Sinfonie in G-dur, Nr. 88
1948-01-13
VI. Abonnementskonzert
Andreae, Volkmar
Basel
Cherubini, Luigi
Anakreon-Ouvertüre
Brun, Fritz
Klavierkonzert in A-dur (1946)
Hirt, Franz Josef
Klavier
Brahms, Johannes
Sinfonie Nr. 3, in F-dur, op. 90
Die Datei heißt "konzerte.xml" und befindet sich in C:\Users\CM\Documents\Tustep\beispiel\konzerte.xml.\\ Das Ergebnis soll nach C:\Users\CM\Documents\Tustep\beispiel\konzerteneu.xml ausgegeben werden.\\ Für die Aufgabe, die es zu lösen gilt, verbleiben wir einstweilen beim Trivialen: es sollen (aus welchem Grund auch immer...) die Orte derjenigen Konzerte ausgegeben werden, in denen sowohl ein Werk von Mozart als auch von Schubert aufgeführt wurde.\\ \\ Das XQuery-Statement, das das Gewünschte leistet, lautet:\\
for $n in //konzert
where $n//komponist = 'Mozart, Wolfgang Amadeus' and $n//komponist = 'Schubert, Franz'
return $n/ort
Aufgerufen aus Tustep heraus:\\
#makro
$$ MODE TUSCRIPT
SET pfadsaxon = "C:\Program Files\Oxygen XML Editor 15\lib\saxon9ee.jar"
SET pfadinput = "C:\Users\CM\Documents\Tustep\beispiel\konzerte.xml"
SET pfadoutput = "C:\Users\CM\Documents\Tustep\beispiel\konzerteneu.xml"
EXECUTE "C:\Windows\System32\cmd.exe" *
DATA /C java -cp "{pfadsaxon}" net.sf.saxon.Query -s:{pfadinput}
DATA -qs:"for $n in //konzert where $n//komponist = 'Mozart, Wolfgang Amadeus' and $n//komponist = 'Schubert, Franz' return $n/ort"
DATA -o:{pfadoutput}
*eof
Das Resultat in C:\Users\CM\Documents\Tustep\beispiel\konzerteneu.xml:\\
Heidelberg
\\ \\
===== Beispiel 2 =====
Nun ein etwas fortgeschritteneres Beispiel. Zusätzlich zur Datei konzerte.xml (siehe oben) steht nun eine Datei kritiken.xml zur Verfügung, die Daten zu Konzertkritiken enthält. Diese Daten bestehen aus den Namen der Verfasser von Konzertkritiken und deren Kritiken, die durch das ref-Attribut auf die Konzert-ids in der Datei konzerte.xml verweisen.\\
Müller, Max
Nicht schlecht.
Hab schon Besseres gehört.
Nicht überzeugend.
Meier, Fritz
War super.
Grottenschlecht.
Fischer, Moritz
Genial.
Enttäuschend.
Bäcker, Barbara
Schön.
Wunderbar.
Die Aufgabe: Aus den beiden Dateien soll eine Liste erstellt werden mit dem Konzerttitel, dem Jahr, dem Ort sowie allen im jeweiligen Konzert aufgeführten individuellen Komponisten. Weiter sollen etwaige Konzertkritiken mit dem Namen des Kritikers und dem Text der Kritik dem jeweiligen Konzert beigeordnet werden. Die Konzertkritiken sollen alphabetisch nach dem Namen des Kritikers geordnet sein. Einige Elemente sollen im Laufe der Transformation umbenannt werden.\\ \\ Die XQuery dazu lautet:\\
for $ko in //konzert
return {$ko/titel}{substring($ko/datum, 1,4)}{$ko/ort}
{string-join(distinct-values($ko//komponist),'/')}{
for $kr in doc('file:/C:/Users/CM/Documents/Tustep/beispiel/kritiken.xml')//kritik
where $ko/@id = $kr/@ref
order by $kr/../name
return
{$kr/../name}{data($kr)}}
In Tustep sodann:\\
#makro
$$ MODE TUSCRIPT
SET pfadsaxon = "C:\Program Files\Oxygen XML Editor 15\lib\saxon9ee.jar"
SET pfadinput = "C:\Users\CM\Documents\Tustep\beispiel\konzerte.xml"
SET pfadoutput = "C:\Users\CM\Documents\Tustep\beispiel\konzerteneu.xml"
EXECUTE "C:\Windows\System32\cmd.exe" *
DATA /C java -cp "{pfadsaxon}" net.sf.saxon.Query -s:{pfadinput}
DATA -qs:"for $ko in //konzert return {$ko/titel}{substring($ko/datum, 1,4)}{$ko/ort} {string-join(distinct-values($ko//komponist),'/')} {for $kr in doc('file:/C:/Users/CM/Documents/Tustep/beispiel/kritiken.xml')//kritik where $ko/@id = $kr/@ref order by $kr/../name return {$kr/../name}{data($kr)}}"
DATA -o:{pfadoutput}
*eof
Das Resultat:\\
10. Volkskonzert
1947
Berlin
Musorgskij, Modest P./Cajkovskij, Pëtr I.
Meier, Fritz
War super.
Müller, Max
Nicht überzeugend.
11. Volkskonzert
1947
Zürich
Musorgskij, Modest P./Cajkovskij, Pëtr I.
Müller, Max
Hab schon Besseres gehört.
4. Jugend-Konzert
1947
Heidelberg
Mozart, Wolfgang Amadeus/Mendelssohn Bartholdy, Felix/Schubert, Franz
Bäcker, Barbara
Schön.
Nachweihnachts-Konzert
1947
Zürich
Labole, P. N./Sibelius, Jean/Scarlatti, Domenico/Borodin, Aleksandr P./Dvorák, Antonín/Bergson, Michael/Saint-Saëns, Camille/Eilenberg, Richard/Silva, Cayetano Alberto
Bäcker, Barbara
Wunderbar.
Fischer, Moritz
Enttäuschend.
12. Volkskonzert
1948
Zürich
Torelli, Giuseppe/Purcell, Henry/Stravinsky, Igor/Mozart, Wolfgang Amadeus/Haydn, Joseph
Müller, Max
Nicht schlecht.
VI. Abonnementskonzert
1948
Basel
Cherubini, Luigi/Brun, Fritz/Brahms, Johannes
Fischer, Moritz
Genial.
Meier, Fritz
Grottenschlecht.
\\
----
[[tustep:loesungen:tustep_und_xml|Zurück zur Übersichtsseite - TUSTEP und XML]]