Handbuch durchsuchen:

- Startseite
- Einleitung
- Hallo Welt!
- Grundlagen
  - Erstellen eines Layoutregelwerks
  - Aufbau der Datendatei und des Layoutregelwerks
  - Objekte ausgeben
  - Raster
  - Bereiche auf der Seite (PositioningArea)
  - Dateiorganisation
  - Silbentrennung / Spracheinstellungen
  - Einbinden von Schriftarten
  - Textformate
  - Textformatierung
  - Farben
- Programmierung
- Bilder einbinden
- Tabellen
- Fortgeschrittene Themen
  - Lesezeichen (Bookmarks)
  - Erzeugen von XML-Strukturen
  - Druckausgabe / Schnittmarken
  - CSS
  - Gruppen (virtuelle Objekte)
  - Virtuelle Seiten
  - Rotieren von Inhalten
  - Sortieren von Daten
  - Umfließen von Bildern
  - Seitentypen
  - Starten des Publishers über den Hotfolder
  - Lua-Filter / Datenvorverarbeitung
  - Schemavalidierung
  - Qualitätssicherung (PDF-Vergleich)
  - Fehlersuche / Debugging
  - Servermodus
  - Steuerung des Layouts beim Aufruf des Publishers
  - Bilder mit MetaPost erstellen und einbinden
- Kochbuch
  - Daumenregister
  - Mehrseitige PDF-Dateien einbinden
  - Layoutoptimierung mithilfe von Gruppen
  - Aufzählungslisten nachahmen
  - Verzeichnisse erstellen
  - Inhaltsverzeichnis in einem Durchlauf erstellen
  - Seitenzahlen: Seite x von y
- Installationsanleitung
- Dateinamen im Publisher
- Voreinstellungen im speedata Publisher
- Starten des Publishers über die Kommandozeile
- Konfiguration des Publishers
- Längenangaben und Maßeinheiten
- XPath- und Layoutfunktionen
- Interne Variablen
- XML Editor mit Schema verbinden
  - Visual Studio Code
  - OxygenXML
  - Atom
- Liste der Änderungen
- Glossar
- Kompatibilität mit anderer Software
- Befehlsreferenz
  - A
  - Action
  - AddSearchpath
  - AtPageCreation
  - AtPageShipout
  - AttachFile
  - Attribute
  - B
  - Barcode
  - Bold
  - BoldItalic
  - Bookmark
  - Box
  - Br
  - Case
  - Circle
  - ClearPage
  - Color
  - Column
  - Columns
  - Compatibility
  - Contents
  - Copy-of
  - DefineColor
  - DefineColorprofile
  - DefineFontalias
  - DefineFontfamily
  - DefineGraphic
  - DefineMatter
  - DefineTextformat
  - Element
  - Fallback
  - Fontface
  - ForAll
  - Frame
  - Grid
  - Group
  - Groupcontents
  - HSpace
  - Hyphenation
  - I
  - Image
  - Include
  - Initial
  - InsertPages
  - Italic
  - Layout
  - Li
  - LoadDataset
  - LoadFontfile
  - Loop
  - Makeindex
  - Margin
  - Mark
  - Message
  - NewPage
  - NextFrame
  - NextRow
  - NoBreak
  - Ol
  - Options
  - Otherwise
  - Output
  - Overlay
  - Pageformat
  - Pagetype
  - Paragraph
  - PDFOptions
  - PlaceObject
  - Position
  - PositioningArea
  - PositioningFrame
  - ProcessNode
  - Record
  - Regular
  - Rule
  - SaveDataset
  - SavePages
  - SetGrid
  - SetVariable
  - SortSequence
  - Stylesheet
  - Span
  - Sub
  - Sup
  - Switch
  - Table
  - TableNewPage
  - Tablefoot
  - Tablehead
  - Tablerule
  - Td
  - Text
  - Textblock
  - Tr
  - Trace
  - Transformation
  - U
  - Ul
  - Until
  - URL
  - Value
  - VSpace
  - While

Version 4.8.0
Handbuch durchsuchen

- Startseite
- Einleitung
- Hallo Welt!
- Grundlagen
  - Erstellen eines Layoutregelwerks
  - Aufbau der Datendatei und des Layoutregelwerks
  - Objekte ausgeben
  - Raster
  - Bereiche auf der Seite (PositioningArea)
  - Dateiorganisation
  - Silbentrennung / Spracheinstellungen
  - Einbinden von Schriftarten
  - Textformate
  - Textformatierung
  - Farben
