How to use the http/html_write library to write HTML to a file

I am trying to generate a HTML file using SWI Prolog’s library(http/html_write). I would like to produce the HTML below and write it to a file named “mypage.html”:

<!DOCTYPE html>
<html>
  <head>
    <title>Hello</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p id="my-id">This is a paragraph.</p>
  </body>
</html>

So far, I have written a Prolog representation of the HTML:

html(head(title('Hello')),
     body([h1('Hello'),
           p(id('my-id'), 'This is a paragraph.')]))

Now what? How do I actually convert this representation into a string which I would then write to a file named “mypage.html”? I have read the documentation (Examples for using the HTML write library), but I am unable to understand how to convert a HTML representation into a string.

I tried to use html_write:print_html/1, but all it does is print the structure like I have written it:

$ swipl --quiet                        
?- use_module(library(http/html_write)).
true.

?- print_html([html(head(title('Hello')),
|                   body([h1('Hello'),
|                         p(id('my-id'), 'This is a paragraph.')]))]).
html(head(title(Hello)),body([h1(Hello),p(id(my-id),This is a paragraph.)]))
true.

?- 

Could you provide a minimal working example for converting a Prolog representation of HTML into a string that is then written to a file?

(Note: this question was originally posted on Stack Overflow: How to use SWI Prolog's http/html_write library to write HTML to a file - Stack Overflow, but there has been no satisfactory answer for over two weeks).

Here is an example of a script that takes an HTML page with a header and a body, transforms it to a list of atoms and layout instructions with phrase/2, then prints it to standard output using print_html/1 or to a file using print_html/2. First, the file, htmlfile.pl:

:- initialization(main, main).

:- use_module(library(http/html_write)).

main :-
    my_html(X),
    phrase(X, Y),
    (   current_prolog_flag(argv, [File|_])
    ->  setup_call_cleanup(open(File, write, Out),
            print_html(Out, Y),
            close(Out))
    ;   print_html(Y)
    ).

my_html(
    page(
        % head
        title('Hello'),
        % body
        [ h1('Hello'),
          p(id('my-id'), 'This is a paragraph.')
        ])
    ).

To write the contents of my_html/1 above to the file my.html:

$ swipl htmlfile.pl my.html

To write to standard output:

$ swipl htmlfile.pl        
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

</head>
<body>

<h1>Hello</h1>

<p id="my-id">
This is a paragraph.</p>
</body>
</html>

See also here.

EDIT: the bottom line is, use phrase/2, then print_html/1 or print_html/2. You could also capture the output of print_html/1 using with_output_to/2, like this:

?- phrase(HTML, L), with_output_to(string(HTML_string), print_html(L)).

See the with_output_to/2 docs for what else you can use for the first argument. This might be useful if you don’t want to write to a file right away.

3 Likes