Seitenzahlen: Seite x von y

Um die Länge des Dokuments in Seiten anzugeben, ist ein zweiter Durchlauf des Publishers notwendig: 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>