- Programmierung
- Bilder einbinden
- Tabellen
- Fortgeschrittene Themen
  - Lesezeichen (Bookmarks)
  - Erzeugen von XML-Strukturen
  - Druckausgabe / Schnittmarken
  - CSS
  - Gruppen (virtuelle Objekte)
  - Virtuelle Seiten
  - Rotieren von Inhalten
  - Sortieren von Daten
  - Umfließen von Bildern
  - Seitentypen
  - Starten des Publishers über den Hotfolder
  - Lua-Filter / Datenvorverarbeitung
  - Schemavalidierung
  - Qualitätssicherung (PDF-Vergleich)
  - Fehlersuche / Debugging
  - Servermodus
  - Steuerung des Layouts beim Aufruf des Publishers
  - Bilder mit MetaPost erstellen und einbinden
- Kochbuch
  - Daumenregister
  - Mehrseitige PDF-Dateien einbinden
  - Layoutoptimierung mithilfe von Gruppen
  - Aufzählungslisten nachahmen
  - Verzeichnisse erstellen
  - Inhaltsverzeichnis in einem Durchlauf erstellen
  - Seitenzahlen: Seite x von y
- Installationsanleitung
- Dateinamen im Publisher
- Voreinstellungen im speedata Publisher
- Starten des Publishers über die Kommandozeile
- Konfiguration des Publishers
- Längenangaben und Maßeinheiten
- XPath- und Layoutfunktionen
- Interne Variablen
- XML Editor mit Schema verbinden
  - Visual Studio Code
  - OxygenXML
  - Atom
- Liste der Änderungen
- Glossar
- Kompatibilität mit anderer Software
- Befehlsreferenz
  - A
  - Action
  - AddSearchpath
  - AtPageCreation
  - AtPageShipout
  - AttachFile
  - Attribute
  - B
  - Barcode
  - Bold
  - BoldItalic
  - Bookmark
  - Box
  - Br
  - Case
  - Circle
  - ClearPage
  - Color
  - Column
  - Columns
  - Compatibility
  - Contents
  - Copy-of
  - DefineColor
  - DefineColorprofile
  - DefineFontalias
  - DefineFontfamily
  - DefineGraphic
  - DefineMatter
  - DefineTextformat
  - Element
  - Fallback
  - Fontface
  - ForAll
  - Frame
  - Grid
  - Group
  - Groupcontents
  - HSpace
  - Hyphenation
  - I
  - Image
  - Include
  - Initial
  - InsertPages
  - Italic
  - Layout
  - Li
  - LoadDataset
  - LoadFontfile
  - Loop
  - Makeindex
  - Margin
  - Mark
  - Message
  - NewPage
  - NextFrame
  - NextRow
  - NoBreak
  - Ol
  - Options
  - Otherwise
  - Output
  - Overlay
  - Pageformat
  - Pagetype
  - Paragraph
  - PDFOptions
  - PlaceObject
  - Position
  - PositioningArea
  - PositioningFrame
  - ProcessNode
  - Record
  - Regular
  - Rule
  - SaveDataset
  - SavePages
  - SetGrid
  - SetVariable
  - SortSequence
  - Stylesheet
  - Span
  - Sub
  - Sup
  - Switch
  - Table
  - TableNewPage
  - Tablefoot
  - Tablehead
  - Tablerule
  - Td
  - Text
  - Textblock
  - Tr
  - Trace
  - Transformation
  - U
  - Ul
  - Until
  - URL
  - Value
  - VSpace
  - While

- This manual in English

# Lua-Filter / Datenvorverarbeitung

Manchmal möchte man vor der eigentlichen PDF-Erstellung die Daten in ein anderes Format überführen oder auf Korrektheit überprüfen. Dafür gibt es die Möglichkeit (seit Version 3.1.9), ein Lua-Skript vor dem eigentlichen Publishing-Lauf auszuführen. Lua ist eine einfache, aber mächtige Programmiersprache, die dafür vorgesehen ist, in andere Programme als Skriptsprache einzubauen.

Im Beispiele-Repository sind drei Anwendungsfälle zu finden.

## Aufruf des Lua-Skripts

Gestartet wird der Filter entweder über die Kommandozeile

    sp --filter myfile.lua

oder über die Konfigurationsdatei, die folgenden Eintrag enthalten muss:

    filter=myfile.lua

Das angegebene Lua-Skript wird ausgeführt, bevor die Erzeugung der PDF-Datei beginnt. Das Skript muss im Publisher-Suchpfad liegen. Daher ist die Hauptanwendung dieses Pre-Processing die Transformation von Daten in ein Format, das für den speedata Publisher geeignet ist. So können CSV oder Excel-Dateien nach XML konvertiert und anschließend die PDF-Erzeugung gestartet werden. Daneben ist es auch möglich, Daten zu validieren.

