function XMLTreeTable(xmlid) {
  var mozilla = navigator.appName == "Netscape";

  function XMLTreeNode(row) {
    this.row = row;
    this.hidden = false;
    this.children = null;
    this.addChild = function(node) {
      if(this.children == null) this.children = new Array();
      this.children[this.children.length] = node;
      node.parent = this;
    }
    this.hasChildren = function() {
      return this.children != null;
    }
    this.canShow = function() {
      if(this.parent == null) return true;
      if(this.parent.hidden) return false;
      return this.parent.canShow();
    }
  }

  var nodes = new Array();
  var rootNode;

  function init() {
    var xmltable = document.getElementById(xmlid);
    var rows = xmltable.getElementsByTagName('TR');
    for(var i=0;i<rows.length;i++) {
      var row = rows[i];
      if(!row.id) continue;
      var node = new XMLTreeNode(row);
      nodes[row.id] = node;
      if(rootNode == null) {
        rootNode = node;
	continue;
      }
      var ind = row.id.lastIndexOf('#');
      if(ind < 0)
        ind = row.id.lastIndexOf('/');
      if(ind < 0) continue;
      var pid = row.id.substr(0,ind);
      var pnode = nodes[pid];
      pnode.addChild(node);
    }
  }

  init();

  function getParent(node,name) {
    node = node.parentNode;
    while(node.nodeName != name)
      node = node.parentNode;
    return node;
  }

this.ra = function(event) {
  var source = getEventSource(event);
  var id = getParent(source,'TR').id;
  var node = nodes[id];
  rhs(source,node,!node.hidden,true,false);
  return false;
}

function setState(node,hide) {
  var links = node.row.getElementsByTagName('A');
  if(links.length == 0) return;
  if(links[0].innerHTML == '-' || links[0].innerHTML == '+') {
    node.hidden = hide;
    links[0].innerHTML = hide ? '+' : '-';
  }
}

function rhs(source,node,hide,self,recursive,cb) {
  if(self) {
    node.hidden = hide;
    source.innerHTML = hide ? '+' : '-';
  }
  function processNode(node,hide,depth,self,recursive) {
    if(depth > 0) {
      if(hide) {
        if(self || depth > 1)
          if(node.row.style.display != 'none')
            node.row.style.display = 'none';
      }
      else {
        if(node.canShow()) {
          if(node.row.style.display == 'none')
            node.row.style.display = (mozilla ? 'table-row' : 'block');
	}
      }
      if(recursive) setState(node,hide);
    }
    if(!node.hasChildren()) return;
    var children = node.children;
    for(var i=0;i<children.length;i++)
      processNode(children[i],hide,depth+1,!self?depth>0:true,recursive);
  }
  processNode(node,hide,0,self,recursive);
}

this.collapseAll = function(cbf) {
  if(rootNode == null) return;
  var links = rootNode.row.getElementsByTagName('A');
  rhs(links[0],rootNode,true,false,true,cbf);
}

}
