function create_element(elem)
{
	if (elem.element == 'text')
		return document.createTextNode(elem.text || '');

	var dom_element = document.createElement(elem.element);

	/* Properties we should expect:
	 *   NAME         TYPE      APPLIES TO       HTML ATTRIBUTE
	 *---------------------------------------------------------------
	 *   cssclass     string    [*]              class
	 *   id           string    [*]
	 *   onclick      string    [*]
	 *                function
	 *   ondblclick   string    [*]
	 *                function
	 *   onmouseout   string    [*]
	 *                function
	 *   onmouseover  string    [*]
	 *                function
	 *   style        string    [*]
	 *   title        string    [*]

	 *   href         string    [a]

	 *   src          string    [img]
	 *   alt          string    [img]

	 *   value        string    [input, option]
	 *   name         string    [input]

	 *   type         string    [input]
	 *   checked      bool      [input]
	 *   readonly     bool      [input]
	 *   disabled     bool      [input, select]

	 *   rows         int       [textarea]
	 *   cols         int       [textarea]

	 *   selected     bool      [option]

	 *   colspan      int       [td]
	 *   rowspan      int       [td]

	 *   cellspacing  int       [table]

	 *   assoc        string    [label]          for

	 *   label        string    [optgroup]

	 *   onchange     string    [select]
	 *                function

	 *   onkeydown    string    [*]
	 *                function

	 *   onkeyup      string    [*]
	 *                function

	 *   onfocus      string    [*]
                    function

	 *   onblur       string    [*]
	 *                function  [*]

	 *   action       string    [form]
	 *   method       string    [form]
	 *   onsubmit     string    [form]
	 *                function

	 *   text         string    [*]              <text content>

	 *   html         string    [*]              <html content> (innerHTML)
	 */

	for (var prop in elem) {
		if (/^data-/.test(prop)) {
			dom_element.setAttribute(prop, elem[prop]);
			continue;
		}

		switch (prop)
		{
			// Skip things which are handled separately
			case 'element':
			case 'children':
				break;

			case 'child':
				dom_element.appendChild(create_element(elem.child));
				break;

			case 'id':
				dom_element.setAttribute('id', elem.id);
				break;

			case 'cssclass':
				dom_element.setAttribute('class', elem.cssclass);
				break;

			case 'href':
				dom_element.setAttribute('href', elem.href);
				break;

			case 'src':
				dom_element.setAttribute('src', elem.src);
				break;

			case 'action':
				dom_element.setAttribute('action', elem.action);
				break;

			case 'value':
				dom_element.setAttribute('value', elem.value);
				break;

			case 'name':
				dom_element.setAttribute('name', elem.name);
				break;

			case 'type':
				dom_element.setAttribute('type', elem.type);
				break;

			case 'style':
				dom_element.setAttribute('style', elem.style);
				break;

			case 'selected':
				if (elem.selected)
					dom_element.setAttribute('selected', 'selected');
				break;

			case 'checked':
				if (elem.checked)
					dom_element.setAttribute('checked', 'checked');
				break;

			case 'title':
				dom_element.setAttribute('title', elem.title);
				break;

			case 'alt':
				dom_element.setAttribute('alt', elem.alt);
				break;

			case 'readonly':
			case 'ro':
				if (elem.readonly || elem.ro)
					dom_element.setAttribute('readonly', 'readonly');
				break;

			case 'disabled':
				if (elem.disabled)
					dom_element.setAttribute('disabled', 'disabled');
				break;

			case 'rows':
				dom_element.setAttribute('rows', elem.rows);
				break;

			case 'cols':
				dom_element.setAttribute('cols', elem.cols);
				break;

			case 'colspan':
				dom_element.setAttribute('colspan', elem.colspan);
				break;

			case 'rowspan':
				dom_element.setAttribute('rowspan', elem.rowspan);
				break;

			case 'cellspacing':
				dom_element.setAttribute('cellspacing', elem.cellspacing);
				break;

			case 'assoc':
				dom_element.setAttribute('for', elem.assoc);
				break;

			case 'label':
				dom_element.setAttribute('label', elem.label);
				break;

			case 'method':
				dom_element.setAttribute('method', elem.method);
				break;

			case 'onchange':
				if (typeof(elem.onchange) == 'function')
					dom_element.onchange = elem.onchange;
				else
					dom_element.setAttribute('onchange', elem.onchange);
				break;

			case 'onkeydown':
				if (typeof(elem.onkeydown) == 'function')
					dom_element.onkeydown = elem.onkeydown;
				else
					dom_element.setAttribute('onkeydown', elem.onkeydown);
				break;

			case 'onkeyup':
				if (typeof(elem.onkeyup) == 'function')
					dom_element.onkeyup = elem.onkeyup;
				else
					dom_element.setAttribute('onkeyup', elem.onkeyup);
				break;

			case 'onclick':
				if (typeof(elem.onclick) == 'function')
					dom_element.onclick = elem.onclick;
				else
					dom_element.setAttribute('onclick', elem.onclick);
				break;

			case 'ondblclick':
				dom_element.onclick = elem.onclick;
				break;

			case 'onfocus':
				if (typeof(elem.onfocus) == 'function')
					dom_element.onfocus = elem.onfocus;
				else
					dom_element.setAttribute('onfocus', elem.onfocus);
				break;

			case 'onblur':
				if (typeof(elem.onblur) == 'function') 
					dom_element.onblur = elem.onblur;
				else
					dom_element.setAttribute('onblur', elem.onblur);
				break;

			case 'onsubmit':
				if (typeof(elem.onsubmit) == 'function')
					dom_element.onsubmit = elem.onsubmit;
				else
					dom_element.setAttribute('onsubmit', elem.onsubmit);
				break;

			case 'onmouseover':
				if (typeof(elem.onmouseover) == 'function')
					dom_element.onmouseover = elem.onmouseover;
				else
					dom_element.setAttribute('onmouseover', elem.onmouseover);
				break;

			case 'onmouseout':
				if (typeof(elem.onmouseout) == 'function')
					dom_element.onmouseout = elem.onmouseout;
				else
					dom_element.setAttribute('onmouseout', elem.onmouseout);
				break;

			case 'text':
				if (elem.text)
					dom_element.appendChild(document.createTextNode(elem.text));
				break;

			case 'html':
				dom_element.innerHTML = elem.html;
				break;

			default:
				throw "Unrecognized property: " + prop;
		}
	}

	if (elem.children) {
		for (var i = 0; i < elem.children.length; i++) {
			if (elem.children[i]) {
				dom_element.appendChild(create_element(elem.children[i]));
			}
		}
	}

	return dom_element;
}