Im Folgenden werden die Anwendungsmöglichkeiten beschrieben, ganz zum Schluss gibt es nochmals eine Übersicht über die eingebauten Funktionen und Methoden.

## Validieren von Eingabedaten

Um RELAX NG-Dateien zu validieren gibt es mehrere Möglichkeiten. Neben einen Variante, direkt im XML Editor das Schema zu validieren (siehe den entsprechenden Abschnitt im Handbuch) gibt es die Möglichkeit, ein externes Programm dafür zu nutzen. Eines davon ist Jing. Es wird mit dem Publisher mitgeliefert.

In der Lua-Vorverarbeitung gibt es eine Funktion, die die Validierung übernimmt:

    runtime = require("runtime")
    runtime.validate_relaxng(‹xmlfile›,‹schemafile›)

Die Funktion liefert im Fehlerfall `false` und die Fehlermeldung zurück. Beispiel:

    -- adjust the paths, of course
    runtime = require("runtime")
    ok, msg = runtime.validate_relaxng("layout.xml","../schema/layoutschema-en.rng")
    if not ok then
        print(msg)
        os.exit(-1)
    end

Das speichert man in einer Datei, z.B. `validate.lua` und ruft dann den Publisher mit

    sp --filter validate.lua

auf. Vor jedem Lauf wird nun überprüft, ob die Layoutdatei dem Schema entspricht und nur dann wird mit der Verarbeitung fortgefahren.

| Man kann nicht nur die Layoutdatei auf Korrektheit überprüfen, sondern auch alle anderen XML-Dateien. Hierzu muss man sich jedoch ein eigenes RELAX NG-Schema erstellen. Eine Anleitung dazu ist unter https://speedata.github.io/relaxngtutorial-de/ verfügbar. Je nach Datendatei ist das auch recht einfach. Insbesondere wenn man immer wieder Daten aus fremden Quellen geliefert bekommt, kann man sich so sicher sein, dass die gewünschte Struktur eingehalten wird.

## Ausführen einer Transformation

Eine XSLT-Transformation verarbeitet eine XML-Datei mit einem XSLT-Skript und erzeugt eine Ausgabedatei. XSLT ist eine Programmiersprache, die für die Verarbeitung von XML-Daten entworfen wurde. Häufig sind Daten aus PIM-Systemen oder Datenbanken nicht in der Form, die für den Publisher optimal sind. Mit XSLT kann man solche Ausgangsdaten verarbeiten und verändern.

Das Programm `saxon` (mit dem speedata Publisher mitgeliefert) kann ein XSLT-Skript ausführen. Der Aufruf ist folgender:

    runtime = require("runtime")
    runtime.run_saxon(‹XSL›,‹source›,‹outfile›,‹parameter›)

Es kann nur ein Parameter angegeben werden (`key=value`). Für mehrere Parameter muss die alternative Version über benannte Parameter benutzt werden.

    runtime = require("runtime")
    ok, msg = runtime.run_saxon("transformation.xsl","sourcefile.xml","data.xml")

    -- quit the publishing process if the transformation fails
    if not ok then
        print(msg)
        os.exit(-1)
    end

Alternativ kann der Aufruf von Saxon auch wie folgt geschehen:

    runtime = require("runtime")
    ok, msg = runtime.run_saxon({ key = value, key = value, ... })

Erlaubte key/value-Paare sind:

Schlüssel | Wert
--- | ---
`source` | Quelldatei (XML)
`stylesheet` | Stylesheetdatei (XSL)
`out` | Resultat
`initialtemplate` | Name des Template, das aufgerufen werden soll
`params` | Tabelle mit Parametern für das Stylesheet

Beispiel:

    runtime = require("runtime")
    ok, msg = runtime.run_saxon({stylesheet = 'json2xml.xsl',
                                 out = 'data.xml',
                                 initialtemplate = 'main',
                                 params = { ["key"] = "value" }})

Siehe dazu auch das Beispiel im Beispiele-Repository.

## Erstellen von XML-Dateien

Man kann die zu verarbeitende Datendatei auch mit dem Lua-Skript erstellen. Dazu gibt es im Modul `xml` die Funktion `encode_table()`, die aus einer Lua-Tabelle eine XML-Datei erstellt.

Das Skript

    xml = require("xml")
    tbl = {
        ["_type"] = "element",
        ["_name"] = "data",
        {
           ["_type"] = "element",
           ["_name"] = "child",
           "Hello, world",
        }
    }

    ok, msg = xml.encode_table(tbl)
    if not ok then
        print(msg)
        os.exit(-1)
    end

