Please note that the latest version of this program is available via Tim Bradshaw's Lisp hacks page at http://www.tfeb.org/lisp/hax.html
Lisp's syntax can be used to express the structure of SGML/XML-based documents very concisely:
<doc> <heading>Foo</heading> <para>this is a paragraph</para> </doc>
Becomes
(:doc (:heading "Foo") (:para "This is a paragraph"))
Because Lisp is also a programming language it is possible to mingle Lisp code and SGML/XML markup in Lisp syntax to programmatically generate documents.
In order to do this `right' for XML you need to deal with
issues of Unicode, case, namespaces and so on. But almost all
documents don't need to worry about this complexity. This code
provides a simple way to mix HTML markup with Lisp code. It does
not enforce anything except the matching of tags, so it knows
nothing about document types or anything like that. In fact the
only thing you need to tell it is which elements have empty
content models, so it generates <br>
rather than
<br></br>.
with-html-output.
Here is an example (which is also included with the code) of Lisp source which calls this macro, and following it the generated HTML (edited slightly so it can be spliced into this document).
(defun count-numbers (n w &optional (s *standard-output*))
(with-html-output (s)
(:html
(:head (:title
(fmt "Numbers from zero below ~R" n)))
(:body
(:h1 (fmt "Numbers from zero below ~R" n))
;; Forms beginning with non-keyword symbols are code to be evaluated.
(lfd)
(:p "Table border width "
(princ w s))
;; isolated keywords are empty tags.
:br
(lfd)
;; empty tags with attributes need this slightly crufty syntax,
;; and also need to be defined as empty.
((:hr :noshade))
(:center
;; the values of attributes are evaluated (in fact the whole
;; attribute list is, but attribute names are keywords).
((:table :border w
:width "90%")
(:tbody ;html 4, bah.
(:tr
((:th :align :left) "English")
((:th :align :right) "Arabic")
((:th :align :right) "Roman"))
;; you can leap into Lisp...
(dotimes (i n)
(let ((c (if (evenp i) "blue" "white")))
;; ... and then back into HTML: the local HTML macro is shorthand
;; for WITH-HTML-OUTPUT to the same stream.
(htm
((:tr :bgcolor c)
((:td :align :left)
(fmt "~R" i))
((:td :align :right)
(fmt "~D" i))
((:td :align :right)
(if (zerop i)
(fmt "")
(fmt "~:@R" i))))
(lfd)))))))
((:hr :noshade))))))
Calling (count-numbers 10 0) yields HTML which is
rendered as follows:
Numbers from zero below ten
Table border width 0
English Arabic Roman zero 0 one 1 I two 2 II three 3 III four 4 IIII five 5 V six 6 VI seven 7 VII eight 8 VIII nine 9 VIIII
| Copyright | htout.lisp is copyright
1999-2000 by me, Tim Bradshaw, and may be used for any purpose
whatsoever by anyone. It has no warranty whatsoever. I
would appreciate acknowledgement if you use it in anger,
and I would also very much appreciate any feedback or bug
fixes. |
|---|---|
| Please mail me | with any bugs or comments. |
Author: Tim Bradshaw(tfb@tfeb.org)
Copyright 1999–2003 Tim Bradshaw