----
[[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]]