erzeugt die XML-Datei

    <data><child>Hello, world</child></data>

die für den folgenden Publisher-Lauf zur Verfügung steht. Das ist besonders dann von Nutzen, wenn die Datenquelle nicht in XML vorliegt.

## Verarbeiten von Excel-Dateien

Ein häufig anzutreffender Anwendungsfall ist, dass die Daten für die Verarbeitung aus Excel-Dateien gelesen werden sollen. Dazu gibt es im Modul `xlsx` die Funktion `open()`, die eine vorhandene Datei öffnet:

    xlsx = require("xlsx")
    spreadsheet, err = xlsx.open("myfile.xlsx")
    if not spreadsheet then
        print(err)
        os.exit(-1)
    end

Das Objekt `spreadsheet` beinhaltet die einzelnen Arbeitsblätter (Worksheets). Die Anzahl der Arbeitsblätter lässt sich über den length-Operator feststellen und die einzelnen Arbeitsblätter per Index (1 ist das erste Arbeitsblatt).

    numWorksheets = #spreadsheet
    ws = spreadsheet[1]

Mit dem Objekt `ws` kann direkt auf die Zelleninhalte zugegriffen werden. Dazu wird es als Funktion aufgerufen und liefert eine Zeichenkette zurück. Die erste Zelle oben links hat die Koordinaten 1,1, die erste Zelle in der zweiten Zeile 1,2 und so weiter.

    cell1 = ws(1,1)
    cell2 = ws(1,2)

Den Namen des Arbeitsblattes kann man über den Wert `name` ermitteln:

    name = ws.name

## Lesen von CSV-Dateien

Ähnlich wie bei Excel-Dateien kann man auch CSV-Dateien direkt einlesen. Die Struktur ist jedoch einfacher, da es nur ein »Arbeitsblatt« gibt.

    csv = require("csv")
    csvtab, msg = csv.decode("myfile.csv",{columns = {1,2,3}})
    if not csvtab then
        print(msg)
        os.exit(-1)
    end

Der zweite Parameter bei `csv.deocde()` ist optional. In diesem Beispiel werden nur die Spalten 1, 2 und 3 ausgegeben. Das Ergebnis ist eine Tabelle aus Zeilen. Jede Zeile ist wiederum eine Tabelle, die die einzelnen Werte der Zeile enthält.

Im Beispiele-Repository wird gezeigt, wie man aus der CSV-Datei eine XML-Datei erstellen kann.

## Funktionsreferenz

### `runtime`

In diesem Modul werden alle Funktionen und Einstellungen gesammelt, die eher allgemeiner Natur sind.

`projectdir`

  Eine Zeichenkette, die das aktuelle Projektverzeichnis enthält (das Verzeichnis mit der `layout.xml` bzw. `publisher.cfg`-Datei)

`variables`

  Eine Tabelle mit alle Variablen, die per `-v` auf der Kommandozeile oder in der Konfigurationsdatei mit `vars=…​` angegeben wurden.

`finalizer`

  Ist dieser Variablen eine Funktion zugewiesen, so wird sie nach der PDF-Erzeugung aufgerufen (callback). Die Funktion hat keine Parameter und keinen Rückgabewert.

      runtime = require("runtime")

      function finished()
          print("PDF is finished now.")
      end

      runtime.finalizer = finished

`options`

  Tabelle mit Konfigurationswerten (siehe Konfiguration des Publishers). Kann sowohl zum Lesen der Werte als auch zum Setzen benutzt werden.

`validate_relaxng(‹xmldatei›,‹schemadatei›)`

  Diese Funktion validiert die angegebene XML-Datei mit dem im zweiten Parameter angegebenen RELAX NG (XML-Syntax) Schema. Die Rückgabe ist ein boolean-Wert, der true ist, wenn der Befehl fehlerfrei ausgeführt wurde. Ansonsten wird ein zweiter Rückgabewert (string) zurück gegeben, der die Fehlermeldung enthält.

`run_saxon(‹XSL›,‹Quelldatei›,‹Ausgabedatei›,‹Parameter›)`

  Diese Funktion ruft das zum Publisher mitgelieferte Programm `saxon` auf. Sie erwartet drei string-Argumente (das Stylesheet, die Eingabe- und die Ausgabedatei) und ein optionales Argument das als Parameter an saxon übergeben wird. Die Rückgabe ist ein boolean-Wert, der true ist, wenn der Befehl fehlerfrei ausgeführt wurde. Ansonsten wird ein zweiter Rückgabewert (string) zurück gegeben, der die Fehlermeldung enthält. Der Parameter hat die Form `keyword=value`.

