Since LP/CLP systems perform symbolic processing using Herbrand terms, it seems natural to be able to handle HTML code directly as terms. Then, such structures only need to be translated by appropriate predicates to HTML code when they need to be output. In general, this relationship between HTML code and Prolog terms allows viewing any WWW page as a Herbrand term. The predicates which provide this functionality in PiLLoW are:
In an HTML term certain atoms and structures represent special functionality at the HTML level. An HTML term can be recursively a list of HTML terms. The following are legal HTML terms:
hello [hello, world] ["This is an ", em('HTML'), " term"]
When converting HTML terms to characters, html2terms/2 translates special structures into the corresponding format in HTML, applying itself recursively to their arguments. Strings are always leaved unchanged. HTML terms may contain logic variables, provided they are instantiated before the term is translated or output. This allows creating documents piecemeal, backpatching of references in documents, etc.
In the following sections we list the meaning of the principal Prolog structures that represent special functionality at the HTML level. Only special atoms are translated, the rest are assumed to be normal text and will be passed through to the HTML document.
Basically, HTML has two kinds of components: HTML elements and HTML environments. An HTML element has the form `` <NAME Attributes >'' were NAME is the name of the element and Attributes is a (possibly empty) sequence of attributes, each of them being either an attribute name or an attribute assignment as name="Value".
An HTML environment has the form ``<NAME Attributes >
Text </NAME>
'' were NAME is the name of the
environment an Attributes has the same form as before.
The general Prolog structures that represent these two HTML constructions are:
img$[src='images/map.gif',alt="A map",ismap]
is translated into the HTML source
<img src="images/map.gif" alt="A map" ismap>
Note that HTML is not case-sensitive, so we can use lower-case
atoms.
address('clip@dia.fi.upm.es')
is translated into the HTML source
<address>clip@dia.fi.upm.es</address>
a([href='http://www.clip.dia.fi.upm.es/'],"Clip home")
represents the HTML source
<a href="http://www.clip.dia.fi.upm.es/">Clip home</a>
Now we can rewrite the previous example as follows:
#!/usr/local/bin/lpshell :- use_module('/usr/local/src/pillow/pillow.pl'). main(_) :- get_form_input(Input), get_form_value(Input,person_name,Name), response(Name,Response), output_html([ 'Content-type: text/html', html([title('Telephone database'), img$[src='phone.gif'], h2('Telephone database'), hr$[], Response)]). response(Name, Response) :- form_empty_value(Name) -> Response = 'You have to provide a name.' ; phone(Name, Phone) -> Response = ['Telephone number of ',b(Name),': ',Phone] ; Response = ['No telephone number available for ',b(Name),'.']. phone(daniel, '336-7448'). phone(manuel, '336-7435'). phone(sacha, '543-5316').
Any HTML construction can be represented with these structures (except comments and declarations, which could be included as atoms or strings), but the PiLLoW library provides additional, specific structures to simplify HTML creation.
In this section we will list the special structures for HTML which PiLLoW understands. A predicate html_expansion/2 is provided to define new structures.
<html>
).
</html>
).
<hr>
).
\\
Produces a line break (translates to <br>
).
<p>
).
<img>
element).
<a href="
Addr">
Text</a>
).
<a name="
Label">
Text</a>
).
<h
N>
environment).
<ul>
environment).
<ol>
environment).
<dl>
environment).
<pre>
environment).
With these additional structures, we can rewrite the previous example as follows (note that in this particular example the use of heading/2 or h2/1 is equally suitable):
#!/usr/local/bin/lpshell :- use_module('/usr/local/src/pillow/pillow.pl'). main(_) :- get_form_input(Input), get_form_value(Input,person_name,Name), response(Name,Response), output_html([ cgi_reply, start, title('Telephone database'), image('phone.gif'), heading(2,'Telephone database'), --, Response, end]). response(Name, Response) :- form_empty_value(Name) -> Response = 'You have to provide a name.' ; phone(Name, Phone) -> Response = ['Telephone number of ',b(Name),': ',Phone] ; Response = ['No telephone number available for ',b(Name),'.']. phone(daniel, '336-7448'). phone(manuel, '336-7435'). phone(sacha, '543-5316').
We have not included above the specific structures for creating forms, they are included and explained in the following section.
In this section we explain the structures which represent the various input elements that provide forms.
</form>
).
checkbox
with name Name, State=on if the checkbox is
initially checked (translates to an <input>
element).
radio
with name Name (several radio buttons
which are interlocked must share their name), Value is the the
value returned by the button, if Selected=Value the button
is initially checked (translates to an <input>
element).
text
, hidden
, submit
,
reset
, ...(translates to an <input>
element).
<textarea>
environment).
<select>
environment).
For example, in order to generate a form suitable for sending input to the previously described phone database handler one could type at a Prolog prompt:
?:- ['/usr/local/src/pillow/pillow.pl'], output_html([ start, title('Telephone database'), heading(2,'Telephone database'), $, start_form('http://www.clip.dia.fi.upm.es/cgi-bin/phone_db.pl'), 'Click here, enter name of clip member, and press Return:', \\, input(text,[name=person_name,size=20]), end_form, end]).
Of course, one could have also simply written directly the resulting HTML document:
<html> <title>Telephone database</title> <h2>Telephone database</h2> <p> <form method="POST" action="http://www.clip.dia.fi.upm.es/cgi-bin/phone_db.pl"> Click here, enter name of clip member, and press Return: <br> <input type="text" name="person_name" size="20"> </form> </html>