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
- 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.10.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
- 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

# Verzeichnisse erstellen

Dieses Kapitel widmet sich der Erstellung von Verzeichnissen. Es gibt prinzipiell zwei Varianten, ein Verzeichnis zu erzeugen. Daher handelt der nächste Abschnitt von dem eingebauten Mechanismus der Marker (`<Mark>`), die darauf folgenden Abschnitte von den Weg per `<Element>` und `<Attribute>` und dem manuellen Speichern der Daten für einen weiteren Durchlauf.

| Damit der Publisher mehrfach durchläuft, muss der Parameter `runs` auf der Kommandozeile bzw. in der Konfigurationsdatei gesetzt werden, beispielsweise mit `sp --runs=2` (Kommandozeile) bzw. `runs = 2` (Konfigurationsdatei). Im Abschnitt Inhaltsverzeichnis in einem Durchlauf erstellen wird ein Mechanismus gezeigt, wie in manchen Fällen ein Verzeichnis in nur einem Durchlauf erzeugt werden kann.

## Marker

Marker sind unsichtbare Zeichen, die in den Text eingefügt werden. Diesen Zeichen wird immer ein Name zugeordnet. Nach Ausgabe des Zeichens auf einer Seite kann man den Publisher nach der Seitenzahl fragen. Der Aufbau ist folgendermaßen:

    <PlaceObject>
      <Textblock>
        <Action>
          <Mark select="'textstart'"/>
        </Action>
        <Paragraph>
          <Value>
          Row
          Row
          Row
          Row
           </Value>
        </Paragraph>
      </Textblock>
    </PlaceObject>

Nach Ausgabe der Seite ist nun mit `sd:pagenumber('textstart')` die Seitennummer ermittelbar.

Die Marker werden automatisch in einer internen Hilfsdatei `publisher.aux` gespeichert, so dass bei einem weiteren Durchlauf auf die Seitenzahlen über `sd:pagenumber()` bereits vor dem Platzieren der Seite verfügbar sind. Als Beispiel wird eine einfache Textstruktur genommen (es ist dasselbe Beispiel wie im nächsten Abschnitt):

    <data>
      <chapter title="Foreword">
        <text>...</text>
      </chapter>
      <chapter title="Introduction">
        <text>...</text>
      </chapter>
      <chapter title="Conclusion">
        <text>...</text>
      </chapter>
    </data>

Die mit dem folgenden Layout ausgegeben wird:

    <Layout
      xmlns="urn:speedata.de:2009/publisher/en"
      xmlns:sd="urn:speedata:2009/publisher/functions/en">

      <DefineFontfamily name="title" fontsize="18" leading="20">
        <Regular fontface="sans"/>
      </DefineFontfamily>

      <Record element="data">
        <!-- This point will be completed further below -->
        <ProcessNode select="chapter"/>
      </Record>

      <Record element="chapter">
        <PlaceObject>
          <Textblock>
            <Action>
              <Mark select="@title"/>
            </Action>
            <Paragraph fontfamily="title">
              <Value select="@title"/>
            </Paragraph>
            <Paragraph>
              <Value select="text"/>
            </Paragraph>
          </Textblock>
        </PlaceObject>
        <ClearPage/>
      </Record>
    </Layout>

Das Grundgerüst für die Marker. Die Stelle für das Inhaltsverzeichnis wird später erweitert (siehe Kommentar).

Der Publisher ordnet nun die Kapitel der Seitenzahl zu. Man kann nun das Verzeichnis im nächsten Durchlauf ausgeben:

      <PlaceObject>
        <Table padding="5pt">
          <ForAll select="chapter">
            <Tr>
              <Td><Paragraph><Value select="@title"/></Paragraph></Td>
              <Td><Paragraph>
                   <Value select="sd:pagenumber(@title)"/> ①
              </Paragraph></Td>
            </Tr>
          </ForAll>
        </Table>
      </PlaceObject>
      <ClearPage/>

Dieser Teil wird in das Layout oben eingefügt, um das Inhaltsverzeichnis auszugeben.

① In einem weiteren Durchlauf stehen die Seitenzahlen zur Verfügung, bevor die eigentlichen Kapitel auf die Folgeseiten geschrieben werden.

## Verzeichnisse erstellen (XML-Struktur)

Im vorherigen Kapitel wurden Verzeichnisse über die Marker erstellt. In diesem Kapitel wird ein Mechanismus benutzt, der etwas mehr manuelle Arbeit bedeutet, aber flexibler ist.

