Abstract. In this chapter we will take a systematic look at the HTML mirror functions, which are derived from a HTML DTD (document type definition). |
![]() ![]() ![]() 1 What is a HTML mirror function We first describe what makes a function an HTML mirror function. |
1.1 What is a HTML mirror function 1.2 The context of a HTML mirror fragment. |
![]() ![]() ![]() 1.1 What is a HTML mirror function |
<html> <head><title>Doc Title</title></head> <body><h1>Title</h1> <p> First paragraph </p> </body> </html>
As the basic idea in LAML, a function has been defined for each element in HTML. In the early days of LAML these functions were programmed manually, in an ad hoc fashion. In the current version of LAML, they are all generated automatically from the formal definition of an XML language, such as XHTML. In another chapter of the tutorial we will see how to generate such function from our own XML languages. The HTML mirror functions are quite advance, not least because they carry out a comprehensive validation of the generated HTML code.
In this chapter we will only be concerned with the latest version of the HTML mirror functions. Thus, all the earlier versions - more or less ad hoc attempts - will not be discussed here. Concretely, we will use the mirror of XHTML 1.0 strict. LAML also supports the other variants of XHTML (transitional and frameset) and HTML4.01. We recommend that you stick to the XHTML mirrors.
The document above corresponds to doc0. (As always, click on the red name to make the document appear in the other big frame of the browser). Take at look at the
write-clause (). (The color dots - source markers - appear in pairs: One in this frame and a similar one in the other frame.
You can navigate both of them). As we see, the direct counterpart to the HTML fragment
shown above is:
(html (head (title "Doc Title") ) (body (h1 "Title") (p "First paragraph") ) )
We notice the following:
![]() ![]() ![]() 1.2 The context of a HTML mirror fragment. |
It is easy to recognize the HTML mirror fragment in write-clause of doc0 ().
But what about the other aspects of doc0? Let us explain each of them, from first to last line.
The form (html ...) actually returns a syntax tree, which is rendered and written to a file by write-html. Using write-html it is possible to control the name of the HTML target file. In the example, no target file is given, however. In that case - and as the default rule - write-html writes the HTML file on doc0.html in the same directory as the laml source file, provided that the LAML source file is located in doc0.laml. Thus, a file f.laml gives rise to a file f.html when it is processed.
![]() ![]() ![]() 2 Parameters to mirror functions In this section we will study the basic parameter passing conventions of the HTML mirror functions |
2.1 Parameters 2.2 More Parameters 2.3 Whitespace handling 2.4 Character references 2.5 CSS attributes |
![]() ![]() ![]() 2.1 Parameters |
Now that we have seen the overall picture we will study the parameter conventions of the HTML mirror functions in LAML. We will turn our interest to another document, namely mirror1. As promised, we load the necessary libraries directly, thus circumventing the use of the use of the simple document style 'simple-xhtml1.0-strict-validating'.
The resulting - and frankly - not very interesting HTML document is mirror1.html
The most basic rules are the following:For a contrete illustration take a look at item one in the-write-clause (), namely:
(a 'href laml-url "LAML")
This corresponds roughly to the HTML fragment:
The first parameter of the Scheme form is the symbol href, which plays the role of an attribute name. Therefore, the following parameter should be a string. And it is, namely the value of the variable laml-url. The third parameter is a string which is not preceded by a symbol; As such, the third parameter "LAML" is part of the contents of the anchor element instance.<a href="laml-url">LAML</a>
The XML-in-LAML processing parameter xml-accept-only-string-valued-attributes is normally true (#t). This parameter is set by the procedure set-xml-accept-only-string-valued-attributes-in, because it needs a language argument. (If you mix two or more XML-in-LAML language, you can have different values of xml-accept-only-string-valued-attributes for the languages involved). As the name indicates, this variable controls the rigidness of LAML with respect to the attribute values. If you set this variable to false (#f) LAML will use the function as-string on the parameter which follows an attribute name (a symbol). We recommend that you use the true value of this attribute.
In the second list element of the-write-clause () we have rotated the parameters,
but still there is one contents parameter, "LAML" and a single attribute, href.
Notice one difference between
(a 'href laml-url "LAML")
and
<a href="laml-url">LAML</a>
In the Scheme form laml-url is a variable, the value of which is the string "http://www.cs.auc.dk/~normark/laml/". The corresponding HTML fragment should really be the much longer
<a href="http://www.cs.auc.dk/~normark/laml/">LAML</a>
In XML it is generally not allowed to apply the same attribute more than once in a given element instance. Therefore, we issue a warning if you attempt so. Thus
(a 'href laml-url 'href "http://www.google.com" "LAML")
will give a warning. From a pragmatic point of view, this XML convention is in fact not very practical. We have found that it sometimes is quite useful to pass an attribute more than once. (This is the case if we work with elements that have many attributes, some of which are set at a general level). In most LAML processing context you can trust that the first occurence of 'href, with the value of the Scheme variable laml-url, takes effect. Trailing occurrences of the 'href attribute are simple ignored.
We see that LAML/Scheme programs can use all elements of Scheme side by side with use of the HTML mirror functions. This is useful in many cases, such as in situations where URLs are defined as symbolic constants, and used several times in a document.
![]() ![]() ![]() 2.2 More Parameters |
Let us now illustrate another mirror function parameter rule:
We still look at mirror1 document, which is rendered as mirror1.html (and part of the tutorial example documents.)
In the third unordered list item in the-write-clause () we pass a single list to the mirror function, namely
(list "LAML" 'href laml-url)
In the fourth item at line only the attributes, as bound to my-attributes, are passed as a list, and this line is really identical with the previous line,
.
This parameter convention makes it possible to organize part of the content, or a collection of attributes, in lists, and just pass the list as a parameter side by side with content and attribute parameters. This is important for a flexible handling of Lisp data, which typically is organized in lists.
Let us finally see a more elaborate example at the last line . Here the variable target-attributes is bound to
the list
(target "t" href "http://www.cs.auc.dk/~normark/laml/"
in the surrounding let* special form. The textual contents of the a element mirror function is
LAML Power
By the way, you will find out that the target attribute of the a element is not valid in XHTML1.0 strict. LAML tells you that when you process the document. We should really use XHTML1.0 transitional if we want a valid document. Try it out yourself!
In summary, we have seen that data, which is organized in lists, can be easily passed as both contents, attributes, and mixed contents/attributes.
To see more advanced, but extremely useful examples of this, please take a look at a set of additional examples, especially those about tables. (These additional examples accompany one of the papers we I have written about LAML). Notice that these particular examples use the HTML4.01 transitional mirror.
![]() ![]() ![]() 2.3 Whitespace handling |
Let us now turn to a detail, namely the handling of white space. We turn out interest to yet another document namely mirror2. You can also see the rendering of the document. In this document we have not given any LAML processing attributes at all. It means that we use the default values.
The relevant mirror rules are:
First, the choice of boolean false, #f, as the space suppress value is arbitrary. Any value which can be distinguised (via a type predicate) from symbols and strings at run time would be equally good. (The value of the variable explicit-space-suppress controls which value to use for white space suppressing).
In the first paragraph of html-write-clause three content strings are passed to the mirror of the p element. Notice that the interspacing after "the" and before "paragraph" is due to the first of the rules.
Normally there is no space just in front of punctuations. The second line
(p "This is the second" (b "paragraph") _ ".")
illustrates the second rule, where the space between "paragraph" and "." is suppressed by the variable named underscore.
The third line shows that the space handling also applies in the case where the contents is passed as a list
of words:
(p (list (kbd "This") "is" "the" "third" "paragraph" _ "."))
Again, take a look at the rendered HTML page.
The fourth paragraph at shows that we can even have attributes, here a class attribute, side by side with
the elements of the list.
The fifth pargraph illustrates that the lists can be nested, and - in
- that the attributes can be
burried in the inner list.
The last, and seventh paragraph (a very strange example, I should admit) shows that white space suppress work well together with content lists.
![]() ![]() ![]() 2.4 Character references |
Character references are used to denote special characters, which cannot be typed directly due to the limitation of the keyboards in normal use. Character references are also used to get access to characters such as <, > and & which have special meanings in HTML.
In LAML there is no technical need to give special interpretations of <, >, and &. Therefore these characters are transformed behind the scene, such that they appear in the HTML document as entered in the input. This is done through use of the character transformation table via which < is converted to <lt;, > to >lt;, and & to <.The HTML character transformation tables is described in in section 5.
Imagine that <, > and & were output verbatim in the HTML text. This would compromise the validation (see section 3) because we in that way could produce HTML markup. In LAML, the only way to produce markup is via use of the HTML mirror functions.
In XHTML a character reference is denoted (char-ref x). The parameter x can be a number or a symbolic name. The document char-ref shows a number of examples. Internally, a character reference is a structural entity in the same way as element instances and white space markers. When the structure (the AST) is linearized to text, the character references are translated to HTML character references.
![]() ![]() ![]() 2.5 CSS attributes |
Inline CSS attributes are handled in a special way in a LAML document. Such attributes are often useful when we form HTML presentational abstractions in which we want to make use of the special rendering made possible with Cascading Style Sheet attributes.
The CSS mirror rule in LAML is the following:
Let us now study a document with CSS attributes, namely mirror3. You can also see the rendering of the document and hereby get a concrete feeling for the effect of the CSS attributes in the document.
Take a look at a-write-clause. When we use inline CSS attributes in a HTML document it normally happens
through the HTML style attribute. The value of a style attribute is a CSS fragment
which uses a slightly different syntax than HTML and XML. At we illustrate this.
In the fragment at we show the preferred LAML handling of CSS attributes in LAML.
We see that CSS attributes can be given side by side with HTML attributes. In other
words, all attributes are handled uniformly, and in the same syntax.
Notice that LAML does not currently check that the names of the CSS attributes makes sense. Thus, the attribute checking does only apply to the HTML attributes.
![]() ![]() ![]() 3 Validation aspects Here we will discuss the validation aspects of the HTML mirrors. |
3.1 Validation |
![]() ![]() ![]() 3.1 Validation |
As one of the attractive properties of the HTML mirror functions in Scheme, these functions validate the generated HTML code on the fly.
Take a look at the document in mirror4. Please notice that this document is invalid in several respects. Can you already now spot the problematic places in the document?
Well, if not, LAML will help you. We get the following feedback when processing the document:
LAML Emacs Processing Welcome to MzScheme version 101, Copyright (c) 1995-99 PLT (Matthew Flatt) Welcome to LAML Version 19.00 (January 2, 2002, slim) alpha-3. (C) Kurt Normark, Aalborg University, Denmark. XML Warning: XML validation error(s) encountered in an instance of the head element Only title, base, script, style, meta, link, and object elements allowed in a head: <title>An Invalid document</title> <em>Empha... <em>Emphasis not allowed here</em> XML Warning: The XML attribute x is not valid in the p element. XML Warning: The attribute id is not allowed to appear more than once in a p element. XML Warning: XML validation error(s) encountered in an instance of the p element <ol><li>Ordered list not allowed here</li></ol> XML Warning: XML validation error(s) encountered in an instance of the body element <li>li item outside ul and ol context</li> LAML processing time: 510 milliseconds. End of LAML processing Process LAML finished
You can control the amount of checking via the boolean variables and settings in the top of the document. Try it out yourself by processing the file mirror4.laml in the accompanying example directory.
The variable xml-check-error, which originally is defined in the common part of XML-in-LAML, determines the system's reaction on validation errors. As the default value, LAML displays a warning. You can redefine it, however:
(define xml-check-error laml-error)
The procedure laml-error is a function akin to Scheme's error procedure.
With this redefinition, the first encountered validation error stops the LAML processing. Try it out!
You can also control the length of the error messages via the variable xml-error-truncation-length
![]() ![]() ![]() 4 Using more than one mirror In this section we will show how to use more than one mirror in the same document. |
4.1 Using more than one mirror |
![]() ![]() ![]() 4.1 Using more than one mirror |
The XML-in-LAML faciltites of LAML permits use of two or more mirror funcitons in the same document. In this section we will illustrate an extreme, but often occuring situation, namely where both the XHTML 1.0 transitional and the XHTML1.0 frameset mirrors are used in the same LAML document.
The LAML document frameset-1 serves as the example. See also the resulting web page.Three documents are generated: frameset-doc, left-doc, and right-doc. The frameset-doc uses the XHTML1.0 frameset mirror functions. The two others use the XHTML1.0 transitional mirror function. The crucial observation is that there is a substantial obverlap between these two sets of mirror functions (in the meaning of similarly named functions).
In order to deal with this, we need to use the so-called language map. As an example, the name html is ambiguous in the sense that it occurs in both XHTML transitional and XHTMl frameset.Using the language map, it is possible to get hold on a specific mirror function in the following way:
(xhtml10-frameset 'html)
In frameset-1 we have used the respective language map to extract unambigious mirror functions from both XHTML languages. See the functions such as fs:html and tr:html.
Strictly speaking, it is possible to use the language map for only the first loaded mirror library. In our example, this is the XHTML frameset library. LAML will complain or warn about possible language overlap when we use the transitional functions, but we can safely ignore the warnings. In frameset-2 we have turned off the language overlap checking, cf. the no-overlap-checking. Check again the resulting web page which is similar to to frameset-1.html (and, in fact, using the same underlying frame XHTML pages.
![]() ![]() ![]() 5 Character transformation Here we will discuss use of the character transformation table. |
5.1 Transformations |
![]() ![]() ![]() 5.1 Transformations |
We will now illustrate the impact of the html-char-transformation-table. Every character in the contents of a HTML document can be transformed through this table. Needless to say, most characters are mapped to themselves via the table. Only < and > are normally transformed to the corresponding character entities < and >. Let us return to mirror2 document, which is renderd as mirror2.html. We will play a little with the document by using a slightly non-standard html-char-transformation-table.
The mirror2 document is copied to mirror5, which we now work on. Please consult it!
In the fundamental LAML librarylaml.scm the HTML character transformation table, referred by html-char-transformation-table, is created as the identity mapping
(define html-char-transformation-table (list->vector (make-list 256 #t)))
which next is mutated at two locations:
(set-html-char-transformation-entry! html-char-transformation-table (char->integer #<) "<") (set-html-char-transformation-entry! html-char-transformation-table (char->integer #>) ">")
This is the setup in laml.scm. Now we rotate all entries in html-char-transformation-table:
(define html-char-transformation-table (list->vector (append (number-interval 1 255) (list 0)) ))
The original definition corresponds to
(define html-char-transformation-table (list->vector (append (number-interval 0 255)) ))
Numbers are possible entries in the table, cf. the documentation of html-char-transformation-table (click the name).
Now take a look at mirror5.html and compare it with mirror2.html. Can you read it?
This exercise is - of course - just for fun. As a more serious application, we use the HTML character transformation table to convert national characters to the corresponding character entities in HTML. This is useful, because we can now type the national characters in our web documents, and they will be converted to safe and good values in the resulting HTML document.
We control character transformation by set-xml-transliterate-character-data-in and set-xml-char-transformation-table-in. The first form enable character transformation if a boolean #t is passed as second parameter. The second one defines the transformation table. When we define a new XML in LAML language it is possible to define at set of element for which we never use character transformations.
From LAML version 20, the character transformation also works with the pretty printed - pp - writing mode.
![]() ![]() ![]() 6 Building abtractions on top of mirror functions We will here see how we can use the power of Scheme programming together with the HTML mirror functions. |
6.1 Building abtractions 6.2 A CD archive |
![]() ![]() ![]() 6.1 Building abtractions |
We have now seen how to write simple documents with the HTML mirror functions. More or less, the LAML documents are simple counterparts to the corresponding HTML documents. But this need not to be the case.
The road is clear for definition of all kinds of abstractions on top of the mirror functions. We have done a lot of work in this direction. Both LENO, the Scheme Elucidator, the Manual document styles, and others useful stuff have been created by writing abstractions on top of the mirror functions.
You can probably imagine that a LAML source document, which makes heavy use of your own functions, can be quite difficult to approach for others than the original author and developer. The original LENO system is a good examples. In order to avoid arbitrary drifting of LAML document styles, we have come up with the XML-in-LAML framework. With this, the higher level abstractions are defined by an XML DTD (document type definition), which gives rise to an XML-in-LAML language. As such, the high level LAML document is closely connected to XML. Still in the XML document, it is possible to develop arbitrary (non-XML related) abstractions - both on the content side and the attribute side. The XML-in-LAML LENO system is a good example of non-trivial and high level document handling in LAML.
We will discuss the XML in LAML framework in much more detail later in this tutorial.
![]() ![]() ![]() 6.2 A CD archive |
In order to illustrate the basic idea of forming abstractions on top of the mirror functions we will make yet another document, namely abstract1. Our domain will be a CD archive overview. The final document, abstract1.html is also available for viewing.
At the application level, document-body, we see an instance of cd-archive ()
and three nested cd-entry clauses (
,
,
). This is an example of a relative high level document that
enumerates a small CD collection.
The implementation of cd-archive and cd-entry is done in the separate file cd-stuff. Let us first study the function cd-entry. First it is noticed that cd-entry takes a number of subentries, each of which is defined by its own function: cd-number, cd-artist, cd-title, and cd-playing-time. These simple functions just tags the parameter(s) by a unique symbol. Thus, these four functions serve as syntactic suggar, which makes the source document abstract1 nice and comprehensible. For internal purposes in cd-number, cd-artist, cd-title, and cd-playing-time the function tag-data is used. As an example
(cd-playing-time 3 4)
returns the list (cd-playing-time "3:4"). cd-entry binds the constituents to local names in the let clause ()
and it outputs a table (
), which is made by use of the XHTML mirror functions.
In a real situation we would recommend to keep the data free of HTML markup until they are encountered by the top-level function, here cd-archive. But for the demo purpose here, our solution is OK.
The top-level function cd-archive returns the HTML envelope. Due to the flexibility of the HTML mirror function
parameter, the list at
(map spacy cd-entries)
Can be passed as an HTML content contribution just after (h1 page-title) ().
With these remarks we are about to end this example. Notice, however, that the CD example is only a simple example of how to form an ad hoc language (a CD archive language), and to implement it by means of Scheme functions. In this example we have not touched on XML-in-LAML at all. We will give an XML-in-LAML example later in this tutorial.
![]() ![]() ![]() 7 Epilogue We finally conclude and summarize this part of the tutorial |
7.1 Epilogue |
![]() ![]() ![]() 7.1 Epilogue |
We have now in relatively great detail studied various aspects of the XHTML 1.0 strict mirror. LAML also contains a fully validating HTML4.01 mirror, and XHTML 1.0 transitional and frameset mirrors. In addition there are a number of older mirrors, which you should not use for your development. They are only included in the distribution, because a number of document styles and tools still use them internally.
And what is then the most important aspects of the HTML mirror functions? Well, here is my answer:
This ends this part of the tutorial. Use the right arrow in the top bar to navigate to the next part of tutorial, or use the home icon to get back to the top level page of the tutorial.