Footnotes

Footnotes

David Pawson

This section deals with a simple method of adding numbered footnotes to a document at the end of a high level element. The example given uses a structure of SECTION to hold all footnotes at its end. Numbering restarts with the next section. Alternatives are described in dbblock.dsl, from Norman Walsh docbook work. The stylesheet is based on functions from Norman Walsh and Chris Maden.

Two blocks of code are necessary, the first to handle the footnote within the body of the document and to generate the footnote references, the second to produce the footnotes as part of a footnotes mode

This code sits in the body of the stylesheet to handle the SECTION, where I want the footnotes to appear.

(element section
	 (let ((footnotes (select-elements (descendants (current-node))
					   "FOOTNOTE")))
	   (sosofo-append (process-children)
			  (if (not (node-list-empty? footnotes))
			      (make rule
				    orientation: 'horizontal)
			      (empty-sosofo))
			  (with-mode footnotes
				     (process-node-list footnotes)))))

Description. The 'let' structure assigns to variable footnotes the list of footnotes found by searching the descendants of element section for all FOOTNOTE elements. The sosofo-append causes the content of the section to be output. If any footnotes exist, the node list footnotes will not be empty and the make rule will produce a dividing line beneath the text of the section and the footnotes. Otherwise the rule is not output — the empty-sosofo clause of the if statement. After seperating the footnotes from the text the with-mode footnotes is used to process the footnotes. I'll come to this in a minute

This also sits in the body of the stylesheet to handle the footnotes as they appear. I want to replace the content of the footnote with a reference to it.

(element footnote
	($ss-seq$ + (literal (footnote-number (current-node)))))

(define (footnote-number footnote)
 (format-number (component-child-number footnote '("SECTION")) "1"))

This code is straight from the docbook stylesheet, file dbblock.dsl. It puts out an in-line sequence, shifted in size and offset by set factors relative to the main text size. The end result is to produce a superscript number, the footnote number of the current-node. This is determined by the element number within the current section.

The only change is the use of SECTION as the collecting point for footnotes. This is defined in the list component element number, defined below. Somewhat redundant, it does permit the flexibility of collecting footnotes under different structural blocks, but brings in a seperate problem not yet resolved, how to avoid duplicate horizontal rules when blocks of footnotes are output together.

(define component-element-list
  (list  "SECTION"=20
	"SUBSECT1"
	"SUBSECT2"
	"REPORT")) ;; just in case nothing else matches...

Next comes the actual processing of the footnotes using the footnotes mode. The element-children function came from Chris Maden and handles the default case.


;; (element-children) returns the children of a node of class element.

(define (element-children #!optional (snl (current-node)))
  (node-list-filter (lambda (node)
                      (equal? (node-property 'class-name
                                             node)
                              'element))
                    (children snl)))


(mode footnotes
  (default (process-node-list (element-children)))


  (element (footnote)
	(make paragraph
	(make sequence
	 =20
	  (literal "Note")
	  (literal (footnote-number (current-node)))
	  (literal " ")
	  (process-children))))
)

The actual mode simply outputs one note per paragraph, preceeded by the two literals and the footnote number.

All other functions are from the standard docbook code, mostly found in file dblib.dsl. As of my usage, it stands at version 1.08 beta 5. It may change. If it does, search out a file called xref, presently held in the print directory of the distribution. This holds the key to finding your way around.