The Hg HTML Generation Library

Hg is a library for generating HTML programmatically from Java.  It is intended to be simple to use, independent of other software (except the Java libraries, of course), and easy to extend.

By ``simple to use'' I mean that the library should be easier than just creating a bunch of println statements.  By easy to extend, I mean the library should be (somewhat) well-designed.  You can judge for yourself; the library is open source software.

Hg Home | SourceForge Summary

Here's a quick survey of the library.

The library is intended for use in servers, servelets, jsp, and the like.

Examples

Here's a short example of using the library to create some simple HTML.

import sjp.hg.*;
public class Simple {
public static void main(String[] args) {
String url = "http://www.cs.utk.edu/~sprowell/hg/";

// Use the DocumentFactory to create a new document.
Document doc = DocumentFactory.makeDocument();
Element bodyElt = doc.getBody();

// Add a header and a paragraph. Note that the angle brackets
// in the paragraph text will be converted to entities.
bodyElt.addElement("h1").addText("Simple");
bodyElt.addElement("p").addText("Hello, <html> world!");

// Create a link.
Element linkElt = bodyElt.addElement("p").addElement("a");
linkElt.addText("Hg Home");
linkElt.addAttribute("href",url);

// Write out the result.
System.out.println(doc.toString());
}
}

Here's another way to create the same HTML, using the parser.

import sjp.hg.*;
public class ParseElement {
public static void main(String[] args) {
// Again, make a document using the document factory.
Document doc = DocumentFactory.makeDocument();
Element bodyElt = doc.getBody();
try {
// Here the supplied string is parsed to create tags,
// attributes, and text.
bodyElt.addContent("<h1>Hello</h1>\n<p>Hello, " +
"&lt;html&gt; world!</p><p><a href=\"http:" +
"//www.cs.utk.edu/~sprowell/hg/\">Hg Home</a></p>");
System.out.println(doc.toString());
} catch (ParseException pe) {
pe.printStackTrace();
}
}
}

Those two examples show you the basics of using the library.  You can also invoke the parser directly, and can rewrite documents.

To create a template, write HTML and include variables of the form {$name$} in values or in the text.  For example, you could create HTML of the form:
<font color="{$color$}">{$color$}</font>

Variables can then be bound to a String instance, or to arbitrary HTML tags.  The former are replaced everywhere they occur.  The latter are replaced only in text nodes where HTML tags can appear.  If the variable color is bound to the string "red", then you get:
<font color="red">red</font>

Alternately, if the variable color is bound to the HTML "<em>R</em>ed", then you get:
<font color="{$red$}"><em>R</em>ed</font>

Without further ado, here's a short program that gets a filename and a sequence of variable assignments from the command line.  It then parses the file as HTML, and replaces variables with their values.  The result is written back out.  This is about as hard as it gets.  Note that most of the code is just there to process the command line.

import java.io.*;
import java.util.List;
import sjp.hg.*;
import sjp.hg.parser.*;
import sjp.hg.template.Bindings;
public class BindTest {
public static void main(String[] args) {
// The user must at least supply a filename.
if (args.length < 1) {
System.out.println("Missing filename.");
System.exit(1);
}

// Save the filename.
String filename = args[0];

// Parse the input arguments. The arguments should be of the
// form name=value, where the name is the variable name (without
// the surrounding {$...$} brackets), and the value may be
// either plain text or well-formed HTML.
Bindings bind = new Bindings();
for (int index = 1; index < args.length; index++) {
String arg = args[index];
int equal = arg.indexOf('=');
if (equal < 0) {
System.out.println("Bad argument " + arg + ".");
System.exit(0);
}
String name = arg.substring(0,equal);
String valueStr = arg.substring(equal+1);
try {
// Parse the input.
Parser parser = ParserFactory.makeParser(valueStr);
List<Node> value = parser.parseTags();
if (value.size() == 1 && value.get(0) instanceof Text) {
// Assume the input is just plain text, and treat it as
// such.
Text textObj = (Text) value.get(0);
bind.set(name, textObj.getValue());
} else {
// The input is HTML; store it as such.
bind.set(name, value);
}
} catch (ParseException e) {
e.printStackTrace();
System.exit(1);
}
}

// At this point all we've done is read the command line
// and make the appropriate variable assignments in the
// Bindings object, bind. That was the hard part. Actually
// doing the HTML processing is very easy.

// Now read the document and perform the substitutions.
try {
Reader reader = new FileReader(filename);
Parser parser = ParserFactory.makeParser(reader);
Document doc = parser.parseDocument();
Element head = (Element) bind.replace(doc.getHead());
Element body = (Element) bind.replace(doc.getBody());
doc.set(head, body);
System.out.println(doc.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
} catch (ParseException e) {
e.printStackTrace();
System.exit(1);
}
}
}
To use this, create an HTML file with variables in it.  The following is an example.
<html>
<head><title>{$title$}</title></head>
<body bgcolor=white text=black>
<h1>{$title$}</h1>
<p>My favorite color is <font color="{$color$}">{$color$}</font>,
and my dog's name is {$dog$}.</p>
</body>
</html>
If this document is saved as example.html, then you can run the above code from the prompt with a command such as:
java BindTest example.html 'title=About Me' 'color=green' 'dog=<b>Cato</b>'

The result is the following HTML output.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML><HEAD><TITLE>About Me</TITLE></HEAD><BODY bgcolor="white" text="black">
<H1>About Me</H1>
<P>My favorite color is <FONT color="green">green</FONT>,
and my dog&#039;s name is <B>Cato</B>.</P>
</BODY></HTML>

If you have comments or suggestions, send them to me.

I am solely responsible for the content of my pages. My extreme and controversial views, as well as my mainstream and status quo views, are mine alone. Any mention of an organization on this page should not be construed as an endorsement by that organization of any page content.