Der speedata Publisher kann beliebige Verzeichnistypen erstellen. Ob Inhaltsverzeichnis, Artikelliste oder Stichwortindex – alle Listen funktionieren nach demselben Prinzip: die notwendigen Daten (z. B. Seitenzahlen, Artikelnummern) werden explizit in einer eigenen Datenstruktur gespeichert, auf Festplatte geschrieben. Beim nächsten Lauf des Publishers werden diese Daten eingelesen und stehen zur Verfügung.

### Schritt 1: Sammeln der Informationen

Die beiden Befehle `<Element>` und `<Attribute>` dienen zur Strukturierung von Daten, die während der Verarbeitung gelesen werden. Das ist schon im Kapitel Erzeugen von XML-Strukturen beschrieben worden. Mit diesen Befehlen lassen sich neue XML Datensatzdateien erzeugen. Folgende Struktur könnte für eine Artikelliste sinnvoll sein:

    <articlelist>
      <article number="1" page="10"/>
      <article number="2" page="12"/>
      <article number="3" page="14"/>
    </articlelist>

Um diese Struktur im Layoutregelwerk zu erstellen, muss sie aus den Befehlen `<Element>` und `<Attribute>` wie folgt zusammengesetzt werden:

    <Element name="articlelist">
      <Element name="article">
        <Attribute name="number" select="1"/>
        <Attribute name="page" select="10"/>
      </Element>
      <Element name="article">
        <Attribute name="number" select="2"/>
        <Attribute name="page" select="12"/>
      </Element>
      <Element name="article">
        <Attribute name="number" select="3"/>
        <Attribute name="page" select="14"/>
      </Element>
    </Element>

### Schritt 2: Speichern und Laden der Informationen

Mit dem Befehl `<SaveDataset>` wird diese Struktur auf die Festplatte gespeichert und mit `<LoadDataset>` wird sie wieder geladen. Existiert die Datei beim Laden nicht, so wird kein Fehler gemeldet, da es sich um den ersten Durchlauf handeln könnte, wo die Datei naturgemäß noch nicht existiert.

### Schritt 3: Verarbeiten der Informationen

Direkt nach dem Laden wird die XML-Verarbeitung mit dem ersten Element der gerade geladenen Struktur fortgesetzt, im Beispiel oben würde nach dem folgenden Befehl im Layoutregelwerk gesucht:

    <Record element="articlelist">
      ...
    </Record>

Das heißt, dass die eigentliche Datenverarbeitung zeitweilig unterbrochen und mit dem neuen Datensatz aus `<LoadDataset>` fortgeführt wird.

### Beispiel

Das ist dasselbe Beispiel wie aus dem vorherigen Abschnitt (Verzeichnisse erstellen). Als Beispiel wird eine einfache Datendatei genommen:

    <data>
      <chapter title="Foreword">
        <text>...</text>
      </chapter>
      <chapter title="Introduction">
        <text>...</text>
      </chapter>
      <chapter title="Conclusion">
        <text>...</text>
      </chapter>
    </data>

Die mit dem folgenden Layout ausgegeben wird:

    <Layout
      xmlns="urn:speedata.de:2009/publisher/en"
      xmlns:sd="urn:speedata:2009/publisher/functions/en">

      <DefineFontfamily name="title" fontsize="18" leading="20">
        <Regular fontface="sans"/>
      </DefineFontfamily>

      ①

      ②
      <Record element="data">
        <ProcessNode select="chapter"/>
      </Record>

      <Record element="chapter">
        ③
        <PlaceObject>
          <Textblock>
            <Paragraph fontfamily="title">
              <Value select="@title"/>
            </Paragraph>
            <Paragraph>
              <Value select="text"/>
            </Paragraph>
          </Textblock>
        </PlaceObject>
        <ClearPage/>
      </Record>
    </Layout>

Grundgerüst für die Ausgabe eines Inhaltsverzeichnisses über die XML-Struktur. Der Code wird im Laufe des Abschnitts ergänzt.

① Die Ausgabe des eigentlichen Inhaltsverzeichnisses wird hier eingefügt.

② Der Abschnitt `data` wird erweitert um das Laden und Speichern der XML-Daten für das Verzeichnis

③ Hier wird Code eingefügt, der die XML-Struktur zusammenbaut (siehe unten)

