Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLBlock.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLBlock.java	(revision 6284)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLBlock.java	(revision 6285)
@@ -4,283 +4,294 @@
 
 public class HTMLBlock
-{ Vector	content;
-	int			tagpos;
-	int			endpos;
-
-	public HTMLBlock(int docpos)
-	{ this.content	= new Vector(1);
-		this.tagpos		= docpos;
-	}
-
-	public HTMLBlock(int docpos, int endpos)
-	{ this.content	= new Vector(1);
-		this.tagpos		= docpos;
-		this.endpos		= endpos;
-	}
-
-	public void addTag(HTMLTag tag)
-	{ if (tag.endPos() > this.endpos)
-		{	this.endpos	= tag.endPos();
-		}
-		content.addElement(tag);
-	}
-
-	public void addText(String text)
-	{ content.addElement(text);
-	}
-
-	public void addText(HTMLCText text)
-	{ if (text.endPos() > this.endpos)
-		{	this.endpos	= text.endPos();
-		}
-		content.addElement(text);
-	}
-
-	/**
-	 * @return HTML encoded <code>String</code> of the document
-	 */
-	public String contentString()
-	{ int member;
-		StringBuffer reply;
-		String type;
-
-		reply = new StringBuffer();
-		for (member = 1; member < content.size() - 1; member ++)
-		{ if (content.elementAt(member) instanceof String)
-			{ reply.append((String) content.elementAt(member));
-			}
-			else if (content.elementAt(member) instanceof HTMLCText)
-			{	reply.append(((HTMLCText) content.elementAt(member)).toString());
-			}
-		}
-		return reply.toString();
-	}
-
-	/**
-	 * Returns document position of start of the block
-	 */
-	public int startPos()
-	{ return this.tagpos;
-	}
-
-	/**
-	 * Returns document position of end of the block
-	 */
-	public int endPos()
-	{ return this.tagpos;
-	}
-
-	/**
-	 * @return head (first) tag of the block
-	 */
-	public HTMLTag headTag()
-	{	return ((HTMLTag) content.elementAt(0));
-	}
-
-	/**
-	 * @return name (as a <code>String</code>) of the tag at the head of the block
-	 */
-	public String headTagName()
-	{ return ((HTMLTag) content.elementAt(0)).tagName();
-	}
-
-	/**
-	 * @return name of the tail (last) tag of the block as a <code>String</code>
-	 */
-	public String tailTagName()
-	{ return (((HTMLTag) content.elementAt(content.size() - 1)).tagName());
-	}
+{ Vector content;
+  int    tagpos;
+  int    endpos;
+
+  public HTMLBlock(int docpos)
+  { this.content = new Vector(1);
+    this.tagpos  = docpos;
+  }
+
+  public HTMLBlock(int docpos, int endpos)
+  { this.content = new Vector(1);
+    this.tagpos  = docpos;
+    this.endpos  = endpos;
+  }
+
+  public void addTag(HTMLTag tag)
+  { if (tag.endPos() > this.endpos)
+    { this.endpos = tag.endPos();
+    }
+    content.addElement(tag);
+  }
+
+  /**
+   *  @deprecccate
+  public void addText(String text)
+  { content.addElement(text);
+  }
+   */
+
+  public void addText(HTMLCText text)
+  { if (text.endPos() > this.endpos)
+    { this.endpos	= text.endPos();
+    }
+    content.addElement(text);
+  }
+
+  /**
+   * @return HTML encoded <code>String</code> of the document
+   */
+  public String contentString()
+  { int member;
+    StringBuffer reply;
+    String type;
+
+    reply = new StringBuffer();
+    for (member = 1; member < content.size() - 1; member ++)
+    { /*if (content.elementAt(member) instanceof String)
+      { reply.append((String) content.elementAt(member));
+      }
+      else 
+      */
+      if (content.elementAt(member) instanceof HTMLCText)
+      {	reply.append(((HTMLCText) content.elementAt(member)).toString());
+      }
+    }
+    return reply.toString();
+  }
+
+  /**
+   * Returns document position of start of the block
+   */
+  public int startPos()
+  { return this.tagpos;
+  }
+
+  /**
+   * Returns document position of end of the block
+   */
+  public int endPos()
+  { return this.tagpos;
+  }
+
+  /**
+   * @return head (first) tag of the block
+   */
+  public HTMLTag headTag()
+  { return ((HTMLTag) content.elementAt(0));
+  }
+
+  /**
+   * @return name (as a <code>String</code>) of the tag at the head of the block
+   */
+  public String headTagName()
+  { return ((HTMLTag) content.elementAt(0)).tagName();
+  }
+
+  /**
+   * @return name of the tail (last) tag of the block as a <code>String</code>
+   */
+  public String tailTagName()
+  { return (((HTMLTag) content.elementAt(content.size() - 1)).tagName());
+  }
 	
 	
-	/**
-	 * 	@return: starting element character position of the item-th item
-	 */
-	private int elementStartPos(int item)
-	{	Object	element;
-		int		pos = -1;
+  /**
+   *  @return: starting element character position of the item-th item
+   */
+  private int elementStartPos(int item)
+  { Object element;
+    int		pos = -1;
 		
-		element = this.content.elementAt(item);
-		if (element instanceof HTMLTag)
-		{	pos	= ((HTMLTag) element).startPos();
-		}
-		else if (element instanceof HTMLCText)
-		{	pos	= ((HTMLCText) element).startPos();
-		}
-		return pos;		
-	}
+    element = this.content.elementAt(item);
+    if (element instanceof HTMLTag)
+    {	pos	= ((HTMLTag) element).startPos();
+    }
+    else if (element instanceof HTMLCText)
+    {	pos	= ((HTMLCText) element).startPos();
+    }
+    return pos;		
+  }
 	
-	/**
-	 * 	@return: ending element character position of the item-th item
-	 */
-	private int elementEndPos(int item)
-	{	Object	element;
-		int		pos = -1;
+  /**
+   *  @return: ending element character position of the item-th item
+   */
+  private int elementEndPos(int item)
+  { Object	element;
+    int		pos = -1;
 		
-		element = this.content.elementAt(item);
-		if (element instanceof HTMLTag)
-		{	pos	= ((HTMLTag) element).endPos();
-		}
-		else if (element instanceof HTMLCText)
-		{	pos	= ((HTMLCText) element).endPos();
-		}
-		return pos;		
-	}
-
-	/**
-	 *	return the HTMLBlock of the indicated subitems
-	 */
-	public HTMLBlock subBlock(int startitem, int enditem)
-	{ int i;
-		Object	element;
-		HTMLBlock reply;
-		reply = new HTMLBlock(	this.elementStartPos(startitem),
-								this.elementEndPos(enditem-1));
-	  // copy all the bits
-	  for (i = startitem; i < enditem; i++)
-	  {	element = this.content.elementAt(i);
-		if (element instanceof HTMLTag)
-		{ reply.addTag((HTMLTag) element);
-		}
-		else if (element instanceof HTMLCText)
-		{	reply.addText((HTMLCText) element);
-		}
-		else if (element instanceof String)
-		{	reply.addText((String) element);
-		}
-	  }
-	  return reply;
-	}
-
-	/**
-	 * Return the position of the given <code>HTMLBlock</code> within this block
-	 * @return the tag index of the child block; or < 0 if not a chile
-	 */
-	public int find(HTMLBlock subblock)
-	{	int start, end, at, attag;
-		HTMLTag tag;
-
-		start = 0;
-		end		= this.content.size();
-		while (start != end)
-		{	/* compare positions */
-			at = (start + end) / 2;
-			attag	= at;
-			while (attag < end &&
-						 (content.elementAt(attag) instanceof HTMLTag) == false)
-			{ attag ++;
-			}
-
-			if (attag == end)
-			{	end = at;
-				continue;
-			}
-			tag =	(HTMLTag) content.elementAt(attag);
-			if (tag.startPos() > subblock.startPos())
-			{ end = at;				
-			}
-			else if (tag.startPos() < subblock.startPos())
-			{ start	= attag + 1;
-			}
-			else
-			{	return attag;
-			}
-		}
-		return -1;
-	}
-
-	/**
-	 * @return The raw HTML of the block
-	 */
-	public String HTMLString()
-	{	int 					loop;
-		StringBuffer	reply;
-
-		reply	= new StringBuffer();
-		for (loop = 0; loop < this.content.size(); loop ++)
-		{	if (content.elementAt(loop) instanceof String)
-			{	reply.append((String) content.elementAt(loop));
-			}
-			else if (content.elementAt(loop) instanceof HTMLCText)
-			{	reply.append(((HTMLCText) content.elementAt(loop)).toString());
-			}
-			else if (content.elementAt(loop) instanceof HTMLTag)
-			{	reply.append(((HTMLTag) content.elementAt(loop)).toString());
-			}
-		}
-		return reply.toString();
-	}
-
-	/**
-	 * @return The text of the block - no HTML tags.  If no text is present, any
-	 *         <code>alt</code> information for <code>img</code> tags will be given 
-	 *         instead
-	 */
-	public String toString()
-	{ int member;
-		StringBuffer reply;
-		StringBuffer ireply;
-
-		reply = new StringBuffer("");
-		ireply = new StringBuffer("");
-		for (member = 0; member < content.size(); member ++)
-		{ if (content.elementAt(member) instanceof String)
-			{ reply.append((String) content.elementAt(member));
-			}
-			if (content.elementAt(member) instanceof HTMLCText)
-			{ reply.append(((HTMLCText) content.elementAt(member)).toString());
-			}
-			else if (content.elementAt(member) instanceof HTMLTag)
-			{ if (((HTMLTag) content.elementAt(member)).tagName().equals("img"))
-				{ ireply.append(((HTMLTag) content.elementAt(member)).idValue("alt"));
-				}
-			}
-		}
-		reply = HTMLCText.cleanString(reply);
-		ireply = HTMLCText.cleanString(ireply);
+    element = this.content.elementAt(item);
+    if (element instanceof HTMLTag)
+    { pos = ((HTMLTag) element).endPos();
+    }
+    else if (element instanceof HTMLCText)
+    { pos = ((HTMLCText) element).endPos();
+    }
+    return pos;		
+  }
+
+  /**
+   *  @return the HTMLBlock of the indicated subitems
+   */
+  public HTMLBlock subBlock(int startitem, int enditem)
+  { int       i;
+    Object    element;
+    HTMLBlock reply;
+    reply = new HTMLBlock(this.elementStartPos(startitem),
+			  this.elementEndPos(enditem-1));
+    // copy all the bits
+    for (i = startitem; i < enditem; i++)
+    { element = this.content.elementAt(i);
+      if (element instanceof HTMLTag)
+      { reply.addTag((HTMLTag) element);
+      }
+      else if (element instanceof HTMLCText)
+      {	reply.addText((HTMLCText) element);
+      }
+      /*
+	else if (element instanceof String)
+	{	reply.addText((String) element);
+	}
+      */
+    }
+    return reply;
+  }
+
+  /**
+   * Return the position of the given <code>HTMLBlock</code> within this block
+   * @return the tag index of the child block; or < 0 if not a chile
+   */
+  public int find(HTMLBlock subblock)
+  { int start, end, at, attag;
+    HTMLTag tag;
+
+    start = 0;
+    end		= this.content.size();
+    while (start != end)
+    { /* compare positions */
+      at = (start + end) / 2;
+      attag	= at;
+      while (attag < end &&
+	     (content.elementAt(attag) instanceof HTMLTag) == false)
+      { attag ++;
+      }
+
+      if (attag == end)
+      { end = at;
+        continue;
+      }
+      tag =	(HTMLTag) content.elementAt(attag);
+      if (tag.startPos() > subblock.startPos())
+      { end = at;				
+      }
+      else if (tag.startPos() < subblock.startPos())
+      { start	= attag + 1;
+      }
+      else
+      {	return attag;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * @return The raw HTML of the block
+   */
+  public String HTMLString()
+  { int 					loop;
+    StringBuffer	reply;
+
+    reply	= new StringBuffer();
+    for (loop = 0; loop < this.content.size(); loop ++)
+    { /*
+	if (content.elementAt(loop) instanceof String)
+      {	reply.append((String) content.elementAt(loop));
+      }
+      else 
+      */
+      if (content.elementAt(loop) instanceof HTMLCText)
+      {	reply.append(((HTMLCText) content.elementAt(loop)).toString());
+      }
+      else if (content.elementAt(loop) instanceof HTMLTag)
+      {	reply.append(((HTMLTag) content.elementAt(loop)).toString());
+      }
+    }
+    return reply.toString();
+  }
+
+  /**
+   * @return The text of the block - no HTML tags.  If no text is present, any
+   *         <code>alt</code> information for <code>img</code> tags will be given 
+   *         instead
+   */
+  public String toString()
+  { int member;
+    StringBuffer reply;
+    StringBuffer ireply;
+    
+    reply = new StringBuffer("");
+    ireply = new StringBuffer("");
+    for (member = 0; member < content.size(); member ++)
+    { /*if (content.elementAt(member) instanceof String)
+      { reply.append((String) content.elementAt(member));
+      }
+      */
+      if (content.elementAt(member) instanceof HTMLCText)
+      { reply.append(((HTMLCText) content.elementAt(member)).toString());
+      }
+      else if (content.elementAt(member) instanceof HTMLTag)
+      { if (((HTMLTag) content.elementAt(member)).tagName().equals("img"))
+	{ ireply.append(((HTMLTag) content.elementAt(member)).idValue("alt"));
+	}
+      }
+    }
+    reply = HTMLCText.cleanString(reply);
+    ireply = HTMLCText.cleanString(ireply);
 //		reply = reply.trim();
-		if (reply == null || reply.length() == 0)
-		{ return ireply.toString();
-		}
-		return reply.toString();
-	}
-
-	public Object elementAt(int at)
-	{	return this.content.elementAt(at);
-	}
-
-	/**
-	 * @return the number of elements in the block
-	 */
-	public int size()
-	{	return this.content.size();
-	}
-
-	/**
-	 * @return an enumeration of all elements in the block
-	 */
-	public Enumeration elements()
-	{ Enumeration enum;
-
-		enum = new HTMLBlockEnumerator(this);
-		return enum;
-	}
-
-	/**
-	 * @return an enumeration of all tags in the block
-	 */
-	public Enumeration tagElements()
-	{ Enumeration enum;
-
-		enum = new HTMLBlockTagEnumerator(this);
-		return enum;
-	}
-
-	/**
-	 * Finalization method
-	 */
-	protected void finalize() throws Throwable
-	{	this.content	= null;
-		super.finalize();
-	}
+    if (reply == null || reply.length() == 0)
+    { return ireply.toString();
+    }
+    return reply.toString();
+  }
+
+  public HTMLObject elementAt(int at)
+  { return (HTMLObject) this.content.elementAt(at);
+  }
+
+  /**
+   * @return the number of elements in the block
+   */
+  public int size()
+  { return this.content.size();
+  }
+
+  /**
+   * @return an enumeration of all elements in the block
+   */
+  public Enumeration elements()
+  { Enumeration enum;
+  
+    enum = new HTMLBlockEnumerator(this);
+    return enum;
+  }
+
+  /**
+   * @return an enumeration of all tags in the block
+   */
+  public Enumeration tagElements()
+  { Enumeration enum;
+
+    enum = new HTMLBlockTagEnumerator(this);
+    return enum;
+  }
+
+  /**
+   * Finalization method
+   */
+  protected void finalize() throws Throwable
+  { this.content	= null;
+    super.finalize();
+  }
 }
 
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLCText.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLCText.java	(revision 6284)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLCText.java	(revision 6285)
@@ -1,188 +1,105 @@
 package org.greenstone.gsdl3.gs3build.util;
 
+public class HTMLCText implements HTMLObject
+{ String text;
+  int    start;
+  int    end;
 
+  public static final String HTML_TEXT_TYPE = "Text";
 
-public class HTMLCText
+  public HTMLCText(String text, int start, int end)
+  { this.text  = text;
+    this.start = start;
+    this.end   = end;
+  }
 
-{ String	text;
+  public String getHTMLType()
+  { return HTML_TEXT_TYPE;
+  }
 
-	int			start;
+  public int startPos()
+  { return this.start;
+  }
 
-	int			end;
+  public int endPos()
+  { return this.end;
+  }
 
+  public boolean isEmpty()
+  { return emptyString(this.text);
+  }
 
+  public static boolean emptyString(String s)
+  { int c;
 
-	public HTMLCText(String text, int start, int end)
+    for (c = 0; c < s.length(); c ++)
+    { if (s.charAt(c) > 32)
+      { return false;
+      }
+    }
+    return true;
+  }
 
-	{ this.text		= text;
+  public static StringBuffer cleanString(StringBuffer buffer)
+  { int c;
+    int w;
 
-		this.start	= start;
+    w = 0;	
+    for (c = 0; c < buffer.length(); c ++)
+    { if (buffer.charAt(c) >= 32)
+      { if (buffer.charAt(c) == 32)
+	{ if (w > 0 && buffer.charAt(w-1) > 32)
+	  { buffer.setCharAt(w, buffer.charAt(c));
+	    w ++;
+	  }
+	}
+        else
+	{ if (c != w)
+	  { buffer.setCharAt(w, buffer.charAt(c));
+	  }
+	  w ++;
+	}
+      }
+      else
+      { if (w > 0 && buffer.charAt(w-1) > 32)
+	{ buffer.setCharAt(w,' ');
+	  w ++;
+	}
+      }
+    }
+    buffer.setLength(w);
+    return buffer;
+  }
 
-		this.end		= end;
+  /**
+   * nullString; used by initialisation for checking for
+   * non-blank content (ie. text other than just spaces/returns)
+   * see constructor (ie HTMLBlockList) methods below for role of
+   * this in the larger plan of things
+   */
+  public boolean nullString()
+  { int ch;
 
+    if (text != null)
+    { for (ch = 0; ch < text.length(); ch ++)
+      { if (text.charAt(ch) > ' ')
+	{ return false;
 	}
+      }
+    }
+    return true;
+  }
 
+  public String toString()
+  { return this.text;
+  }
 
-
-	public int startPos()
-
-	{	return this.start;
-
-	}
-
-
-
-	public int endPos()
-
-	{	return this.end;
-
-	}
-
-
-
-	public boolean isEmpty()
-
-	{	return emptyString(this.text);
-
-	}
-
-
-
-	public static boolean emptyString(String s)
-
-	{	int c;
-
-
-
-		for (c = 0; c < s.length(); c ++)
-
-		{	if (s.charAt(c) > 32)
-
-			{ return false;
-
-			}
-
-		}
-
-		return true;
-
-	}
-
-
-
-	public static StringBuffer cleanString(StringBuffer buffer)
-
-	{ int c;
-
-	  int w;
-
-
-
-	  w = 0;	
-
-	  for (c = 0; c < buffer.length(); c ++)
-
-	  { if (buffer.charAt(c) >= 32)
-
-	  	{ if (buffer.charAt(c) == 32)
-
-	  	  { if (w > 0 && buffer.charAt(w-1) > 32)
-
-	  	    { buffer.setCharAt(w, buffer.charAt(c));
-
-		  	  	w ++;
-
-	  	    }
-
-	  	  }
-
-	  	  else
-
-	  	  { if (c != w)
-
-	   	    { buffer.setCharAt(w, buffer.charAt(c));
-
-	   	    }
-
-      	  w ++;
-
-	  	  }
-
-	  	}
-
-	  	else
-
-	  	{ if (w > 0 && buffer.charAt(w-1) > 32)
-
-	  	  { buffer.setCharAt(w,' ');
-
-    	    w ++;
-
-	  	  }
-
-	  	}
-
-	  }
-
-	  buffer.setLength(w);
-
-	  return buffer;
-
-	}
-
-
-
-	/**
-
-	 * nullString; used by initialisation for checking for
-
-	 * non-blank content (ie. text other than just spaces/returns)
-
-	 * see constructor (ie HTMLBlockList) methods below for role of
-
-	 * this in the larger plan of things
-
-	 */
-
-	public boolean nullString()
-
-	{ int ch;
-
-
-
-		if (text != null)
-
-		{ for (ch = 0; ch < text.length(); ch ++)
-
-			{ if (text.charAt(ch) > ' ')
-
-				{ return false;
-
-				}
-
-			}
-
-		}
-
-		return true;
-
-	}
-
-
-
-	public String toString()
-
-	{	return this.text;
-
-	}
-
-	public String toString(boolean cleaned)
-	{	if (cleaned == false)
-		{	return toString();
-		}
-		else
-		{	return HTMLEntity.decodeText(this.text);
-		}
-	}
-
+  public String toString(boolean cleaned)
+  { if (cleaned == false)
+    { return toString();
+    }
+    else
+    { return HTMLEntity.decodeText(this.text);
+    }
+  }
 }
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLContext.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLContext.java	(revision 6284)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLContext.java	(revision 6285)
@@ -46,5 +46,7 @@
 		length	= 0;
 		while (	start > 0)
-		{	if (parent.elementAt(start) instanceof String)
+		{	
+		  /*
+		  if (parent.elementAt(start) instanceof String)
 			{	string = (String) parent.elementAt(start);
 
@@ -59,6 +61,8 @@
 				{	break;
 				}
-			}
-			else if (parent.elementAt(start) instanceof HTMLCText)
+				}
+				else 
+		  */
+			if (parent.elementAt(start) instanceof HTMLCText)
 			{	string = ((HTMLCText) parent.elementAt(start)).toString();
 
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLDoc.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLDoc.java	(revision 6284)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLDoc.java	(revision 6285)
@@ -11,15 +11,15 @@
 
 public class HTMLDoc
-{ String		 		content;
-	String				title;
-	URL						url;						 
-	int						pos;
-	int						status;
-	HTMLBlockList blocklist;
-	List          urls_out;
-	List          urls_in;
-	Object				note;
-	HTMLLoader		loader;
-	HTMLBlock			coded;
+{ String        content;
+  String        title;
+  URL           url;
+  int           pos;
+  int           status;
+  HTMLBlockList blocklist;
+  List          urls_out;
+  List          urls_in;
+  Object        note;
+  HTMLLoader    loader;
+  HTMLBlock     coded;
 
 	/**
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLEntity.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLEntity.java	(revision 6284)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLEntity.java	(revision 6285)
@@ -7,18 +7,18 @@
 
 public class HTMLEntity
-{ String 	name;
-	int     code;
-  static  Vector 	entities = null;
-	static	Vector	nmapping = null;
+{ String  name;
+  int     code;
+  static Vector entities = null;
+  static Vector	nmapping = null;
 
   public HTMLEntity(String name, int code)
   { int start, end, at;
-		HTMLEntity compareEntity;
-
-  	if (HTMLEntity.entities == null)
-  	{ HTMLEntity.entities = new Vector();
-    }
-  	if (HTMLEntity.nmapping == null)
-  	{ HTMLEntity.nmapping = new Vector();
+    HTMLEntity compareEntity;
+
+    if (HTMLEntity.entities == null)
+    { HTMLEntity.entities = new Vector();
+    }
+    if (HTMLEntity.nmapping == null)
+    { HTMLEntity.nmapping = new Vector();
     }
 
@@ -27,24 +27,24 @@
 
     entities.addElement(this);
-		start = 0;
-		end		= nmapping.size();
-		while (start != end)
-		{	at	= (start + end) / 2;
+    start = 0;
+    end   = nmapping.size();
+    while (start != end)
+    { at = (start + end) / 2;
 	
-			compareEntity = 
-			 	(HTMLEntity) entities.elementAt(((Integer) nmapping.elementAt(at)).intValue());
-			if (compareEntity.code > code)
-			{	end = at;
-			}
-			else
-			{	start = at + 1;
-			}
-		}
-		if (end == nmapping.size())
-		{ nmapping.addElement(new Integer(nmapping.size()));
-		}
-		else
-		{	nmapping.insertElementAt(new Integer(nmapping.size()), start);
-		}
+      compareEntity = 
+	(HTMLEntity) entities.elementAt(((Integer) nmapping.elementAt(at)).intValue());
+      if (compareEntity.code > code)
+      { end = at;
+      }
+      else
+      { start = at + 1;
+      }
+    }
+    if (end == nmapping.size())
+    { nmapping.addElement(new Integer(nmapping.size()));
+    }
+    else
+    { nmapping.insertElementAt(new Integer(nmapping.size()), start);
+    }
   }
 
@@ -52,5 +52,5 @@
   { Character c;
 
-  	c = new Character((char) this.code);
+    c = new Character((char) this.code);
     return c.toString();
   }
@@ -58,11 +58,11 @@
   public static String codeString(char c)
   { StringBuffer 	reply;
-  	String        codestring;
-
-  	if (c < 128 || c == '&' || c == '<' || c == '>')
-  	{ return null;
-    }
-		codestring = Integer.toString((int) c);
-    reply	= new StringBuffer("&#");
+    String        codestring;
+
+    if (c < 128 || c == '&' || c == '<' || c == '>')
+    { return null;
+    }
+    codestring = Integer.toString((int) c);
+    reply      = new StringBuffer("&#");
     reply.append(codestring);
     reply.append(";");
@@ -71,151 +71,151 @@
   }
 
-	public static String nameCodeString(char c)
-	{	int start, end, at, compare;
-		HTMLEntity compareEntity;
-
-		start = 0;
-		end		= nmapping.size();
-		while (start != end)
-		{	at	= (start + end) / 2;
-	
-			compareEntity = 
-			 	(HTMLEntity) entities.elementAt(((Integer) nmapping.elementAt(at)).intValue());
-			if (compareEntity.code == (int) c)
-			{	StringBuffer reply;
-
-				reply = new StringBuffer("&");
-				reply.append(compareEntity.name);
-				reply.append(";");
-				return reply.toString();
-			}
-			else if (compareEntity.code < c)
-			{	end	= at;
-			}
-			else
-			{	start	= at + 1;
-			}
-		}
-		return codeString(c);
-	}
+  public static String nameCodeString(char c)
+  { int start, end, at, compare;
+    HTMLEntity compareEntity;
+
+    start = 0;
+    end		= nmapping.size();
+    while (start != end)
+    { at	= (start + end) / 2;
+      
+      compareEntity = 
+	(HTMLEntity) entities.elementAt(((Integer) nmapping.elementAt(at)).intValue());
+      if (compareEntity.code == (int) c)
+      { StringBuffer reply;
+
+        reply = new StringBuffer("&");
+	reply.append(compareEntity.name);
+	reply.append(";");
+	return reply.toString();
+      }
+      else if (compareEntity.code < c)
+      {	end	= at;
+      }
+      else
+      {	start	= at + 1;
+      }
+    }
+    return codeString(c);
+  }
 
   public static void getEntities(String source)
   { HTMLEntity 	newentity;
-  	int         pos;
+    int         pos;
     int					start;
     String			name;
     int					code;
-
-		if (source == null)
-		{	return;
-		}
+    
+    if (source == null)
+    { return;
+    }
 
     start = 0;
     while (start < source.length())
     { pos = start;
-		  while (source.charAt(pos) != ':')
-  		{ pos ++;
-	  	}
-	    name = source.substring(start, pos);
-
-	    // skip colon and reset
-  		pos ++;
-	  	start = pos;
-
-			while(pos < source.length() && source.charAt(pos) > ' ')
-  		{ pos ++;
-    	}
-			code = Integer.parseInt(source.substring(start, pos));
-
-	    newentity = new HTMLEntity(name, code);
-
-  	  while ( pos < source.length() && source.charAt(pos) < ' ')
+      while (source.charAt(pos) != ':')
       { pos ++;
       }
+      name = source.substring(start, pos);
+
+      // skip colon and reset
+      pos ++;
       start = pos;
-    }
-  }
-
-	public static void getEntities(InputStream in)
-	{	getEntities(DocumentLoader.getAsString(in));
+
+      while(pos < source.length() && source.charAt(pos) > ' ')
+      { pos ++;
+      }
+      code = Integer.parseInt(source.substring(start, pos));
+
+      newentity = new HTMLEntity(name, code);
+      
+      while ( pos < source.length() && source.charAt(pos) < ' ')
+      { pos ++;
+      }
+      start = pos;
+    }
+  }
+
+  public static void getEntities(InputStream in)
+  { getEntities(DocumentLoader.getAsString(in));
+  }
+
+  public static void getEntities(File file)
+  { FileInputStream in;
+
+    try
+    { in = new FileInputStream(file);
+      getEntities(in);
+      in.close();
+    }
+    catch (IOException io)
+    { System.out.println("No entities");
+    }
+  }
+
+  public static void getEntities()
+  { ClassLoader loader;
+    InputStream	in;
+
+    in = ClassLoader.getSystemResourceAsStream("org\\greenstone\\gsdl3\\gs3build\\util\\Entities.map");
+    if (in == null)
+    { System.out.println("Unable to load Entities.map from org.greenstone.gsdl3.gs3build.util");
+    }
+    getEntities(in);
+  }
+
+  public static String encodeText(String source, boolean named)
+  { StringBuffer reply;
+    int          start,at;
+
+    if (source == null)
+    { return null;
+    }
+
+    if (HTMLEntity.entities == null)
+    {	getEntities();
+    }
+
+    reply	= new StringBuffer();
+    at 		= 0;
+    start	= 0;
+    while (at < source.length())
+    { if (source.charAt(at) > 128)
+      {	if (at != start)
+	{ reply.append(source.substring(start, at));
 	}
 
-	public static void getEntities(File file)
-	{	FileInputStream in;
-
-		try
-		{	in = new FileInputStream(file);
-			getEntities(in);
-			in.close();
-		}
-		catch (IOException io)
-		{ System.out.println("No entities");
-		}
+        if (named)
+	{ reply.append(nameCodeString(source.charAt(at)));
 	}
-
-	public static void getEntities()
-	{	ClassLoader loader;
-		InputStream	in;
-
-		in 			=	ClassLoader.getSystemResourceAsStream("org\\greenstone\\gsdl3\\gs3build\\util\\Entities.map");
-		if (in == null)
-		{	System.out.println("Unable to load Entities.map from org.greenstone.gsdl3.gs3build.util");
-		}
-		getEntities(in);
+	else
+	{ reply.append(codeString(source.charAt(at)));
 	}
-
-  public static String encodeText(String source, boolean named)
-  {	StringBuffer 	reply;
-		int						start,at;
-
-		if (source == null)
-		{	return null;
-		}
-
-		if (HTMLEntity.entities == null)
-		{	getEntities();
-		}
-
-		reply	= new StringBuffer();
-		at 		= 0;
-		start	= 0;
-		while (at < source.length())
-		{ if (source.charAt(at) > 128)
-			{	if (at != start)
-				{	reply.append(source.substring(start, at));
-				}
-
-				if (named)
-				{ reply.append(nameCodeString(source.charAt(at)));
-				}
-				else
-				{ reply.append(codeString(source.charAt(at)));
-				}
-				start	= at + 1;
-			}
-			at ++;
-		}
+	start	= at + 1;
+      }
+      at ++;
+    }
 		
-  	return reply.toString();
+    return reply.toString();
   }
 
   public static String decodeText(String source)
   { int start, end, loff, roff;
-  	int sstart, send, test;
+    int sstart, send, test;
     int startoff, endoff, baseoff;
     boolean matched;
     String  tail;
-		StringBuffer reply;
-
-		if (source == null)
-		{ return null;
-		}
-
-		if (HTMLEntity.entities == null)
-		{	getEntities();
-		}
-
-    reply			= new StringBuffer();
-    baseoff		= 0;
+    StringBuffer reply;
+
+    if (source == null)
+    { return null;
+    }
+
+    if (HTMLEntity.entities == null)
+    {	getEntities();
+    }
+
+    reply   = new StringBuffer();
+    baseoff = 0;
 
     tail = source;
@@ -254,79 +254,79 @@
         }
       }
-			else
+      else
       {	start = 0;
-  		  end		= HTMLEntity.entities.size();
-        loff	= 0;
-
-	  	  while (startoff+1+loff < tail.length() && start != end)
-  	  	{ sstart	= start;
-    			send		= end;
-          test		= (sstart + send) >> 1;
-
-		      matched	= false;
-
-    	    roff	= startoff + 1 + loff;
-
-  	  	  while (sstart != send)
-    	  	{	test = (sstart + send) >> 1;
-
-      			if (tail.charAt(roff) < ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.charAt(loff))
-	      		{ send = test;
-		        }
-  		      else if (tail.charAt(roff) > ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.charAt(loff))
-						{ sstart	= test + 1;
-      		  }
-        		else
-		        { break;
-  		      }
-    		  }
-
-//					System.out.println(sstart+">"+send+":"+loff);
-
-      		if (sstart != send) // found a match
-	      	{ sstart = test;
-  	    		while (sstart >= start &&
-    	    					tail.charAt(roff) ==
-      	      	      ((HTMLEntity) HTMLEntity.entities.elementAt(sstart)).name.charAt(loff))
-	        	{ sstart --;
-		        }
-  		      sstart ++;
-
-    		    send = test + 1;
-      		  while (send < end &&
-        						tail.charAt(roff) ==
-          		        ((HTMLEntity) HTMLEntity.entities.elementAt(send)).name.charAt(loff))
-		      	{ send ++;
-  		      }
+        end   = HTMLEntity.entities.size();
+        loff  = 0;
+
+	while (startoff+1+loff < tail.length() && start != end)
+	{ sstart = start;
+	  send   = end;
+          test	 = (sstart + send) >> 1;
+
+	  matched	= false;
+		      
+	  roff	= startoff + 1 + loff;
+
+	  while (sstart != send)
+	  { test = (sstart + send) >> 1;
+
+	    if (tail.charAt(roff) < ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.charAt(loff))
+	    { send = test;
+	    }
+	    else if (tail.charAt(roff) > ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.charAt(loff))
+	    { sstart	= test + 1;
+	    }
+	    else
+	    { break;
+	    }
+	  }
+
+	  //					System.out.println(sstart+">"+send+":"+loff);
+
+	  if (sstart != send) // found a match
+	  { sstart = test;
+	    while (sstart >= start &&
+		   tail.charAt(roff) ==
+		   ((HTMLEntity) HTMLEntity.entities.elementAt(sstart)).name.charAt(loff))
+	    { sstart --;
+	    }
+	    sstart ++;
+
+	    send = test + 1;
+	    while (send < end &&
+		   tail.charAt(roff) ==
+		   ((HTMLEntity) HTMLEntity.entities.elementAt(send)).name.charAt(loff))
+	    { send ++;
+	    }
 
 //						System.out.println(sstart+"!"+send+":"+loff);
 
-    		    start = sstart;
-      		  end	= send;
-	      	}
-	  	    else
-  	  	  { loff	= 0;
-    	    	reply.append(tail.substring(0, startoff+1));
-      	  	break;
-      		}
+	    start = sstart;
+	    end	= send;
+	  }
+	  else
+	  { loff	= 0;
+	    reply.append(tail.substring(0, startoff+1));
+	    break;
+	  }
 
 //					System.out.println(start+">"+end+":"+loff);
-
-		      loff ++;
-  		    if (end == start + 1 &&
-    		      ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.length() == loff)
-      		{ reply.append(tail.substring(0, startoff));
-        		reply.append(((HTMLEntity) HTMLEntity.entities.elementAt(test)).toString());
-          	if (roff < tail.length() - 1 && tail.charAt(roff+1) == ';')
-	          { loff ++;
-  	        }
-    	      break;
-	    	  }
-	  	  }
+	  
+	  loff ++;
+	  if (end == start + 1 &&
+	      ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.length() == loff)
+	  { reply.append(tail.substring(0, startoff));
+	    reply.append(((HTMLEntity) HTMLEntity.entities.elementAt(test)).toString());
+	    if (roff < tail.length() - 1 && tail.charAt(roff+1) == ';')
+	    { loff ++;
+	    }
+	    break;
+	  }
+	}
       }
 
       tail = tail.substring(startoff + 1 + loff);
     } while (tail != null && tail.length() > 0);
-
+    
     if (tail != null)
     { reply.append(tail);
@@ -335,12 +335,12 @@
   }
 
-	public static void main(String args[])
-	{ String reply;
-
-		getEntities();
-
-		reply = decodeText(args[0]);
-		System.out.println(reply);
-	}
+  public static void main(String args[])
+  { String reply;
+
+    getEntities();
+    
+    reply = decodeText(args[0]);
+    System.out.println(reply);
+  }
 }
 
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLObject.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLObject.java	(revision 6285)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLObject.java	(revision 6285)
@@ -0,0 +1,5 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public interface HTMLObject
+{ public String getHTMLType();
+}
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLTag.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLTag.java	(revision 6284)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLTag.java	(revision 6285)
@@ -1,27 +1,33 @@
 package org.greenstone.gsdl3.gs3build.util;
 
-public class HTMLTag
-{ String 	tagtext;
-	String	name;
-	int			docpos;
-	int			endpos;
-
-	public HTMLTag(String tagtext, int docpos, int endpos)
-	{	this.tagtext	= tagtext;
-		this.name			= null;
-		this.docpos		= docpos;
-		if (this.docpos < 0)
-		{ this.endpos = -1;
-		}
-		else
-		{	this.endpos		= endpos;
-		}
-	}
-
-	public HTMLTag(String tagtext)
-	{ this.tagtext 	= tagtext;
-		this.docpos		= -1;
-		this.name			= null;
-	}
+public class HTMLTag implements HTMLObject
+{ String tagtext;
+  String name;
+  int	 docpos;
+  int    endpos;
+
+  public static final String HTML_ELEMENT_TYPE = "Element";
+
+  public HTMLTag(String tagtext, int docpos, int endpos)
+  { this.tagtext = tagtext;
+    this.name    = null;
+    this.docpos  = docpos;
+    if (this.docpos < 0)
+    { this.endpos = -1;
+    }
+    else
+    { this.endpos = endpos;
+    }
+  }
+
+  public HTMLTag(String tagtext)
+  { this.tagtext 	= tagtext;
+    this.docpos		= -1;
+    this.name			= null;
+  }
+
+  public String getHTMLType()
+  { return HTML_ELEMENT_TYPE;
+  }
 
 	public HTMLTag endTag()
Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLTidy.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLTidy.java	(revision 6285)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/util/HTMLTidy.java	(revision 6285)
@@ -0,0 +1,174 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.io.File;
+import java.io.FileReader;
+
+import java.net.URL;
+
+import org.w3c.dom.*;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+import org.greenstone.gsdl3.gs3build.doctypes.GMLDocument;
+
+public class HTMLTidy extends DefaultHandler
+{
+  String label;
+  File   file;
+  StringBuffer value;
+  boolean inElement;
+  boolean accumulate;
+  Document document;
+  Element  currentElement;
+  Element root;
+
+  class HTMLCommentHandler implements LexicalHandler
+  {
+    HTMLTidy parent;
+
+    HTMLCommentHandler(HTMLTidy tidier)
+    { this.parent = tidier;
+    }
+
+    public void comment(char ch[], int start, int length)
+    { String comment = new String(ch, start, length);
+
+      parent.comment(comment);
+    }
+
+    public void endCDATA()
+    {
+    }
+
+    public void endDTD()
+    {
+    }
+
+    public void endEntity(String name)
+    {
+    }
+
+    public void startCDATA()
+    {
+    }
+
+    public void startDTD(String name, String publicId, String systemId)
+    {
+    }
+
+    public void startEntity(String name)
+    {
+    }
+  }
+
+  public HTMLTidy(URL url)
+  { // TODO: complete
+  }
+
+  public HTMLTidy(File file)
+  { this.file = null;
+    this.label = null;
+    this.value = null;
+
+    this.document = new org.apache.html.dom.HTMLDocumentImpl();
+
+    this.currentElement = this.document.getDocumentElement();
+    this.root = this.currentElement;
+
+    try {
+      XMLReader handler  = new org.ccil.cowan.tagsoup.Parser();
+      HTMLCommentHandler commentHandler = new HTMLCommentHandler(this);
+      handler.setContentHandler(this);
+      handler.setProperty("http://xml.org/sax/properties/lexical-handler", commentHandler);
+      handler.parse(file.toString());
+    }
+    catch (java.io.IOException io)
+    {
+    }
+    catch (org.xml.sax.SAXException saxEx)
+    {
+      System.out.println(saxEx);
+    }
+  }
+
+  public void startElement(String URI, String localName, String qName, Attributes attributes)
+  { // System.out.println("Starting " + localName);
+  
+    if (localName.equals("html") == false) {
+      Element childElement = this.document.createElement(localName);
+      
+      this.currentElement.appendChild(childElement);
+      this.currentElement = childElement;
+
+      for (int a = 0; a < attributes.getLength(); a ++)
+      { String name = attributes.getLocalName(a);
+        String value = attributes.getValue(a);
+
+	childElement.setAttribute(name, value);
+      }
+    }
+  }
+
+  public void comment(String text)
+  {
+    Comment comment = document.createComment(text);
+    this.currentElement.appendChild(comment);
+  }
+
+  public void endElement(String URI, String localName, String qName)
+  { // System.out.println("Ending " + localName);
+
+    if (localName.equals("html")) {
+      return;
+    }
+
+    // TODO: check is the same name as current node
+    if (!this.currentElement.getTagName().equals(localName.toUpperCase())) {
+      // TODO: error handling
+      System.out.println("Bad end at " + localName + " " + this.currentElement.getTagName());
+      return;
+    }
+
+    this.currentElement = (Element) this.currentElement.getParentNode();
+  }
+
+  public void characters(char c[], int start, int length)
+  { String string = new String(c, start, length);
+    Node text_node = this.document.createTextNode(string);
+    this.currentElement.appendChild(text_node);
+  }
+
+  public void recursePrint(Element element, int indent)
+  {
+    for (int i = 0; i < indent; i++) {
+      System.out.print(" ");
+    }
+    System.out.println(element.toString());
+    for (int c = 0; c < element.getChildNodes().getLength(); c ++)
+    { Node n = element.getChildNodes().item(c);
+
+      if (n.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+	Element e = (Element) n;
+	
+	this.recursePrint(e, indent+2);
+      }
+    }
+  }
+
+  public Document getDocument()
+  { 
+    //    this.recursePrint(this.root, 0);
+    //    System.out.println(this.document.toString());
+    //    System.out.println(this.root);
+    return this.document;
+  }
+}