`run_saxon(‹tabelle›)`

  Diese Funktion ruft das zum Publisher mitgelieferte Programm `saxon` auf. Sie erwartet eine Tabelle als Argument mit den Schlüsselwörtern, die unten aufgelistet sind. Die Rückgabe ist ein boolean-Wert, der true ist, wenn der Befehl fehlerfrei ausgeführt wurde. Ansonsten wird ein zweiter Rückgabewert (string) zurück gegeben, der die Fehlermeldung enthält.

  Schlüssel | Wert
  --- | ---
  `source` | Quelldatei (XML)
  `stylesheet` | Stylesheetdatei (XSL)
  `out` | Resultat
  `initialtemplate` | Name des Template, das aufgerufen werden soll
  `params` | Tabelle mit Parametern für das Stylesheet

`find_file(‹Dateiname oder URL›)`

  Findet die angegebene Datei im Publisher-Suchpfad und gibt den absoluten Pfad zurück. Bei nicht gefunden: nil bzw. false und eine Fehlermeldung.

### `xml`

Mit dem XML-Modul werden XML-Dateien erzeugt. Zuerst muss die XML-Struktur in einer Lua-Tabelle erzeugt werden, anschließend wird sie mit `encode_table()` unter dem Namen `data.xml` gespeichert.

`encode_table(‹tabelle›,[dateiname])`

  Erzeugt eine XML-Datei (`data.xml` bzw. der optional gegebene Dateiname) der übergebenen Tabelle. Rückgabewert 1 ist ein bool (success), Wert 2 ist die Fehlermeldung, wenn der erste Wert `false` ist. Die Tabelle hat folgende Struktur:

      element = {
          ["_type"] = "element",
          ["_name"] = "elementname",
          attribute1 = "value1",
          attribute2 = "value2",
          child1,
          child2,
          child3,
          ...
      }

  `child1`, `…​` sind entweder Zeichenketten, Elemente oder Kommentare. Kommentare haben folgende Form:

      comment = {
               _type = "comment",
               _value = " Das ist ein Kommentar! "
         }

### `CSV`

CSV-Dateien

`decode(‹dateiname›,‹parameter›)`

  Liest eine CSV-Datei ein. Der Rückgabewert ist eine Tabelle bzw. im Fehlerfall `false` und eine Fehlermeldung.

  Die `parameter` werden in einer Tabelle kodiert:

  `charset`

    Wenn die CSV-Datei Latin-1 kodiert ist, muss dieser Wert auf ISO-8859-1 stehen. Andere Kodierungen auf Anfrage.

  `separator`

    Entweder ein Komma (Voreinstellung), ein Semikolon oder das entsprechend genutzte Trennzeichen.

  `columns`

    Eine Tabelle, die die gewünschten Spalten in ihrer Reihenfolge enthält. Z.B. `{3,2,1}` für die ersten drei Spalten in umgekehrter Reihenfolge.

### `xlsx`

Liest eine Excel-Datei ein.

`open(‹dateiname›)`

  Öffnet die angegebene Datei. Der Rückgabewert ist ein `spreadsheet`-Objekt bzw. im Fehlerfall `false` und eine Fehlermeldung.

  Das `spreadsheet`-Objekt beinhaltet die einzelnen Arbeitsblätter. Die Anzahl der Arbeitsblätter kann mit dem `#`-Operator ermittelt werden. Auf die einzelnen Arbeitsblätter kann man mit dem Index-Operator `[]` zugreifen, wobei das erste Arbeitsblatt den Index 1 hat.

  Die einzelnen Arbeitsblätter können als Funktion mit zwei Parametern benutzt werden (siehe Beispiel oben). Die Parameter sind die x und y Koordinaten der auszulesenden Zelle, die erste Zelle oben links hat die Koordinate 1,1. Die Ausmaße des Inhalts kann über die Parameter `minrow`, `maxrow`, `mincol` und und `maxcol` ermittelt werden. Der Name ist im Parameter `name` enthalten.

`string_to_date(‹string›)`

  Wandelt eine Zahl (kodiert als Zeichenkette) in ein Datum um. Rückgabe ist eine Tabelle mit den Schlüsseln `day`, `month`, `year`, `hour`, `minute` und `second`. Beispiel: `xlsx.string_to_date("43458")` ergibt

      {
        ["day"] = "24"
        ["month"] = "12"
        ["year"] = "2018"
        ["hour"] = "0"
        ["minute"] = "0"
        ["second"] = "0"
      }

### `http`

Die HTTP-Bibiliothek ist unter https://github.com/cjoudrey/gluahttp beschrieben.

- Starten des Publishers über den Hotfolder
- Schemavalidierung