Nun wird eine Variable definiert (`entries`), die die Informationen über die Kapitelanfänge enthält. Die Zielstruktur soll folgende sein:

    <tableofcontent>
      <entry chaptername="Foreword" page="2"/>
      <entry chaptername="Introduction" page="3"/>
      <entry chaptername="Conclusion" page="4"/>
    </tableofcontent>

Im Abschnitt `chapter` (Punkt 3 im Layout oben) wird oben der Code eingefügt, um die Variable `entries` mit den Inhalten zu füllen:

      <Record element="chapter">
        <SetVariable variable="entries">
          <Copy-of select="$entries"/>
          <Element name="entry">
            <Attribute name="chaptername" select="@title"/>
            <Attribute name="page" select="sd:current-page()"/>
          </Element>
        </SetVariable>

        <PlaceObject>
        ...

Es wird also mittels `<Copy-of>` jeweils etwas neues zu einer Variablen hinzugefügt.

Die Struktur muss am Anfang geladen und am Ende des Durchlaufs gespeichert werden, damit sie immer aktuell ist. Wenn die Datei `toc` noch nicht vorhanden ist, wird der Befehl einfach übergangen. Der neue Abschnitt `data` sieht nun so aus und wird an die Stelle 2 im Layout oben eingefügt (anstelle des dort vorhandenen Records):

      <Record element="data">
        <LoadDataset name="toc"/>
        <SetVariable variable="entries"/>
        <ProcessNode select="chapter"/>
        <SaveDataset name="toc" elementname="tableofcontents"
                     select="$entries"/>
      </Record>

Beim nächsten Durchlauf greift der Befehl `<LoadDataset>` und öffnet die zuvor gespeicherte XML-Datei. Im Layoutregelwerk wird ein Abschnitt für das Element `tableofcontents` gesucht, das ja das Wurzelelement der gespeicherten Datei ist. Das muss noch in das Layoutregelwerk eingefügt werden (Stelle 1 im Layout oben):

    <Record element="tableofcontents">
      <PlaceObject>
        <Table padding="5pt">
          <ForAll select="entry">
            <Tr>
              <Td><Paragraph><Value select="@chaptername"/></Paragraph></Td>
              <Td><Paragraph><Value select="@page"/></Paragraph></Td>
            </Tr>
          </ForAll>
        </Table>
      </PlaceObject>
      <ClearPage/>
    </Record>

Es wird eine Tabelle ausgegeben mit einer Zeile für jedes Kindelement `entry`. Durch den anschließenden Seitenumbruch wird der nachfolgende Text nach hinten geschoben. Dadurch muss man das Dokument drei Mal durchlaufen lassen, bevor das Inhaltsverzeichnis korrekt ist:

1. Im ersten Durchlauf wird die Datenstruktur zusammengestellt.
2. Anschließend kann das Inhaltsverzeichnis erstellt werden, durch den Seitenumbruch verschiebt sich der Inhalt um eine Seite nach hinten, die Datenstruktur wird entsprechend aktualisiert.
3. Erst im dritten Durchlauf ist das Inhaltsverzeichnis korrekt.

Wenn man weiß, dass das Inhaltsverzeichnis nur eine Seite in Anspruch nehmen wird, dann kann man den Seitenumbruch auch schon im ersten Durchlauf einfügen. Damit spart man sich einen Durchlauf.

## Sortierung von Stichwortverzeichnissen

In der Regel sind Stichwortverzeichnisse am Ende eines Dokuments zu finden, um in gedruckten Werken relevante Seiten schnell aufzufinden. Bei diesen Stichworten kann es sich um Wörter oder auch um Artikelnummern oder andere Bezeichnungen handeln.

Im Gegensatz zum Inhaltsverzeichnis (das meist vorne in einer Publikation ist), müssen die Daten nur zusammengestellt werden, ein Zwischenspeichern für den nächsten Lauf entfällt in der Regel.

#### Beispiel

Stichwortverzeichnis aus dem Beispiel

Die Beispiele sind naturgemäß immer etwas konstruiert, das ist hier ganz besonders der Fall. Der Index wird in der Praxis natürlich anders zusammengestellt. Da hier nur die Sortierung gezeigt werden soll, wird das Stichwort und die Seitenzahl vorgegeben:

    <data>
      <keyword word="Giraffe" page="1"/>
      <keyword word="Garage" page="2"/>
      <keyword word="Greeting" page="3"/>
      <keyword word="Elevator" page="4"/>
    </data>

