Seitenzahlen: Seite x von y

Es gibt zwei Wege, die letzte Seitenzahl zu ermitteln. Der erste Weg ist einfach und empfohlen. Der zweite Weg führt über selbst gespeicherte Daten und war die einzige Möglichkeit bis Version 3.9.26. Er wird hier weiterhin beschrieben, weil er aufzeigt, wie Daten gespeichert und für den nächsten Durchlauf bereitgestellt werden.

Um die Länge des Dokuments in Seiten anzugeben, ist in beiden Fällen ein zweiter Durchlauf des Publishers notwendig, da erst am Ende des ersten Durchlaufs klar ist, wie lang das Dokument wird.

Der einfache Weg: $_lastpage

Die interne Variable $_lastpage enthält die Anzahl der Seiten im vorherigen Durchlauf. Diese Variable ist seit Version 3.9.26 verfügbar.

Der etwas kompliziertere Weg

Am Ende des ersten Durchlaufs wird die aktuelle (= letzte) Seitennummer gespeichert, die man anschließend in den folgenden Durchläufen nutzen kann.

Das folgende Beispiel erzeugt einige Seiten mit Ausgaben in der Form Seite 1 von ??. Das dient als Basis für die Ergänzungen.

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

  <Record element="data">
    <!-- ?? is a placeholder that gets overridden -->
    <SetVariable variable="maxpages" select="'??'"/>

    <Loop select="10" variable="i">
      <PlaceObject>
        <Textblock>
          <Paragraph>
            <Value
              select="concat('Page ', sd:current-page(), ' of ', $maxpages )"/>
          </Paragraph>
        </Textblock>
      </PlaceObject>
      <SetVariable variable="lastpage" select="sd:current-page()"/>
      <NewPage/>
    </Loop>
  </Record>
</Layout>

Am Ende der letzte Seite kann die Information mithilfe von <SaveDataset> für den nächsten Lauf zwischengespeichert werden:

<SetVariable variable="attrPagenumber">
  <Attribute name="numberofpages" select="$lastpage"/>
</SetVariable>
<SaveDataset
  name="pagecount"
  elementname="pageinfo"
  attributes="$attrPagenumber"/>

<SaveDataset> erwartet eine XML-Struktur bei der Attribute im Element <Attribute> und, Elemente in <Element> gespeichert werden, wobei dieser Befehl wiederum <Attribute> als Kindelemente haben kann. Diese Struktur wird als XML auf die Festplatte gespeichert und hat in diesem Beispiel die folgende Form:

<pageinfo numberofpages="10" />

Zu Beginn des Laufs kann nun die Datei eingelesen werden, falls sie existiert (d.h. im ersten Lauf wird kein Fehler erzeugt, weil die Datei noch nicht erzeugt wurde):

<Record element="data">
  <SetVariable variable="maxpages" select="'??'"/>
  <LoadDataset name="pagecount"/>
  ...

und dazu

<Record element="pageinfo">
  <SetVariable variable="maxpages" select="@numberofpages"/>
</Record>

Der Datensatz pageinfo wird dann aufgerufen, wenn die XML-Datei pagecount eingelesen wird. Es wird nichts anderes gemacht, als die kurz vorher definierte Variable maxpages mit dem korrekten Inhalt zu überschreiben.

Das vollständige Beispiel sieht nun so aus:

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

  <!-- only evaluated if the file `pagecount` is found (second run) -->
  <Record element="pageinfo">
    <SetVariable variable="maxpages" select="@numberofpages"/>
  </Record>

  <!-- start of data processing -->
  <Record element="data">
    <SetVariable variable="maxpages" select="'??'"/>
    <LoadDataset name="pagecount"/>
    <Loop select="10" variable="i">
      <PlaceObject>
        <Textblock>
          <Paragraph>
            <Value
              select="concat('Page ', sd:current-page(), ' of ', $maxpages )"/>
          </Paragraph>
        </Textblock>
      </PlaceObject>
      <SetVariable variable="lastpage" select="sd:current-page()"/>
      <NewPage/>
    </Loop>
    <!--  Now we know the total number of pages  -->
    <SetVariable variable="attrPagenumber">
      <Attribute name="numberofpages" select="$lastpage"/>
    </SetVariable>
    <SaveDataset
      name="pagecount"
      elementname="pageinfo"
      attributes="$attrPagenumber"/>
  </Record>
</Layout>