Chapter 9: About Cross References and Page Numbers
Many documents (such as this one) require page cross references. For example the table of contents of this user guide lists the page numbers of the beginnings of each part, chapter, and section.
RML provides several features that support cross referencing and page number calculations.
The <name>
and <namedString>
tags allow forward
referencing and the <evalString>
tag allows computations of page numbers (or
other computations) inside an RML text. Furthermore these techniques may be combined with preprocessing methods,
such as XSL, the C preprocessor, or the Preppy preprocessor to allow the convenient construction of structures
such as tables of contents, indices or bibliographies.
9.1. the namedString tag and forward references
The <namedString>
tag is similar to the <name>
tag --
it associates a name to a string of text. The namedString
tag is more general than the name
tag in the sense that it
allows other string constructs such as <getName>
in the named text. For example, the
following snippet associates the name Introduction
with the current page number at the time of formatting.
The name
tag does not permit other tags inside the string it names in this manner.
Elsewhere, the RML text may substitute the page number for the introduction using the construct
<name id="Introduction" default="this is a default placeholder, used if Introduction is undefined."/>
...and this reference to the Introduction
name may occur before the Introduction
name is defined.
For example the reference may occur at the beginning of the document in the Table of Contents.
Whenever a name is referenced before it has been defined the default
attribute must be present.
In order to prevent possible formatting anomalies the default value should be approximately the same
size as the expected final value.
9.2. Multiple pass pdf formatting
RML2PDF resolves names that are referenced before they have been defined by making (by default) at most two passes through the text. If the first pass does not define all names before they have been referenced then RML2PDF formats the document twice.
On the first pass the default value for any undefined name is used for formatting the document (and it may under some circumstances effect the placement of the page breaks). On the second the program uses the resolved value determined on the first pass where the name is referenced.
It is possible to create a chain of references that cannot be resolved, such as:
<namedString id="a"><name id="b" default="XXX"/></namedString>
<namedString id="b"><name id="a" default="XXX"/></namedString>
In this case RML2PDF
will signal an error and fail.
It is also possible to have a chain of references which requires more than one pass to resolve, such as:
<namedString id="a"><pageNumber/> is where A is defined, and <name id="b" default="XXX"/></namedString>
...
<namedString id="b"><pageNumber/> is where B is defined, and <name id="c" default="XXX"/></namedString>
...
<namedString id="c"><pageNumber/> is where C is defined</namedString>
By default RML2PDF
will fail in this case also, but it is possible to invoke the main processing function RML2PDF.go
to allow additional formatting passes. For example as in:
to request that the processor execute a maximum of 3 formatting passes before signalling an error if more unresolved names remain.
WARNING: A document that requires two formatting passes will take about twice as long to generate as a document that requires only one. For time critical applications it is best to avoid the need for extra formatting passes if they are not needed.
RML documents that do not have references to names before they are defined will not require more than one formatting pass.
9.3. Calculated Page Numbers: evalString
Some documents require the ability to give "relative pagenumbers." To meet this requirement RML2PDF
includes the
<evalString>
tag. For example The following <para>
:
<para><font color="crimson">
The last page is <getName id="LASTPAGENO" default="-999"/>
One less than that is
<evalString default="XXXX">
<getName id="LASTPAGENO" default="-999"/> - 1
</evalString>.
The current page is <pageNumber/>.
And there are
<evalString default="XXXX">
<getName id="LASTPAGENO" default="-999"/> - <pageNumber/>
</evalString>
pages to go.
</font></para>
LASTPAGENO
, which is presumably defined on the last page. In the context of this document the paragraph evaluates
to the following.
The last page is 1 One less than that is 0. The current page is 66. And there are -65 pages to go.
RML document can make use of arbitrary arithmetic calculations using the
<evalString>
tag, but in practice addition + and subtraction over page numbers
are the most useful.
9.4. Generated RML
Although the name
, namedString
,
getName
and evalString
tags can be used to
build tables of contents and indices, it is not easy to directly edit RML documents that includes cross reference
structures of this kind.
For example to directly add a new section to the this document in RML text it would be necessary to add a new table of contents entry at the top, something like this:
<para style="contents2">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Installation
</para>
<condPageBreak height="144"/>
<h2>
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Installation and Use
</h2>
<para>
RML2PDF is available in several formats: [etcetera...]
</para>
To avoid this complexity this document is not directly written in RML per se, but is written using a text
preprocessor called preppy
which automatically builds the table of contents and inserts the appropriate
entries at the top (while keeping track of chapter and section numbers).
For very complex documents using a preprocessor of some sort may be advisable.