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
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
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.
<namedString id="Introduction">The Introduction starts at <pageNumber/></namedString>
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>
Performs arithmetic calculations (subtractions) using the current page number and a forward reference to the 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
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>
As well as the text of the section itself
<condPageBreak height="144"/> <h2> <getName id="chapterNumber"/>.<seq id="sectionNumber"/> Installation and Use </h2> <para> RML2PDF is available in several formats: [etcetera...] </para>
And unless the creator takes great care it may be necessary to adjust various section or chapter numbers in other entries as well.
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.