Die grundlegende Designentscheidung bei populo besteht darin, den diversen Zuständen der Suchmaschine nicht unterschiedliche Programme entsprechen zu lassen, in deren Programmcode Elemente der Avanti-Jobs und der HTML-Ausgabeseiten eingebettet sind, sondern Vorlagedateien für die Avanti-Aufträge und Ausgabeseiten, die von einem Programm interpretiert werden. Damit diese Interpretation stattfinden kann, ist aber eine zusätzliche Steuersprache erforderlich.
Dieser Ansatz vermindert einerseits die Flexibilität (aus der Sicht des Programmierers, der mit einer universellen Programmiersprache vorher alles hätte machen können) und erhöht sie andererseits (aus der Sicht des HTML-Codierers oder des Codierers von Aufträgen für Avanti, der schnell neue Zustände in die Suchmaschine integrieren kann oder vorhandene abwandelt). Dieses Sowohl-als auch gilt ebenso für die Komplexität: Die Zustände sind durch die Auslagerung in verschiedene Dateien einfacher identifizierbar und von ihrer Notation her reiner (.htm-Dateien enthalten nur HTML, .job-Dateien enthalten Avanti-Befehle, .pl-Dateien enthalten (fast) kein Auftragselemente oder Layoutbeschreibungen), der Preis ist aber die zusätzliche Steuersprache, die beherrscht sein will.
Aufgrund der Anforderungen läßt sich schnell ableiten, welches die Grundfunktionalität der Steuersprache sein muß:
if-Befehl von Avanti reicht zur Steuerung
nicht aus: Schon beim Formulieren von Abfragen sollten
Varianten (qrix vorwärts oder rückwärts)
darstellbar sein. Für die Ausgabe gelten dieselben
Anforderungen: Es ist nicht angemessen, eine komplette
.htm-Seite zu duplizieren, nur damit dort
ein Treffer statt 1 Treffer dargestellt
wird.
Die Kennzeichnung von Elementen der populo-Sprache erfolgt immer durch
spezielle Zeichenfolgen, die mit
Der einfachste Fall sind im normalen HTML-Text auftretende Variablen. Dabei ist nur der Variablenname anzugeben, was einfach durch die Zeichenfolge
PO!Variablenname!geschieht.
Gelegentlich können dabei allerdings noch kleinere Modifikationen notwendig sein, z. B. eine Umwandlung einzelner Zeichen in HTML-Code. Für solche Zwecke stellt populo verschiedene Funktionen bereit. Die notwendige Kennzeichnung erfolgt fast genauso:
PO!Funktionenname( [Argument(e)] )!
Beispiel: Nehmen wir an, wir hätten verschiedene Variablen, die wie folgt belegt sind:
Name = 'Paul' Strasse = 'Pockelsstraße 5'und außerdem in der .htm-Datei die Stelle
Person PO!Name! wohnt PO!Htm(Strasse)!.populo macht dann daraus (
Htm ist eine von populo bereitgestellte
Umwandlungsfunktion):
Person Paul wohnt Pockelsstraße 5
Wenn man sich das obige Beispiel genauer ansieht, stellt sich natürlich die Frage, wie man Variable überhaupt mit Werten belegt. Allgemeiner gefragt: Wie bringt man populo dazu, zwischendurch gewisse Aufgaben auszuführen, ohne daß dies im Ergebnis zu sehen ist? Die Antwort darauf sind die populo-Routinen.
Die Syntax dafür ist
PO&Routinenname( [Argument(e)] )&Routinen können ohne Argumente auftreten, aber auch hier sind runde Klammern notwendig. Jede dieser Aufrufe muß in einer eigenen Zeile stehen, da der Rest einer solchen Zeile ignoriert wird (dies kann als Möglichkeit für Kommentare ausgenutzt werden).
Beispiel: Um die im letzten Beispiel benutzte Variablenbelegung zu erhalten, kann u. a. der folgende Teil in der Template-Datei stehen:
PO&Set(Vorname, 'Paul')& PO&Set(Name, 'Müller')& PO&Set(Strasse, 'Pockelsstraße 5')& PO&Set(Ort, 'Braunschweig')&
Unglücklicherweise gibt es einen ganzen Zoo von Zuweisungsoperationen, die hier nur kurz aufgelistet werden sollen:
Es wurde schon erwähnt, daß noch eine konditionale Abarbeitung und eine Schleifenkonstruktion nötig ist. Diese fallen unter den Oberbegriff Kontrollstrukturen und beziehen sich in der Regel auf mehrere Zeilen, die in einer populo verständlichen Weise eingeschlossen werden müssen. Die Syntax sieht im Großen und Ganzen so aus:
PO?Kontrollstruktur [ ( [ Argument(e) ] ) ]? Anweisungszeilen [PO? ?] Anweisungszeilen PO?ENDKontrollstruktur [ ]?
In den Anweisungszeilen dürfen weitere Konstrollstrukturen eingeschachtelt sein.
Auch hier ein Beispiel zu Erläuterung:
Es wurde nach Datensätzen mit einer bestimmten Bedingung gesucht, und
das erhaltene Ergebnis soll jetzt angezeigt werden. Die Anzahl der
gefundenen Datensätze sei dabei in der Variablen Anzahl
festgehalten worden. Denkbar ist dafür die folgende Einleitung:
PO?IF( Anzahl > 1 )? Es wurden PO!Anzahl! Datensätze gefunden. PO?ELSIF( Anzahl == 1 )? Es wurde ein Datensatz gefunden. PO?ELSE? Es wurde kein Datensatz gefunden. PO?ENDIF?
Unter den bisherigen Sprachelementen fehlt noch die Konstruktion, mit der auf Ergebnisse zurückgegriffen werden, die erst während der Abarbeitung des Auftrags durch Avanti festgelegt werden. Dazu wird die Möglichkeit ausgenutzt, daß mit Avanti eine beliebige Ausgabe mittels
write " " newlineerzeugt werden kann. Nun muß populo diese Zeile nur noch als für sich bestimmt erkennen können. Dies geschieht auf die übliche Weise, diesmal mit den Begrenzungszeichen
PO: :Anstelle von
steht nun üblicherweise der Aufruf einer
Initialisierungsroutine. Die Konstruktion mit Beispiel: Folgende Zeile könnte in einer .job-Datei vorkommen:
write "PO:Set(Txt, Int(" l ") Treffer zu 'PO!Begr!'):" n
Mit der Belegung Blume für Begr wird die entsprechende
Zeile in
write "PO:Set(Txt, Int(" l ") Treffer zu 'Blume'):" n
umgewandelt und als Bestandteil des Auftrags an Avanti übermittelt.
Im Ergebnis des Auftrags tauch diese Zeile dann als einzelne Zeile der
Form
PO:Set(Txt, Int( 0005 ) Treffer zu 'Blume'):auf und beim Zurücklesen durch populo wird dann die Zuweisung von
5 Treffer zu 'Blume' an die Variable Txt durchgeführt.
Im Zusammenhang mit der speziellen, reservierten Variablen LineTyp
ist diese Konstruktion unabdinglich:
Während des Zurücklesens des Resultats von Avanti wird jede Zeile entsprechend dem aktuellen Wert von LineTyp vorbehandelt. Liefert eine Anfrage mehrere Sorten Ausgabe, also etwa, weil unter der Kontrolle von Avanti entschieden wird, ob ein Registerausschnitt oder eine Kurztitelliste geliefert wird, so kann die Initialisierung von LineTyp nicht beim Absenden des Jobs erfolgen, sondern erst später:
Beispiel: Um populo mitzuteilen, daß Avanti als nächstes Registerzeilen liefert, muß in der .job-Datei an der entsprechenden Stelle die Zeile
find PER PO!Begriff! if ok jump liste // hier also Null Treffer, wir sparen uns einen leeren Schirm // und bieten Browsing an: write "PO:Set(LineTyp, 1):" newline //Registerzeilen folgen qrix PER PO!Begriff! jump daswars:liste write "PO:Set(LineTyp, 3):" newline //Kurztitelzeilen folgen list recnum
:daswars
Für typische Arten von Avanti-Resultaten sind Vorverarbeitungen schon vordefiniert:
| 0 |
unspezifiziert, Fehlermeldungen |
|
| 1 |
Registerauszüge |
qrix f 1 |
| (2) |
erkannte Verweise in (1) |
nur Ausgabe! |
| 3 |
Kurztitellisten |
list recnum |
| 4 |
Vollausgabe |
download |
| 5 |
Satznummern intern speichern |
list internal |
| 11 |
Registerauszüge, noch Kurztitel holen |
qrix f 1 |
| (12) |
erkannte Verweise in (12) |
nur Ausgabe! |
| 13 |
Satznummern für vollständige Kurzanzeige |
list internal |
| 14 |
Zwischenspeichern vollständiger Kurzanzeigen |
list internal |
| (21) |
geholte Kurztitelzeile zu 11 |
nur Ausgabe! |
| (22) |
geholte Kurztitelzeile zu 12 |
nur Ausgabe! |
Falls für eigene Zwecke (untergliederte Register etc.) stärkere
Differenzierungen erforderlich sind, sind weitere LineTypen
zu definieren, dazu muß aber typischerweise an mehreren Stellen
in die datenbankspezifische Konfigurationsdatei eingegriffen werden.
komplexes Beispiel (Job):
In Abhängigkeit von den Eingaben soll ein Registerauszug
erstellt werden:
//PO&IniVar(Startwert,s1)&Startwert aus HTTP-Feld s1 //PO&IniVar(Endwert,s2)&Endwert aus HTTP-Feld s2 //PO&IniVar(Register,ix)&Register aus HTTP-Feld ix qrix f 1 qrix m 99 // MaxShowRegister stammt aus der Konfigurationsdatei qrix n PO!MaxShowRegister! // Der Knopf 'rückwaerts blättern' habe im HTML-Formular für die // Eingabe den Namen t_ _prev bekommen //PO?IF( JobSubtyp eq "prev")? qrix - //PO?ENDIF? write "PO:Set(LineTyp,1):" newline // WICHTIG! //alternativ: Vorher Zeichenkette zusammenbasteln, //braucht aber ebenfalls ein 'if' //PO?IF( Endwert )? qrix PO!Register! PO!Startwert! @ PO!Endwert! //PO?ELSE qrix PO!Register! PO!Startwert! //PO?ENDIF?
komplexes Beispiel (zugehörige Ausgabe):
<HTML> <BODY> <!-- "Link" wird vorinitialisiert: --> <!-- PO&LinkIni(Link,db)&--> <!-- %RegInfo aus der Konfigurationsdatei haben wir mit einem FeldWeil LineTyp vorCaptionfür den Klartext zum symbolischen Registernamen versehen --> <!-- PO&Localize(RegInfo, Register, R_)&--> <P>Gesucht wurde PO!Htm(Startwert) <BR> im Register PO!R_Caption!</P><PRE> <!-- PO?LOOP? -->
qrix auf 1 gesetzt war, haben wir jetzt
Zugriff auf die Registerbestandteile als L_Count (Zählung),
L_Recno (Satznummern) und L_0 (Registerinhalt).
Wir formatieren die Zeilen als Links in die Datenbank vom
Anfragetyp showrec:
(PO!L_Count!) <A HREF="PO!Link!&t_showrec=xyz&recs=PO!L_Recno!"> PO!Htm(L_0)!</A> <!-- PO?ENDLOOP? --> </PRE> Tsch&üuml;s! </BODY>