von Patrick Gundlach |

Inhaltsverzeichnis in einem Durchlauf erstellen

Oft genug hat man Dokumente mit einem Inhaltsverzeichnis, das irgendwo am Anfang des Dokuments stehen soll. Der normale Weg beim speedata Publisher ist es, die Daten für das Inhaltsverzeichnis während eines Durchlaufs zu sammeln (welche Abschnitte gibt es? auf welcher Seite fangen diese an?). Im nächsten Durchlauf werden diese Daten dann benutzt, um das Inhaltsverzeichnis zu erstellen. Diese Methode war bisher notwendig, weil diese Informationen benötigt werden, bevor sie zur Verfügung stehen.

Nun hat PDF aber eine ganz nette Eigenschaft: man kann die Seiten in einer beliebigen Reihenfolge anzeigen lassen.

Der Seitenbaum in einer PDF-Datei besteht im einfachsten Fall aus einer Liste der vorhandenen Seiten.

Es ist möglich, die Reihenfolge der Seiten nachträglich zu ändern, in dem die Liste der Seiten geändert wird.

Der Seitenbaum muss nicht in der Reihenfolge der geschriebenen Seiten entsprechen.

In LuaTeX gibt es seit Version 1.11.1 (taufrisch) mit dem neuen Callback page_order_index die Möglichkeit, die Seitenreihenfolge zu ändern.

Die Benutzung ist trivial:

function(pagenumber)
  return pagenumber
end

Es wird die physikalische Seitenzahl übergeben und die logische Seitenzahl zurückgegeben. Zum Beispiel um Seite 1 und 12 zu tauschen kann folgender Code benutzt werden (aus dem Handbuch):

callback.register("page_order_index",function(page)
        if page ==  1 then return 12
    elseif page == 12 then return  1
    else                   return page
end end)

Es bleibt das Problem, dass bei der Berechnung der Kopf- und Fußzeilen, des Satzspiegels (linke bzw. rechte Seite) usw. die neue Reihenfolge berücksichtigt werden muss. Das wird auf PDF-Ebene natürlich nicht gelöst.

speedata Publisher

Die Schnittstelle zum speedata Publisher läuft über die schon vorhandenen Befehle <InsertPages> und <SavePages>:

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

  <Record element="data">
    <InsertPages name="table of contents" pages="1" />

    <ProcessNode select="chapter" />

    <SavePages name="table of contents">
      <PlaceObject>
        ...
      </PlaceObject>
    </SavePages>
  </Record>
</Layout>

Das Ziel der später erstellten Seiten wird mit <InsertPages> markiert und die eigentlichen Seiten mit <SavePages> erzeugt. Der speedata Publisher kümmert sich darum, dass die interne Seitenzahl nach <InsertPages> um die angegebene Zahl erhöht wird und dass im Inhalt von <SavePages> wiederum die Seitenzahl angepasst wird.

Damit die Seitennummerierung auch richtig ist, muss man die Anzahl der einzufügenden Seiten vorab kennen. Das ist bei Datenblättern und Produktkatalogen (dem eigentlichen Anwendungsfall für den speedata Publisher) fast immer gegeben, so dass das in der Praxis nur eine kleine Einschränkung ist.

Beispiel

Ein ausführliches und kommentiertes Beispiel ist in dem »examples-Repository« zu finden.

https://github.com/speedata/examples/tree/master/technical/singlepasstoc

Dieses Feature benötigt den speedata Publisher in der Version 3.7.13 oder höher.