function xmlHelper () {
  this.loadXml = function (dname){
    var xmlDoc;
    if (window.XMLHttpRequest) {
      xmlDoc=new window.XMLHttpRequest();
      xmlDoc.open("GET",dname,false);
      xmlDoc.send("");

      return xmlDoc.responseXML;
    }
    // IE 5 and IE 6
    else if (ActiveXObject("Microsoft.XMLDOM")) {
      xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async=false;
      xmlDoc.load(dname);
      return xmlDoc;
    }
    alert("Error loading document");
    return null;
  }
}


function xmlPtr(data){
  this.d=data;
}

xmlPtr.prototype={
  text:function() { 
    if (!_isFF) return this.d.xml; 
    var x = new XMLSerializer();   
    return x.serializeToString(this.d); 
  },  
  // get node attribute value
  getA:function(name){
    return this.d.getAttribute(name); 
  },
  // get first child node with specified tag
  getFC:function(tagName){
    var nodeSet = this.d.childNodes;
    for (var i = 0; i < nodeSet.length; i++) { 
      if (nodeSet[i].nodeType == 1 && (tagName == undefined || nodeSet[i].tagName==tagName))
        return new xmlPtr(nodeSet[i]);
    }
  },
  // get next sibling node with specified tag
  getNS:function(tagName){
    var ns = this.d.nextSibling;
    while (ns != undefined && ns.nodeType != 1)
      ns = ns.nextSibling;
    return ns != undefined  ? new xmlPtr(ns) : undefined;
  },
  // get node text content
  getT:function(){
    return this.d.textContent;
  },
  // get node tag name
  getTag:function(){
    return this.d.tagName;
  },
  // has children
  hasC:function () {
    var nodeSet = this.d.childNodes;
      for (var i = 0; i < nodeSet.length; i++) 
        if (nodeSet[i].nodeType == 1)
          return true;
    return false;
  },
  // add new attribute
  addA:function(n,v) {
    this.d.setAttribute(n,v);
  },
  // add new child node from t=tag name 
  addCNT:function(t){
    var tagNode = _xd.d.createElement(t);
    this.d.appendChild(tagNode);
    return new xmlPtr(tagNode);
  },
  // add new sibling node from t=tag name 
  addSNT:function(t){
    var tagNode = _xd.d.createElement(t);
    this.d.parentNode.appendChild(tagNode);
    return new xmlPtr(tagNode);
  },
  // add new sibling node from t=tag name 
  addCN:function(e){
    this.d.appendChild(e);
    return new xmlPtr(e);
  },
  // add new sibling node from t=tag name 
  addSN:function(e){
    this.d.parentNode.appendChild(e);
    return new xmlPtr(e);
  },
  // output xml as string
  toString:function() {
    var result = '';
    var ns = this.d;
    while (ns != undefined)
    {
      if (ns.nodeType == 1)
      {
        result += '<' + ns.tagName;
        for (var i = 0; i < ns.attributes.length; i++) { 
          if (i == 0) result += ' ';
          var a = ns.attributes[i];
            result += a.name + '="' + a.value.replace(/"/g, '["]').replace(/</g, '[<]').replace(/>/g, '[>]').replace(/&/g, '[amp;]') + '" ';
        }
        result += '>';
        var xp = new xmlPtr(ns);
        if (xp.hasC())
          result += '\n' + xp.getFC().toString();
        else
          result +=  xp.getT();
        result += '</' + ns.tagName + '>' + '\n';

      }
      ns = ns.nextSibling;
    }
    return result;
  }
}

function xmlDocPtr(rootTag){
  this.d = undefined;
  this.ptr = undefined;

  this.init = function () {
   parser=new DOMParser();
   this.d=parser.parseFromString("<" + rootTag + "/>","text/xml");
   this.ptr = this.getPtr();
  }
  this.getPtr = function () {
    return new xmlPtr(this.d);
  }
  this.replaceRoot = function(rootTag) {
    this.d = _xd.d.createElement(rootTag);
    this.ptr = this.getPtr();
  }
  this.init();
}

var _xd = new xmlDocPtr('root'); 