Die Layoutdatei besteht aus drei Abschnitten, die einzeln erläutert werden.

    <Layout xmlns="urn:speedata.de:2009/publisher/en"
      xmlns:sd="urn:speedata:2009/publisher/functions/en">

      <Record element="data"> ①
        ...
      </Record>

      <Record element="keyword"> ②
        ...
      </Record>

      <Record element="index"> ③
        ...
      </Record>
    </Layout>

Das Gerüst für die Sortierung und Ausgabe des Stichwortverzeichnisses

① Der Rahmen, der erst die Einträge zusammenbaut, sortiert und anschließend ausgibt.

② Hier werden die Einträge einzeln in der Variablen `indexeinträge` gespeichert.

③ Die sortierten Einträge werden in einer Tabelle ausgegeben.

Der Abschnitt `data` ist der erste Teil aus dem vorherigen Listing:.

    <Record element="data">
      <SetVariable variable="indexentries"/> ①
      <ProcessNode select="keyword"/>

      <SetVariable variable="index">  ②
        <Element name="index">
          <Makeindex select="$indexentries" sortkey="name" section="section"
                     pagenumber="page" />
        </Element>
      </SetVariable>

      <ProcessNode select="$index"/>  ③
    </Record>

① Eine leere Variable `indexentries` wird deklariert. Diese wird im Record `entry` mit den einzelnen Elementen gefüllt (s.u.).

② Die nun gefüllte Variable `indexentries` wird um das Eltern-Element `Index` ergänzt, sortiert und in `$index` gespeichert.

③ Hier wird der Inhalt der Variablen `$index` als Datenstruktur interpretiert und ausgeführt (siehe die Ergänzung unten).

Der Befehl `<Makeindex>` sortiert und gruppiert die Daten, die im Attribut `select` übergeben werden. Die Sortierung erfolgt anhand des Attributs, der bei `sortkey` angegeben ist. Die Gruppierung erfolgt anhand des ersten Buchstabens des Sortierschlüssels. Die Elementstruktur, die mit dem Befehl `<Makeindex>` aufgebaut wird, ist folgende:

    <index>
      <section name="E">
        <indexentry name="Elevator" page="4"/>
      </section>
      <section name="G">
        <indexentry name="Garage" page="2"/>
        <indexentry name="Giraffe" page="1"/>
        <indexentry name="Greeting" page="3"/>
      </section>
    </index>

Der Abschnitt zum Element `keyword` (einfügen an Stelle 1 im Listing Das Gerüst für die Sortierung und Ausgabe des Stichwortverzeichnisses) ist einfach gehalten, und entspricht dem »Copy-of« Muster (siehe Copy-of). Hier wird die Variable `indexeinträge` um jeweils einen Eintrag ergänzt.

    <Record element="keyword">
      <SetVariable variable="indexentries">
        <Copy-of select="$indexentries"/>
        <Element name="indexentry">
          <Attribute name="name" select="@word"/> ①
          <Attribute name="page" select="@page"/>
        </Element>
      </SetVariable>
    </Record>

① In der aktuellen Publisher-Version muss der Eintrag, der sortiert wird, in einem Attribut mit dem Namen `name` gespeichert werden.

Im letzten Teil wird die Tabelle ausgegeben (einfügen an Stelle 3 im Listing Das Gerüst für die Sortierung und Ausgabe des Stichwortverzeichnisses). Für jeden Abschnitt (Element `section` in `<Makeindex>`) wird eine Zeile in Hellgrau ausgegeben mit dem Sortierschlüssel. Anschließend wird für jeden Eintrag innerhalb dieses Abschnittes eine Zeile mit dem Namen des Eintrags und der Seitenzahl ausgegeben.

    <Record element="index">
      <PlaceObject column="1">
        <Table width="3" stretch="max">
          <ForAll select="section">
            <Tr break-below="no" top-distance="10pt">
              <Td colspan="2" backgroundcolor="lightgray">
                <Paragraph><Value select="@name"></Value></Paragraph>
              </Td>
            </Tr>
            <ForAll select="indexentry">
              <Tr>
                <Td>
                  <Paragraph><Value select="@name"/></Paragraph>
                </Td>
                <Td align="right">
                  <Paragraph><Value select="@page"/></Paragraph>
                </Td>
              </Tr>
            </ForAll>
          </ForAll>
        </Table>
      </PlaceObject>
    </Record>

- Aufzählungslisten nachahmen
- Inhaltsverzeichnis in einem Durchlauf erstellen