//XMLParser.js
//Kitchen-sink parser for GuiLib and Freeance Config

function XMLParser(xmlResponseDoc)
{
  this.xmlDoc = xmlResponseDoc||null;   // XmlDocument
  if (this.xmlDoc == null)
  return (this);
};

XMLParser.prototype.setResponseByDoc = function(xmlResponseDoc)
{
  if (!xmlResponseDoc) return;
  this.xmlDoc = xmlResponseDoc;
};

XMLParser.prototype.setResponseByStr = function(XMLParserStr)
{
  if (!XMLParserStr) return;
  if (this.xmlDoc == null)
    this.xmlDoc = XmlDocument.create();
  this.xmlDoc.loadXML(XMLParserStr);
};

/**********************************************************
                      Main Parser
***********************************************************/

XMLParser.prototype.getObject = function()
{
  if (this.xmlDoc == null)
    return null;
  if (arguments.length > 0)
  {
    switch (arguments[0])
    {
      case 'mapConfig':
        return (this.parseMapConfig(this.xmlDoc.getElementsByTagName("map").item(0)));
        break;
      case 'templateConfig':
        return (this.parseTemplateConfig(this.xmlDoc.getElementsByTagName("templates").item(0)));
        break;
      case 'applicationConfig':
        return (this.parseApplicationConfig(this.xmlDoc.getElementsByTagName("applicationConfig").item(0)));
        break;
      case 'queryConfig':
        return (this.getObjectRecurse(this.xmlDoc.getElementsByTagName("queryConfig").item(0)));
        break;
      case 'emailConfig':
        return (this.parseEMailConfig(this.xmlDoc.getElementsByTagName(arguments[0]).item(0)));
        break;
      case 'measureConfig':
        return (this.parseMeasureConfig(this.xmlDoc.getElementsByTagName(arguments[0]).item(0)));
        break;
      case 'extensionConfig':
        return(this.parseExtensionConfig(this.xmlDoc.getElementsByTagName('extensionConfig').item(0)));
        break;
      case 'templateDefinitions':
        return (this.parseTemplateDefinitions(this.xmlDoc.getElementsByTagName('templateDefinitions').item(0)));
        break;
      default:
        return (this.getObjectRecurse(this.xmlDoc.getElementsByTagName("value").item(0)));
    }
  }
  else
    return (this.getObjectRecurse(this.xmlDoc.getElementsByTagName("value").item(0)));
};

XMLParser.prototype.getObjectRecurse = function(newNode)  //(theNode,<widgetParent|mapConfig>)
{
  var theNode = newNode;
  var i = 0;
  if (this.xmlDoc == null) return null;
  switch (theNode.nodeName)
  {
    case 'left':
    case 'top':
    case 'zpos':
    case 'width':
    case 'height':
    case 'visibility':
    case 'style':
    case 'label':
    case 'imageName':
    case 'partOfExtension':
    case 'tooltip':
    case 'onTooltip':
    case 'offTooltip':
    case 'buttonState':
    case 'useRollover':
    case 'enableDrag':
    case 'groupName':
    case 'imageSource':
    case 'scaleImage':
    case 'orientation':
    case 'caption':
    case 'setActive':
    case 'useScroll':
    case 'pageType':
    case 'usePageControl':
    case 'color':
    case 'font':
    case 'fontSize':
    case 'valueFontSize':
    case 'cellSpacing':
      if (this.__helper__getNextElementNamedChildNode(theNode,0,"value")!= -1)
        return (this.getObjectRecurse(theNode.childNodes[this.__helper__getNextElementNamedChildNode(theNode,0,"value")]));
      else
      {
        return null;
      }
      break;    
    case 'value':
      return(this.getObjectRecurse(theNode.childNodes[this.__helper__getNextElementChildNode(theNode,0)]));
      break;
    case 'activeTheme':
    case 'themeGroupMember':
    case 'resultTemplate':
    case 'fieldList':
    case 'themeName':
    case 'slaveType':
    case 'styleSheet':
    case 'resourceId':
    case 'mapId':
    case 'string':
      return(this.decodeSTRING(theNode));
      break;
    case 'expression':
      return (this.parseExpression(theNode));
      break;
    case 'queryConfig':
      return this.parseQueryConfig(theNode);
      break;
    case 'definedQuery':
      return (this.parseDefinedQuery(theNode));
      break;
    case 'queryGroup':
      return (this.parseQueryGroup(theNode));
      break;
    case 'tolerance':
    case 'maxSelect':
    case 'limit':
    case 'i4':
    case 'int':
      for (i=0; i<theNode.childNodes.length; i++)
        this.getObjectRecurse(theNode.childNodes[i]);
      return(this.decodeINT(theNode));
      break;
    case 'boolean':
      return(this.decodeBOOLEAN(theNode));
      break;
    case 'boundBoxPercentMin':
    case 'double':
      for (i=0; i<theNode.childNodes.length; i++)
        this.getObjectRecurse(theNode.childNodes[i]);
      return(this.decodeDOUBLE(theNode));
      break;
    case '#text':
    case '#comment':
      break;
    case 'dateTime.iso8601': return(this.decodeDATETIME(theNode)); break;
    case 'base64': return(this.decodeBASE64(theNode)); break;
    case 'array': return(this.decodeARRAY(theNode)); break;
    case 'struct': return(this.decodeSTRUCT(theNode)); break;
    default: alert('unknown node type: '+theNode.nodeName); break;
  }
};

/**********************************************************
              Generic data handling
***********************************************************/
XMLParser.decodeSTRING = function(theNode)
{
  if(theNode)
    if (theNode.childNodes.length > 0) // has textNode
      return (theNode.childNodes[0].nodeValue);
  return ('');
};
XMLParser.prototype.decodeSTRING = XMLParser.decodeSTRING;
XMLParser.prototype.decodeINT = XMLParser.decodeINT = function(theNode) // leaf node
{ 
  var theSTRING = XMLParser.decodeSTRING(theNode);
  return (parseInt(theSTRING,10));
};

XMLParser.prototype.decodeBOOLEAN = XMLParser.decodeBOOLEAN = function(theNode)
{
  var theSTRING = this.decodeSTRING(theNode);
  return (parseInt(theSTRING) == 1);
};

XMLParser.prototype.decodeDOUBLE = XMLParser.decodeDOUBLE = function(theNode)
{
  var theSTRING = this.decodeSTRING(theNode);
  return (parseFloat(theSTRING));
};

XMLParser.prototype.decodeDATETIME = function(theNode) {};
XMLParser.prototype.decodeBASE64 = function(theNode) {};

/**********************************************************
                  Helper Functions
***********************************************************/

XMLParser.prototype.getNextChildNodeIndex = 
XMLParser.prototype.__helper__getNextElementChildNode = 
XMLParser.getNextElementChildNode = function(aNode,firstpos)
{
  var foundpos = -1;
  for (var lcv=firstpos;(lcv < aNode.childNodes.length) && (foundpos == -1); lcv++)
    if (aNode.childNodes[lcv].nodeType == 1)
      foundpos = lcv;
  return (foundpos);
};

XMLParser.prototype.getNextNamedChildNodeIndex = 
XMLParser.prototype.getNextElementNamedChildNode = 
XMLParser.prototype.__helper__getNextElementNamedChildNode = 
XMLParser.getNextElementNamedChildNode = function(aNode,firstpos,nodeName)
{
  for (var lcv=firstpos;lcv < aNode.childNodes.length; lcv++)
    if ((aNode.childNodes[lcv].nodeType == 1) && (aNode.childNodes[lcv].nodeName == nodeName))
      return(lcv);
  return (-1);
};

XMLParser.prototype.getRemainingNamedChildNodes =
XMLParser.prototype.__helper__getRemainingNextElementNamedChildNodes =
XMLParser.getRemainingNextElementNamedChildNodes = function(aNode,firstpos,nodeName)
{
  var nodeCollection = new Array();
  for (var lcv=firstpos;lcv < aNode.childNodes.length; lcv++)
    if ((aNode.childNodes[lcv].nodeType == 1) && (aNode.childNodes[lcv].nodeName == nodeName))
      nodeCollection[nodeCollection.length] = aNode.childNodes[lcv];
  return (nodeCollection);
};
/**********************************************************
          Freeance Config Parsing Functions
***********************************************************/
XMLParser.prototype.parseApplicationConfig = function(appNode)
{
  var customLayoutIndex = this.__helper__getNextElementNamedChildNode(appNode,0,"customOptions");
  var mapUnitIndex = this.__helper__getNextElementNamedChildNode(appNode,0,"mapUnits");
  var vmapHeightIndex = this.__helper__getNextElementNamedChildNode(appNode,0,"vmapHeight");
  var nodeIndex = this.__helper__getNextElementNamedChildNode(appNode,0,"userScripts");
  var clientType = ((this.__helper__getNextElementNamedChildNode(appNode,0,"clientType")!=-1)?(this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"clientType")])):('LandRecords'));
  var appConfig = {
    id: this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"applicationId")]),
    organization: this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"organization")]),
    title: this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"title")]),
    administrator: this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"administrator")]),
    adminEmail: this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"adminEmail")]),
    clientType: clientType,
    lastSavedBy: ((this.__helper__getNextElementNamedChildNode(appNode,0,"lastSavedBy")!=-1)?(this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"lastSavedBy")])):('2.3.1')),  //major, minor, patch level
    stylesheet: ((this.__helper__getNextElementNamedChildNode(appNode,0,"stylesheet")!=-1)?(this.decodeSTRING(appNode.childNodes[this.__helper__getNextElementNamedChildNode(appNode,0,"stylesheet")])):('Default')),
    customConfig: ((customLayoutIndex!=-1)?(this.parseApplicationCustomOptions(appNode.childNodes[customLayoutIndex],clientType)):(null)),
    mapUnits: ((mapUnitIndex > -1)?(this.decodeSTRING(appNode.childNodes[mapUnitIndex])):('FT')),
    vmapHeight: ((vmapHeightIndex > -1)?(this.decodeINT(appNode.childNodes[vmapHeightIndex])):(100)),
    userScripts: (nodeIndex==-1)?(Array()):(this.parseUserScripts(appNode.childNodes[nodeIndex]))
  }
  return appConfig;
};

XMLParser.prototype.parseUserScripts = function(parentNode)
{
  var config = [];
  var scriptNodes = parentNode.getElementsByTagName('scriptfile');
  for (var i=0;i<scriptNodes.length;i++)
    config.push(scriptNodes[i].getAttribute('url'));
  return config;
};

XMLParser.prototype.parseApplicationCustomOptions = function (customNode, clientType)
{
  var customConfig = null;
  switch (clientType)
  {
    case 'PublicAccess1':
      return this.parsePublicAccessCustomOptions(customNode);
      break;
    case 'PublicKiosk1':
      return this.parsePIKCustomOptions(customNode);
      break;
  }
};

XMLParser.prototype.parsePublicAccessCustomOptions = function (customNode)
{
  var customConfig = new Object;
  customConfig.pageHeaderHeight = this.decodeINT(customNode.childNodes[this.__helper__getNextElementNamedChildNode(customNode,0,"pageHeaderHeight")]);
  customConfig.rightPanelWidth = this.decodeINT(customNode.childNodes[this.__helper__getNextElementNamedChildNode(customNode,0,"rightPanelWidth")]);
  customConfig.mapToolOptionHeight = this.decodeINT(customNode.childNodes[this.__helper__getNextElementNamedChildNode(customNode,0,"mapToolOptionHeight")]);
  customConfig.vicinityMapWidthOpen = this.decodeINT(customNode.childNodes[this.__helper__getNextElementNamedChildNode(customNode,0,"vicinityMapWidthOpen")]);
  customConfig.homeLinkHeight =this.decodeINT(customNode.childNodes[this.__helper__getNextElementNamedChildNode(customNode,0,"homeLinkHeight")]);
  var nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"defaultActivePanel");
  customConfig.defaultActivePanel = (nodeIndex>-1)?(this.decodeSTRING(customNode.childNodes[nodeIndex])):('userIntro');
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"mapAutoRedraw");
  customConfig.mapAutoRedraw = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"clickDeselect");
  customConfig.clickDeselect = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"expandSearch");
  customConfig.expandSearch = (nodeIndex==-1)?(false):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"freezeTableHeader");
  customConfig.freezeTableHeader = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"customLegendURL");
  customConfig.customLegendURL = (nodeIndex==-1)?(''):(this.decodeSTRING(customNode.childNodes[nodeIndex]));
  return customConfig;
};

XMLParser.prototype.parsePIKCustomOptions = function (customNode)
{
  //get values for page customization....
  var customConfig = new Object;
  var nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"pageHeaderHeight");
  customConfig.pageHeaderHeight = (nodeIndex==-1)?(70):(this.decodeINT(customNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"leftPanelDisplay");
  customConfig.leftPanelDisplay = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"legendDisplay");
  customConfig.legendDisplay = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"legendEnable");
  customConfig.legendEnable = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"layerDisplay");
  customConfig.layerDisplay = (nodeIndex==-1)?(false):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"layerEnable");
  customConfig.layerEnable = (nodeIndex==-1)?(true):(this.decodeINT(customNode.childNodes[nodeIndex])==1);
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"resultPanelHeight");
  customConfig.resultPanelHeight = (nodeIndex==-1)?(50):(this.decodeINT(customNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"customPanelPosition");
  customConfig.customPanelPosition = (nodeIndex==-1)?(0):(this.decodeINT(customNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"customPanelTitle");
  customConfig.customPanelTitle = (nodeIndex==-1)?('Site Instructions'):(this.decodeSTRING(customNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(customNode,0,"customLegendURL");
  customConfig.customLegendURL = (nodeIndex==-1)?(''):(this.decodeSTRING(customNode.childNodes[nodeIndex]));
  return customConfig;
};


XMLParser.prototype.parseMeasureConfig = function(configNode)
{
  var config = null;
  if (configNode != null)
  {
    config = new Object();
    config.distanceMeasureUnits = this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'distanceMeasureUnits')]);
    config.distanceColor = this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'distanceColor')]);
    config.distanceThickness = this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'distanceThickness')]);
  }
  return (config);
};

XMLParser.prototype.parseEMailConfig = function(configNode)
{
  var config = null;
  if (configNode != null)
  {
    config = new Object();
    config.allowMapImages = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'allowMapImages')]) == 'true');
    config.allowSearchResults = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'allowSearchResults')]) == 'true');
    config.allowBufferResults = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'allowBufferResults')]) == 'true');
    config.allowSelectionResults = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'allowSelectionResults')]) == 'true');
    config.allowMessageBody = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'allowMessageBody')]) == 'true');
    config.allowFeedbackButton = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'allowFeedbackButton')]) == 'true');
    config.forceFeedbackMode = (this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'forceFeedbackMode')]) == 'true');
    config.mapImageHandle = this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'mapImageHandle')]);
    config.vmapImageHandle = this.decodeSTRING(configNode.childNodes[this.__helper__getNextElementNamedChildNode(configNode,0,'vmapImageHandle')]);
  }
  return (config);
};

XMLParser.prototype.parseExtensionConfig = function(extensionConfigNode)
{
  var extensions = new Object();
  var extensionNodes = extensionConfigNode.getElementsByTagName('extension');
  for(var lcv=0; lcv < extensionNodes.length;lcv++)
  {
    var extension = extensionNodes[lcv];
    var name = extension.getAttribute('name');
    var enabled = extension.getAttribute('enabled');
    var dynamicfile = extension.getAttribute('dynamicfile');
    var compressedfile = extension.getAttribute('compressedfile');
    var module=extension.getAttribute('module');
    extensions[name] = {
      enabled: (enabled == 'true')?true:false,
      dynamicfile: dynamicfile,
      compressedfile: compressedfile,
      module: module
    }
  }
  return(extensions);
};

XMLParser.prototype.parseTemplateConfig = function(templateRootNode)
{
  var templates = new Object();
  var htmlString = '';
  for (var templateIndex = this.__helper__getNextElementNamedChildNode(templateRootNode,0,"template");templateIndex!=-1;templateIndex=this.__helper__getNextElementNamedChildNode(templateRootNode,templateIndex+1,"template"))
  {
    for (var lcv=0;lcv < templateRootNode.childNodes[templateIndex].childNodes.length;lcv++)
    {
      if (templateRootNode.childNodes[templateIndex].childNodes.item(lcv).nodeType == 4)
        htmlString = templateRootNode.childNodes[templateIndex].childNodes.item(lcv).nodeValue;
    }
    templates[templateRootNode.childNodes[templateIndex].getAttribute("id")] = htmlString;
  }
  return templates;
};

XMLParser.prototype.parseMapConfig = function(mapNode)
{
  var mapConfig = new Object();
  mapConfig['id'] = mapNode.getAttribute("id");
  mapConfig["resourceId"] = this.getObjectRecurse(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"resourceId")]);
  mapConfig["imsHostname"] = this.decodeSTRING(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"imsHostname")]);
  mapConfig["previousStates"] = this.decodeINT(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"previousStates")]);
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"vicinityMap")!=-1)
    mapConfig['vmap'] = this.parseVMapConfig(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"vicinityMap")]);
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"themeDefinitions")!=-1)
    mapConfig['themes'] = this.parseThemeDefinitions(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"themeDefinitions")]);
  mapConfig["activeTheme"] = this.getObjectRecurse(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"activeTheme")]);
  
  var seamlessPanIdx=this.__helper__getNextElementNamedChildNode(mapNode,0,"seamlessPan");
  var seamlessPan = false;
  if(seamlessPanIdx!=-1)
    seamlessPan=(mapNode.childNodes[seamlessPanIdx].getAttribute('enabled')=='true');
  mapConfig['seamlessPan'] = seamlessPan;
  mapConfig['themeGroups'] = this.parseThemeGroups(mapNode);
  
  var legendAttributeIndex = this.__helper__getNextElementNamedChildNode(mapNode,0,"legendAttributes");
  var legendIndex = this.__helper__getNextElementNamedChildNode(mapNode,0,"legend");
  if (legendAttributeIndex!=-1)
    mapConfig['legendAttributes'] = this.parseLegendAttributes(mapNode.childNodes[legendAttributeIndex]);
  else
    if(legendIndex>-1)
      mapConfig['legendAttributes'] = this.parseLegendAttributes(mapNode.childNodes[legendIndex]);
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"labelConfig")!=-1)
    mapConfig['labelConfig'] = this.parseLabelConfig(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"labelConfig")]);
  mapConfig['loginQuery'] = null;
  
  mapConfig['printConfig'] = new Object();
  var printConfigTags = this.__helper__getRemainingNextElementNamedChildNodes(mapNode,0,"printConfig");
  if (printConfigTags.length > 0)
    alert('This client application has a print configuration using the old HTML printing engine.\nA new print configuration will need created using the new PDF Print Templates in order for printing to function.');
  
  var printConfigTags = this.__helper__getRemainingNextElementNamedChildNodes(mapNode,0,"pdfPrintConfig");
  if (printConfigTags.length > 0){
    mapConfig.printConfig = this.parsePdfPrintConfig(printConfigTags[0]);
  }
  else{
    mapConfig.printConfig = new Object;
    mapConfig.printConfig.templates = new Array;
    mapConfig.printConfig.defaultTemplate = -1;
  }
  //Configure the CSV export system
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"exportConfig")!=-1)
    mapConfig['exportConfig'] = this.parseMapExportConfig(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"exportConfig")]);

  //Capture any geocode extension data
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"geocodeConfig")!=-1)
    mapConfig['geocodeConfig'] = this.parseGeocodeConfig(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"geocodeConfig")]);
  else
    mapConfig['geocodeConfig'] = null;

  //parse theme sets
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"mapSchemeDefinitions")!=-1)
  {
    var mapSchemeConfigNode = mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"mapSchemeDefinitions")];
    var defaultMapSchemeNode = mapSchemeConfigNode.childNodes[this.__helper__getNextElementNamedChildNode(mapSchemeConfigNode,0,"defaultScheme")];
    mapConfig['mapSchemeConfig'] = this.parseMapSchemeConfig(mapSchemeConfigNode);
  }
  else
  {
    mapConfig['mapSchemeConfig'] = null;
  }
  if (this.__helper__getNextElementNamedChildNode(mapNode,0,"scalebar")!=-1)
  {
    var scalebarConfigNode = mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"scalebar")];
    mapConfig['scalebarConfig'] = this.parseScalebarConfig(scalebarConfigNode);
  }
  else
  {
    mapConfig['scalebarConfig'] = null;
  }
  
  var proxSearchNodes = mapNode.getElementsByTagName('proximitySearchConfig');
  if (proxSearchNodes.length>0)
    mapConfig['proximitySearchConfig'] = this.parseProximitySearchConfig(proxSearchNodes[0]);
  else
    mapConfig['proximitySearchConfig'] = new Array();

  var projectionId = 0;
  var projectionIdx = this.__helper__getNextElementNamedChildNode(mapNode,0,'projectionId');
  if(projectionIdx!=-1)
    projectionId=(mapNode.childNodes[projectionIdx].getAttribute('value')!=null)?(parseInt(mapNode.childNodes[projectionIdx].getAttribute('value'))):(this.decodeINT(mapNode.childNodes[projectionIdx]));
  mapConfig['projectionId']=projectionId;

  return mapConfig;
};




XMLParser.prototype.parseThemeGroups = function(mapNode)
{
  //land records clients use an older format, load old format if applicable
  var appConfig = this.getObject('applicationConfig');
  if(appConfig.clientType=='LandRecords')
    return this.parseThemeGroupDefinitions(mapNode.childNodes[this.__helper__getNextElementNamedChildNode(mapNode,0,"themeGroupDefinitions")]);
  //end landrecords fix
  var config = [];
  //determine type of layer control to use
  var themeGroupDefinitionNodes = mapNode.getElementsByTagName("themeGroupDefinitions");
  var layerControlNodes = mapNode.getElementsByTagName("layerControl");
  if (themeGroupDefinitionNodes.length>0) //pre-4.2 format, map to new structure
  {
    config = this.parseOldThemeGroups(themeGroupDefinitionNodes[0]);
  }
  else
  {
    //top-level is an implicit group
    for (var i=0;i<layerControlNodes[0].childNodes.length;i++)
      if (layerControlNodes[0].childNodes[i].nodeName=='groupItem')
        config.push(this.parseThemeGroupItem(layerControlNodes[0].childNodes[i]));
  }
  return config;
};


XMLParser.prototype.parseThemeGroupItem = function(groupItemNode){
  var config = {
    type:groupItemNode.getAttribute('type'),
    name:groupItemNode.getAttribute('name'),
    layerid:groupItemNode.getAttribute('layerid'),
    toggle:groupItemNode.getAttribute('toggle')=='on',
    children:[]
  };
  if(config.type=='group')
    for(var i=0;i<groupItemNode.childNodes.length;i++)
      if(groupItemNode.childNodes[i].nodeName=='groupItem')
        config.children.push(this.parseThemeGroupItem(groupItemNode.childNodes[i]));
  return config;
};


XMLParser.prototype.parseOldThemeGroups = function(parentNode)
{
  dprintf('loading pre-4.2 style theme groups');
  var config = [];
  var childconfig = [];
  var groupMemberNodes = null;
  var groupNodes = parentNode.getElementsByTagName('themeGroup');
  if (groupNodes.length==1) //treat as single group with label
  {
    config.push({
      type: 'label',
      name: this.decodeSTRING(groupNodes[0].getElementsByTagName('themeGroupName')[0]),
      toggle: false
    });
    groupMemberNodes = groupNodes[0].getElementsByTagName('themeGroupMember');
    for (var i=0;i<groupMemberNodes.length;i++){
      config.push({
        type:'layer',
        layerid:this.decodeSTRING(groupMemberNodes[i]),
        toggle:true
      });
    }
  }
  else
  {
    for (var i=0;i<groupNodes.length;i++){
      childconfig = [];
      groupMemberNodes = groupNodes[i].getElementsByTagName('themeGroupMember');
      for (var j=0;j<groupMemberNodes.length;j++){
        childconfig.push({
          type:'layer',
          layerid:this.decodeSTRING(groupMemberNodes[j]),
          name:'',
          toggle:true,
          children:[]
        });
      }
      config.push({
        type: 'group',
        name: this.decodeSTRING(groupNodes[i].getElementsByTagName('themeGroupName')[0]),
        layerid:'',
        toggle: false,
        children: childconfig
      });
    }
  }
  return config;  
};

XMLParser.prototype.parseScalebarConfig = function(newNode)
{
  var scalebarConfig = new Array();
  for (var levelIndex = this.__helper__getNextElementNamedChildNode(newNode,0,"level");levelIndex!=-1;levelIndex=this.__helper__getNextElementNamedChildNode(newNode,levelIndex+1,"level"))
  {
    var levelNode = newNode.childNodes[levelIndex];
    scalebarConfig[scalebarConfig.length] = [
      parseInt(levelNode.getAttribute('topUnit')),
      parseFloat(levelNode.getAttribute('topLength')),
      parseInt(levelNode.getAttribute('bottomUnit')),
      parseFloat(levelNode.getAttribute('bottomLength')),
      parseFloat(levelNode.getAttribute('mapWidth'))
    ];
  }
  return scalebarConfig;
};

XMLParser.prototype.parseGeocodeConfig = function(newNode)
{
  var geocodeConfig = new Object();
  var gcStyleNodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'gcStyle');
  geocodeConfig['gcStyle'] = ((gcStyleNodeIndex>-1)?(newNode.childNodes[gcStyleNodeIndex].getAttribute('style')):(null));
  geocodeConfig['gcTags'] = new Array();
  geocodeConfig['streetLayerID'] = newNode.getElementsByTagName('streetLayer')[0].getAttribute('id');
  var gcTags = newNode.getElementsByTagName('gcTag');
  for(var lcv=0;lcv < gcTags.length;lcv++)
    geocodeConfig.gcTags.push(gcTags[lcv].getAttribute('id'));
  var tags = newNode.getElementsByTagName('minScore');
  if (tags.length > 0)
    geocodeConfig['minScore'] = newNode.getElementsByTagName('minScore')[0].getAttribute('value');
  var tags = newNode.getElementsByTagName('maxCandidates');
  if (tags.length > 0)
    geocodeConfig['maxCandidates'] = parseInt(newNode.getElementsByTagName('maxCandidates')[0].getAttribute('value'));
  else
    geocodeConfig['maxCandidates'] = 2;
  var tags = newNode.getElementsByTagName('gisStylesheet');
  if (tags.length > 0)
    geocodeConfig['gisStylesheet'] = newNode.getElementsByTagName('gisStylesheet')[0].getAttribute('value');
  else
    geocodeConfig['gisStylesheet'] = 'General_PointStar';
  var paddingIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'gcPadding');
  if (paddingIndex != -1)
    geocodeConfig['padding'] = parseInt(newNode.childNodes[paddingIndex].getAttribute('distance'));
  else
    geocodeConfig['padding'] = 100;
  
  var nodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'indexAddressText');
  geocodeConfig.indexAddressText = (nodeIndex==-1)?('Search for an address and display its location on the map.'):(this.decodeSTRING(newNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'formAddressText');
  geocodeConfig.formAddressText = (nodeIndex==-1)?('Enter a street address on this form and click \'Run Search\' to show it on the map.'):(this.decodeSTRING(newNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'titleAddressText');
  geocodeConfig.titleAddressText = (nodeIndex==-1)?('Find Address'):(this.decodeSTRING(newNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'indexIntersectionText');
  geocodeConfig.indexIntersectionText = (nodeIndex==-1)?('Search for an intersection of two streets and display its location on the map.'):(this.decodeSTRING(newNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'formIntersectionText');
  geocodeConfig.formIntersectionText = (nodeIndex==-1)?('Enter the names of two streets and click \'Run Search\' to show the intersection on the map.'):(this.decodeSTRING(newNode.childNodes[nodeIndex]));
  nodeIndex = this.__helper__getNextElementNamedChildNode(newNode,0,'titleIntersectionText');
  geocodeConfig.titleIntersectionText = (nodeIndex==-1)?('Find Intersection'):(this.decodeSTRING(newNode.childNodes[nodeIndex]));
  
  return(geocodeConfig);
};


XMLParser.prototype.parseProximitySearchConfig = function(proximitySearchConfigNode)
{
  var config = new Array();
  var currentSearch = null;
  var proximitySearchNodes = proximitySearchConfigNode.getElementsByTagName('PROXIMITYSEARCH');
  var inputNodes = null;
  for (var i=0;i<proximitySearchNodes.length;i++)
  {
    currentSearch = {
      name:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('name')[0]),
      layerid:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('layerid')[0]),
      stylesheet:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('stylesheet')[0]),
      fieldlist:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('fieldlist')[0]),
      maxselect:this.decodeINT(proximitySearchNodes[i].getElementsByTagName('maxselect')[0]),
      inputValues:new Array(),
      descriptionHTML:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('descriptionHTML')[0]),
      formHTML:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('formHTML')[0]),
      whereclause:this.decodeSTRING(proximitySearchNodes[i].getElementsByTagName('whereclause')[0])
    };
    inputNodes = proximitySearchNodes[i].getElementsByTagName('input');
    if (inputNodes.length>0)
    for (var j=0;j<inputNodes.length;j++){
      currentSearch['inputValues'].push({
        type: inputNodes[j].getAttribute('type'),
        defaultValue: this.decodeSTRING(inputNodes[j].getElementsByTagName('defaultvalue')[0]),
        initialValue: this.decodeSTRING(inputNodes[j].getElementsByTagName('initialvalue')[0])
      });
    }
    config.push(currentSearch);
  }  
  return config;
};

XMLParser.prototype.parseMapSchemeConfig = function (mapSchemeConfigNode)
{
  var mapSchemeTags = this.__helper__getRemainingNextElementNamedChildNodes(mapSchemeConfigNode,0,"mapScheme");
  var defaultMapSchemeNode = mapSchemeConfigNode.childNodes[this.__helper__getNextElementNamedChildNode(mapSchemeConfigNode,0,"defaultScheme")];
  var mapSchemes = new Array;
  if (mapSchemeTags.length > 0)
  {
    for (var i = 0; i<mapSchemeTags.length; i++)
    {
      var currentMapSchemeId = parseInt(mapSchemeTags[i].getAttribute('id'));
      var themes = new Object;
      var themeTags = this.__helper__getRemainingNextElementNamedChildNodes(mapSchemeTags[i],0,"theme");
      for (var currentTheme = 0; currentTheme < themeTags.length; currentTheme++)
      {
        themeId = themeTags[currentTheme].getAttribute('id');
        themes[themeId] = {
          id: themeId,
          display: parseInt(themeTags[currentTheme].getAttribute('display')),
          legend: themeTags[currentTheme].getAttribute('legend')
        }
      };
      mapSchemes.push({
        id: currentMapSchemeId,
        name: this.decodeSTRING(mapSchemeTags[i].childNodes[this.__helper__getNextElementNamedChildNode(mapSchemeTags[i],0,"schemeName")]),
        themes: themes
      }
      );
    }
  };
  return {
    mapSchemes: mapSchemes,
    defaultMapScheme: parseInt(this.decodeSTRING(defaultMapSchemeNode))
  };
};


XMLParser.prototype.parseVMapConfig = function(vmapNode)
{
  var vmapConfig = new Object();
  var childNodeIndex = 0;
  vmapConfig['id'] = vmapNode.getAttribute("id");
  vmapConfig["resourceId"] = this.getObjectRecurse(vmapNode.childNodes[this.__helper__getNextElementNamedChildNode(vmapNode,0,"resourceId")]);
  vmapConfig["slaveType"] = this.getObjectRecurse(vmapNode.childNodes[this.__helper__getNextElementNamedChildNode(vmapNode,0,"slaveType")]);
  vmapConfig["boundBoxPercentMin"] = this.getObjectRecurse(vmapNode.childNodes[this.__helper__getNextElementNamedChildNode(vmapNode,0,"boundBoxPercentMin")]);
  vmapConfig["styleSheet"] = this.getObjectRecurse(vmapNode.childNodes[this.__helper__getNextElementNamedChildNode(vmapNode,0,"styleSheet")]);
  return vmapConfig;
};

XMLParser.prototype.parseThemeDefinitions = function (newNode)
{
  var themeDefinitions = new Object();
  for (themeIndex=this.__helper__getNextElementNamedChildNode(newNode,0,"theme");themeIndex!=-1;themeIndex=this.__helper__getNextElementNamedChildNode(newNode,themeIndex+1,"theme"))
  {
    themeDefinitions[newNode.childNodes[themeIndex].getAttribute("id")] = this.parseTheme(newNode.childNodes[themeIndex]);
  }
  return themeDefinitions;
};

XMLParser.prototype.parseTheme = function (themeNode)
{
  var themeAttributes = new Object;
  themeAttributes["id"] = themeNode.getAttribute("id");
  themeAttributes["hideTheme"] = themeNode.getAttribute("hideTheme");
  if (themeAttributes["hideTheme"] == null)
    themeAttributes["hideTheme"] = false;
  else
    themeAttributes["hideTheme"] = themeAttributes["hideTheme"] == 'true';
  themeAttributes["themeName"] = this.getObjectRecurse(themeNode.childNodes[this.__helper__getNextElementNamedChildNode(themeNode,0,"themeName")]);
  
  if (this.__helper__getNextElementNamedChildNode(themeNode,0,"themeFields")!=-1){
    themeAttributes["themeFields"]=this.decodeSTRING(themeNode.childNodes[this.__helper__getNextElementNamedChildNode(themeNode,0,"themeFields")]).parseJSON();
  }
  if (this.__helper__getNextElementNamedChildNode(themeNode,0,"selectOptions")!=-1)
    themeAttributes["selectOptions"] = this.parseThemeSelectOptions(themeNode.childNodes[this.__helper__getNextElementNamedChildNode(themeNode,0,"selectOptions")]);
  else
    themeAttributes["selectOptions"] = null;
  if (this.__helper__getNextElementNamedChildNode(themeNode,0,"bufferOptions")!=-1)
    themeAttributes["bufferOptions"] = this.parseThemeBufferOptions(themeNode.childNodes[this.__helper__getNextElementNamedChildNode(themeNode,0,"bufferOptions")]);
  else
    themeAttributes["bufferOptions"] = null;
  themeAttributes["visibility"] = false;
  themeAttributes["altLegends"] = new Array;

  var altLegends = themeNode.getElementsByTagName('altLegend');
  for(var lcv=0;lcv < altLegends.length;lcv++)
  {
    var currentNode = altLegends[lcv];
    themeAttributes["altLegends"][lcv] = new Object();
    themeAttributes["altLegends"][lcv].legendName = this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"legendName")]);
    themeAttributes["altLegends"][lcv].legendLabel = this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"legendLabel")]);
  }
  return themeAttributes;
};

XMLParser.prototype.parseThemeSelectOptions = function(newNode)
{
  var keyfieldTypeNodes = newNode.getElementsByTagName('keyFieldType');
  var zoomRatioNodes = newNode.getElementsByTagName('zoomExtentRatio');
  var sqlParamNodes = newNode.getElementsByTagName('sqlParams');
  return {
    styleSheet: this.decodeSTRING(newNode.getElementsByTagName("styleSheet")[0]),
    fieldList: this.decodeSTRING(newNode.getElementsByTagName("fieldList")[0]),
    limit: this.decodeINT(newNode.getElementsByTagName("limit")[0]),
    tolerance: this.decodeDOUBLE(newNode.getElementsByTagName("tolerance")[0]),
    idField: this.decodeSTRING(newNode.getElementsByTagName("idField")[0]),
    keyField: this.decodeSTRING(newNode.getElementsByTagName("keyField")[0]),
    keyFieldType: (keyfieldTypeNodes.length)?this.decodeINT(keyfieldTypeNodes[0]):12,
    zoomExtentRatio:(zoomRatioNodes.length)?this.decodeDOUBLE(zoomRatioNodes[0]):1.2,
    resultTemplate: this.decodeSTRING(newNode.getElementsByTagName("resultTemplate")[0]),
    sqlParams: (sqlParamNodes.length)?this.parseChainedQuerySqlParams(sqlParamNodes[0]):null
  };
};

XMLParser.prototype.parseChainedQuerySqlParams = function(sqlParamsNode)
{
  var sqlParams = [];
  var sqlParamNodeList = sqlParamsNode.getElementsByTagName('sqlParam');
  var currentParam = null;
  for(var lcv=0;lcv < sqlParamNodeList.length;lcv++)
  {
    var theNode = sqlParamNodeList[lcv];
    currentParam = {
      pdqIdentifier: this.decodeSTRING(theNode.getElementsByTagName("pdqIdentifier")[0]),
      fieldList: []
    };
    var fieldListNode = theNode.getElementsByTagName("fieldList")[0];
    var fieldNodeList = fieldListNode.getElementsByTagName('field');
    for(var fieldIndex=0;fieldIndex < fieldNodeList.length;fieldIndex++)
    {
      currentParam["fieldList"].push({
        fieldName: this.decodeSTRING(fieldNodeList[fieldIndex].getElementsByTagName("fieldName")[0]),
        pdqFieldName: this.decodeSTRING(fieldNodeList[fieldIndex].getElementsByTagName("pdqFieldName")[0])
      });
    }
    if (this.getNextNamedChildNodeIndex(theNode,0,"queryType") > -1)
    {
      currentParam["queryType"] = this.decodeSTRING(theNode.getElementsByTagName("queryType")[0]);
      currentParam["numRows"] = this.decodeINT(theNode.getElementsByTagName("numRows")[0]);
      currentParam["startAt"] = this.decodeINT(theNode.getElementsByTagName("startAt")[0]);
    }
    else  // do not want.  use full select instead
    {
      currentParam["queryType"] = '';
      currentParam["numRows"] = 0;
      currentParam["startAt"] = 0;
    }
    sqlParams.push(currentParam);
  }
  if (sqlParams.length == 0)
    sqlParams = null;
  return(sqlParams);
};

XMLParser.prototype.parseThemeBufferOptions = function(newNode)
{
  var bufferAttributes = {
    styleSheet: this.getObjectRecurse(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"styleSheet")]),
    fieldList: this.getObjectRecurse(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"fieldList")]),
    limit: this.getObjectRecurse(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"limit")]),
    resultTemplate: this.getObjectRecurse(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"resultTemplate")]),
    invalidTemplate: this.decodeSTRING(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"invalidTemplate")]),
    maxSelect: this.getObjectRecurse(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"maxSelect")])
  };
  var sqlParamsIndex = this.__helper__getNextElementNamedChildNode(newNode,0,"sqlParams");
  if (sqlParamsIndex > -1)
    bufferAttributes["sqlParams"] = this.parseChainedQuerySqlParams(newNode.childNodes[sqlParamsIndex]);
  else
    bufferAttributes["sqlParams"] = null;
  if (this.__helper__getNextElementNamedChildNode(newNode,0,"filterQueries") != -1)
  {
    var queryListNode = newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"filterQueries")];
    bufferAttributes["filterQueries"] = new Object();
    for (var queryIndex = this.__helper__getNextElementNamedChildNode(queryListNode,0,"query");queryIndex!=-1;queryIndex=this.__helper__getNextElementNamedChildNode(queryListNode,queryIndex+1,"query"))
    {
      bufferAttributes["filterQueries"][this.decodeSTRING(queryListNode.childNodes[queryIndex])] = null;
    }
  }
  else
    bufferAttributes["filterQueries"] = null;
  if (this.__helper__getNextElementNamedChildNode(newNode,0,"export_csv")!=-1)
  {
    if (!bufferAttributes["export_"])
      bufferAttributes["export_"] = new Object();
    bufferAttributes["export_"].csv = new Object();
    if(this.decodeSTRING(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"export_csv")]) == 'true')
    {
      bufferAttributes["export_"].csv.enabled = true;
      bufferAttributes["export_"].csv.delim = this.decodeSTRING(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"export_csv_delim")]);
      if(this.decodeSTRING(newNode.childNodes[this.__helper__getNextElementNamedChildNode(newNode,0,"export_csv_includefieldnames")])=='true')
        bufferAttributes["export_"].csv.includeFieldNames = true;
      else
        bufferAttributes["export_"].csv.includeFieldNames = false;
    }
    else
      bufferAttributes["export_"].csv.enabled = false;
  }
  return bufferAttributes;
};

XMLParser.prototype.parseThemeGroupDefinitions = function (newNode)
{
  var themeGroupDefinitions = new Object();
  for(var groupIndex=this.__helper__getNextElementNamedChildNode(newNode,0,"themeGroup");groupIndex!=-1;groupIndex=this.__helper__getNextElementNamedChildNode(newNode,groupIndex+1,"themeGroup"))
  {
    var groupNode = newNode.childNodes[groupIndex];
    var groupNameIndex = this.__helper__getNextElementNamedChildNode(groupNode,0,"themeGroupName");
    if (groupNameIndex==-1)
      var groupName = escapeHTML(groupNode.getAttribute("name"));
    else
      var groupName = this.decodeSTRING(groupNode.childNodes[groupNameIndex]);
    themeGroupDefinitions[groupName] = new Array;
    for (var groupMemberIndex = this.__helper__getNextElementNamedChildNode(groupNode,0,"themeGroupMember");groupMemberIndex!=-1;groupMemberIndex=this.__helper__getNextElementNamedChildNode(groupNode,groupMemberIndex+1,"themeGroupMember"))
    {
      var groupMemberNode = groupNode.childNodes[groupMemberIndex];
      var groupMemberName = this.getObjectRecurse(groupMemberNode);
      themeGroupDefinitions[groupName][groupMemberName] = groupMemberName;
    }
  }
  return themeGroupDefinitions;
};

XMLParser.prototype.parseLegendAttributes = function (newNode)
{
  return (newNode.nodeName=='legendAttributes')?{
    width: this.decodeINT(newNode.getElementsByTagName('width')[0].getElementsByTagName('int')[0]),
    height: this.decodeINT(newNode.getElementsByTagName('height')[0].getElementsByTagName('int')[0]),
    color: this.decodeSTRING(newNode.getElementsByTagName('color')[0].getElementsByTagName('string')[0]),
    font: this.decodeSTRING(newNode.getElementsByTagName('font')[0].getElementsByTagName('string')[0]),
    fontSize: this.decodeINT(newNode.getElementsByTagName('fontSize')[0].getElementsByTagName('int')[0]),
    valueFontSize: this.decodeINT(newNode.getElementsByTagName('valueFontSize')[0].getElementsByTagName('int')[0]),
    cellSpacing: this.decodeINT(newNode.getElementsByTagName('cellSpacing')[0].getElementsByTagName('int')[0])
  }:{
    width: newNode.getAttribute('width'),
    height: parseInt(newNode.getAttribute('height')),
    color: newNode.getAttribute('color'),
    font: newNode.getAttribute('font'),
    fontSize: newNode.getAttribute('fontSize'),
    valueFontSize: parseInt(newNode.getAttribute('valueFontSize')),
    cellSpacing: parseInt(newNode.getAttribute('cellSpacing'))
  };
};

XMLParser.prototype.parseMapExportConfig = function(newNode)
{
  return {enabled: newNode.getAttribute('enabled')};
};

XMLParser.prototype.parsePdfPrintConfig = function (newNode)
{
  var printConfig = {
    templates: [],
    defaultTemplate: parseInt(newNode.getAttribute('defaultTemplate'))
  };
  var templateNodes = newNode.getElementsByTagName('template');
  for(var i=0;i<templateNodes.length;i++)
  {
    var inputNodes = templateNodes[i].getElementsByTagName('userinput');
    var userinput = [];
    for (var j=0;j<inputNodes.length;j++)
      userinput.push({
          id:inputNodes[j].getAttribute('id'),
          description:inputNodes[j].getAttribute('description'),
          maxlength:parseInt(inputNodes[j].getAttribute('maxlength'))
      });
    printConfig.templates.push({
      displayName: this.decodeSTRING(templateNodes[i].getElementsByTagName("displayname")[0]),
      templateName: this.decodeSTRING(templateNodes[i].getElementsByTagName("templatename")[0]),
      orientation: templateNodes[i].getAttribute('orientation'),
      unit: templateNodes[i].getAttribute('unit'),
      width: parseFloat(templateNodes[i].getAttribute('width')),
      height: parseFloat(templateNodes[i].getAttribute('height')),
      mapwidth: parseFloat(templateNodes[i].getAttribute('mapwidth')),
      mapheight: parseFloat(templateNodes[i].getAttribute('mapheight')),
      userinput: userinput
    });
  }
  if ((printConfig.templates.length > 0)&&(printConfig.defaultTemplate==-1))
    printConfig.defaultTemplate = 0;
  if (printConfig.templates.length==0)
    printConfig.defaultTemplate = -1;
  printConfig.activeTemplate = printConfig.defaultTemplate;
  return printConfig;
};

XMLParser.prototype.parseLabelConfig = function (newNode)
{
  var labelConfig = new Object();
  labelConfig["pointLabels"] = new Object();
  for(var labelIndex=this.__helper__getNextElementNamedChildNode(newNode,0,"pointLabel");labelIndex!=-1;labelIndex=this.__helper__getNextElementNamedChildNode(newNode,labelIndex+1,"pointLabel"))
  {
    var currentNode = newNode.childNodes[labelIndex];
    var nameIndex = this.__helper__getNextElementNamedChildNode(currentNode,0,'labelName');
    if (nameIndex==-1)
      var labelId = currentNode.getAttribute("id");
    else
      var labelId = this.decodeSTRING(currentNode.childNodes[nameIndex]);
    var hiddenIdx = this.__helper__getNextElementNamedChildNode(currentNode,0,"hidden");
    labelConfig.pointLabels[labelId] = {
      styleSheet: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"styleSheet")]),
      sampleURL: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"sampleURL")]),
      description: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"description")]),
      hidden: (hiddenIdx==-1)?false:(this.decodeSTRING(currentNode.childNodes[hiddenIdx])=='true')
    };
  }
  labelConfig["textLabels"] = new Object();
  for(var labelIndex=this.__helper__getNextElementNamedChildNode(newNode,0,"textLabel");labelIndex!=-1;labelIndex=this.__helper__getNextElementNamedChildNode(newNode,labelIndex+1,"textLabel"))
  {
    var currentNode = newNode.childNodes[labelIndex];
    var nameIndex = this.__helper__getNextElementNamedChildNode(currentNode,0,'labelName');
    if (nameIndex==-1)
      var labelId = currentNode.getAttribute("id");
    else
      var labelId = this.decodeSTRING(currentNode.childNodes[nameIndex]);
    var hiddenIdx = this.__helper__getNextElementNamedChildNode(currentNode,0,"hidden");
    labelConfig.textLabels[labelId] = {
      styleSheet: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"styleSheet")]),
      sampleCSS:  this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"sampleCSS")]),
      sampleText: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"sampleText")]),
      hidden: (hiddenIdx==-1)?false:(this.decodeSTRING(currentNode.childNodes[hiddenIdx])=='true')
    };
  }
  labelConfig["lineLabels"] = new Object();
  for(var labelIndex=this.__helper__getNextElementNamedChildNode(newNode,0,"lineLabel");labelIndex!=-1;labelIndex=this.__helper__getNextElementNamedChildNode(newNode,labelIndex+1,"lineLabel"))
  {
    var currentNode = newNode.childNodes[labelIndex];
    var nameIndex = this.__helper__getNextElementNamedChildNode(currentNode,0,'labelName');
    if (nameIndex==-1)
      var labelId = currentNode.getAttribute("id");
    else
      var labelId = this.decodeSTRING(currentNode.childNodes[nameIndex]);
    var hiddenIdx = this.__helper__getNextElementNamedChildNode(currentNode,0,"hidden");
    labelConfig.lineLabels[labelId] = {
      styleSheet: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"styleSheet")]),
      color: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"color")]),
      thickness: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"thickness")]),
      description: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"description")]),
      hidden: (hiddenIdx==-1)?false:(this.decodeSTRING(currentNode.childNodes[hiddenIdx])=='true')
    };
  }
  labelConfig["polygonLabels"] = new Object();
  for(var labelIndex=this.__helper__getNextElementNamedChildNode(newNode,0,"polyLabel");labelIndex!=-1;labelIndex=this.__helper__getNextElementNamedChildNode(newNode,labelIndex+1,"polyLabel"))
  {
    var currentNode = newNode.childNodes[labelIndex];
    var nameIndex = this.__helper__getNextElementNamedChildNode(currentNode,0,'labelName');
    if (nameIndex==-1)
      var labelId = currentNode.getAttribute("id");
    else
      var labelId = this.decodeSTRING(currentNode.childNodes[nameIndex]);
    var hiddenIdx = this.__helper__getNextElementNamedChildNode(currentNode,0,"hidden");
    labelConfig.polygonLabels[labelId] = {
      styleSheet: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"styleSheet")]),
      color: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"color")]),
      thickness: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"thickness")]),
      fillColor: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"fillColor")]),
      description: this.decodeSTRING(currentNode.childNodes[this.__helper__getNextElementNamedChildNode(currentNode,0,"description")]),
      hidden: (hiddenIdx==-1)?false:(this.decodeSTRING(currentNode.childNodes[hiddenIdx])=='true')
    };
  }
  return labelConfig;
};

XMLParser.prototype.parseMapLoginQuery = function(queryNode)
{
  var definedQueryNode = queryNode.childNodes[this.__helper__getNextElementNamedChildNode(queryNode,0,"definedQuery")];
  return this.parseDefinedQuery(definedQueryNode);
};

XMLParser.prototype.parseQueryConfig = function(theNode){
  var queryConfig = {
    queries: [],
    groups: {}
  };
  for (var childIndex=this.__helper__getNextElementNamedChildNode(theNode,0,"queryGroup");childIndex!=-1;childIndex=this.__helper__getNextElementNamedChildNode(theNode,childIndex+1,"queryGroup"))
    queryConfig.groups[theNode.childNodes[childIndex].getAttribute("id")] = this.parseQueryGroup(theNode.childNodes[childIndex]);
  for (var i=0;i<theNode.childNodes.length;i++)
  {
    if(theNode.childNodes[i].nodeName=='definedQuery')
      queryConfig.queries.push(this.parseDefinedQuery(theNode.childNodes[i]));
  }
  return queryConfig;
};

XMLParser.prototype.parseQueryGroup = function(groupNode)
{
  var groupId = groupNode.getAttribute("id");
  var queryGroup = new Array;
  var queryIndex = 0;
  for (var childIndex=this.__helper__getNextElementNamedChildNode(groupNode,0,"query");childIndex!=-1;childIndex=this.__helper__getNextElementNamedChildNode(groupNode,childIndex+1,"query"))
  {
    queryGroup[queryIndex] = this.decodeSTRING(groupNode.childNodes[childIndex]);
    queryIndex++;  
  }  
  return queryGroup;
};

XMLParser.prototype.parseDefinedQuery = function(queryNode)
{
  var requestNode = queryNode.getElementsByTagName('request')[0];
  var fieldsNode = queryNode.getElementsByTagName('fieldList')[0];
  var exportNode = queryNode.getElementsByTagName('exportQuery')[0];
  var templateNode = queryNode.getElementsByTagName('resultTemplates')[0];
  var fieldList = this.parseQueryFields(fieldsNode);
  var exportConfig = (!exportNode)?({
      csv:{
        enabled: false,
        delim:',',
        includeFieldNames:true
      },
      xml:{
        enabled: false
      }
    }):({
      csv:{
        enabled: (this.decodeSTRING(exportNode.getElementsByTagName('export_csv')[0])=='true'),
        delim:this.decodeSTRING(exportNode.getElementsByTagName('export_csv_delim')[0]),
        includeFieldNames:(this.decodeSTRING(exportNode.getElementsByTagName('export_csv_includefieldnames')[0])=='true')
      },
      xml:{
        enabled: (this.decodeSTRING(exportNode.getElementsByTagName('export_xml')[0])=='true')
    }
  });
  
  var displayIndex = this.getNextElementNamedChildNode(queryNode,0,"display");
  var dbtypeindex = this.getNextElementNamedChildNode(requestNode,0,"dbtype");
  var config = {
    id: queryNode.getAttribute('id'),
    display: (displayIndex>-1)?(this.decodeSTRING(queryNode.childNodes[displayIndex])=='true'):true,
    title: this.decodeSTRING(queryNode.getElementsByTagName('title')[0]),
    description: this.decodeSTRING(queryNode.getElementsByTagName('description')[0]),
    HTMLForm: this.decodeSTRING(queryNode.getElementsByTagName('HTMLForm')[0]),
    fieldList:fieldList,
    request:{
      dbtype: (dbtypeindex>-1)?(this.decodeSTRING(requestNode.childNodes[dbtypeindex])):'',
      requestMethod: this.decodeSTRING(requestNode.childNodes[this.getNextElementNamedChildNode(requestNode,0,"requestMethod")]),
      pdqIdentifier: this.decodeSTRING(requestNode.childNodes[this.getNextElementNamedChildNode(requestNode,0,"pdqIdentifier")])
    },
    export_:exportConfig,
    templates:{
      validTemplate:this.decodeSTRING(templateNode.getElementsByTagName('validTemplate')[0]),
      invalidTemplate:this.decodeSTRING(templateNode.getElementsByTagName('invalidTemplate')[0]),
      emptyTemplate:this.decodeSTRING(templateNode.getElementsByTagName('emptyTemplate')[0]),
      pageRows:this.decodeINT(templateNode.getElementsByTagName('pageRows')[0])
    },
    suggestConfig:[],
    zoomto:{
      enabled: false,
      queryfield:'',
      layerfield:'',
      layerfieldtype:12,
      layerid:'',
      stylesheet:''      
    }
  };
  var zoomto = null;
  var zoomtoNode = null;
  for (var i=0;i<queryNode.childNodes.length;i++)
    if(queryNode.childNodes[i].nodeName=='zoomto')
      zoomtoNode = queryNode.childNodes[i];
  
  if(zoomtoNode){
    config["zoomto"]={
      enabled: true,
      queryfield:zoomtoNode.getAttribute("queryfield"),
      layerfield:zoomtoNode.getAttribute("layerfield"),
      layerfieldtype:parseInt(zoomtoNode.getAttribute("layerfieldtype")),
      layerid:zoomtoNode.getAttribute("layerid"),
      stylesheet:zoomtoNode.getAttribute("stylesheet")
    }
  };
  var suggestNodeIndex = this.getNextElementNamedChildNode(queryNode,0,"suggestConfig");
  if (suggestNodeIndex!=-1)
  {
    var suggestConfigNode = queryNode.childNodes[suggestNodeIndex];
    var suggestNodes = suggestConfigNode.getElementsByTagName('suggestInput');
    for (var i=0;i<suggestNodes.length;i++)
    {
      config.suggestConfig.push({
        pdqfield: suggestNodes[i].getAttribute('pdqfield'),
        elementId: suggestNodes[i].getAttribute('elementId'),
        resultElementId: suggestNodes[i].getAttribute('resultElementId'),
        timeout: parseInt(suggestNodes[i].getAttribute('timeout')),
        dbid: suggestNodes[i].getAttribute('dbid'),
        tablename: suggestNodes[i].getAttribute('tablename'),
        fieldname: suggestNodes[i].getAttribute('fieldname'),
        resultlimit: parseInt(suggestNodes[i].getAttribute('resultlimit'))
      });
    }
  };
  return config;  
};

XMLParser.prototype.parseQueryFields = function(fieldsNode)
{
  var fieldsConfig = new Array();
  for (var fieldIndex=this.__helper__getNextElementChildNode(fieldsNode,0);fieldIndex!=-1;fieldIndex=this.__helper__getNextElementChildNode(fieldsNode,fieldIndex+1))
  {
    var currentNode = fieldsNode.childNodes[fieldIndex];
    var newField = {
      id:currentNode.getAttribute("id"),
      fieldType: currentNode.nodeName,
      caption: '',
      fieldName: '',
      width: 0,
      defaultValue: '',
      initialValue: '',
      optionList: [],
      dynamicList:{
        dbid: '',
        table:'',
        valuefield: '',
        labelfield: '',
        whereclause:'',
        limit:10      
      }
    };
    for (var i=0;i<currentNode.childNodes.length;i++){
      var fieldOptionNode=currentNode.childNodes[i];
      switch(fieldOptionNode.nodeName){
        case 'caption':
        case 'fieldName':
        case 'defaultValue':
        case 'initialValue':
          newField[fieldOptionNode.nodeName]=this.decodeSTRING(fieldOptionNode);
          break;
        case 'width':
          newField['width']=this.decodeINT(fieldOptionNode);
          break;
        case 'optionList':
          newField['optionList'] = this.parseOptionList(fieldOptionNode);
          break;
        case 'dynamicList':
          newField['dynamicList']['dbid']=fieldOptionNode.getAttribute('dbid');
          newField['dynamicList']['table']=fieldOptionNode.getAttribute('table');
          newField['dynamicList']['valuefield']=fieldOptionNode.getAttribute('valuefield');
          newField['dynamicList']['labelfield']=fieldOptionNode.getAttribute('labelfield');
          newField['dynamicList']['whereclause']=fieldOptionNode.getAttribute('whereclause');
          newField['dynamicList']['limit']=parseInt(fieldOptionNode.getAttribute('limit'));
          break;
      };
    }
    fieldsConfig.push(newField);
  }
  return fieldsConfig;
};

XMLParser.prototype.parseOptionList = function(listParentNode)
{
  var optionList = new Array;
  for (var optionIndex=this.__helper__getNextElementChildNode(listParentNode,0);optionIndex!=-1;optionIndex=this.__helper__getNextElementChildNode(listParentNode,optionIndex+1))
  {
    var currentNode = listParentNode.childNodes[optionIndex];
    switch (currentNode.nodeName)
    {
      case 'option':
        optionList.push({
          type: 'option',
          value: currentNode.getAttribute("value"),
          label: currentNode.getAttribute("label")
        });
        break;
      case 'optgroup':
        optionList.push({
          type: 'optgroup',
          label: currentNode.getAttribute("label"),
          value: this.parseOptionList(currentNode)
        });
        break;
      default:
        break;
    }
  }
  return optionList;
};

XMLParser.prototype.parseTemplateDefinitions = function (documentNode)
{
  //the documentNode is the 'templateDefinitions' tag
  var templateDefinitionsObject = new Object;
  for (var currentNode = this.__helper__getNextElementNamedChildNode(documentNode,0,"templateDefinition");
              currentNode!=-1;
              currentNode=this.__helper__getNextElementNamedChildNode(documentNode,currentNode+1,"templateDefinition")
       )
  {
    templateDefinitionsObject[documentNode.childNodes[currentNode].getAttribute("id")] = this.parseTemplateDefinition(documentNode.childNodes[currentNode]);
  }
  return templateDefinitionsObject;
};

XMLParser.prototype.parseTemplateDefinition = function (templateDefinitionNode)
{
  var templateDefinition = new Object;
  templateDefinition.templateStructure = null;
  var templateStructureIndex = this.__helper__getNextElementNamedChildNode(templateDefinitionNode,0,"templateStructure");
  if (templateStructureIndex!=-1)
    templateDefinition.templateStructure = this.parseSelectionTemplateStructure(templateDefinitionNode.childNodes[templateStructureIndex]);
  var queryOptionsIndex = this.__helper__getNextElementNamedChildNode(templateDefinitionNode,0,"queryOptions");
  if (queryOptionsIndex!=-1)
    templateDefinition.queryOptions = this.parseTemplateQueryOptions(templateDefinitionNode.childNodes[queryOptionsIndex]);
  return templateDefinition;
};

XMLParser.prototype.parseTemplateQueryOptions = function (queryOptionsNode)
{
  var queryOptions = new Object;
  var zoomToResultsIndex = this.__helper__getNextElementNamedChildNode(queryOptionsNode,0,"zoomToResults");
  if (zoomToResultsIndex!=-1)
  {
    var zoomToResultsNode = queryOptionsNode.childNodes[zoomToResultsIndex];
    queryOptions.zoomToResults = {
      enabled: zoomToResultsNode.getAttribute('enabled'),
      queryField: zoomToResultsNode.getAttribute('queryField'),
      themeId: zoomToResultsNode.getAttribute('themeId'),
      themeField: zoomToResultsNode.getAttribute('themeField'),
      gisStylesheet: zoomToResultsNode.getAttribute('gisStylesheet')
    };
  }
  else
    queryOptions.zoomToResults = null;
  return queryOptions;
};

XMLParser.prototype.parseSelectionTemplateStructure = function (templateStructureNode)
{
  //build a data structure for the template elements...
  var templateStructure = new Array;
  var templateIndex = 0;
  for (var currentNode = this.__helper__getNextElementNamedChildNode(templateStructureNode,0,"templateElement");
    currentNode!=-1;
    currentNode=this.__helper__getNextElementNamedChildNode(templateStructureNode,currentNode+1,"templateElement"))
  {
    var theNode = templateStructureNode.childNodes[currentNode]
    var displayType = theNode.getAttribute('displayType');
    if (displayType=='header')
      displayType = 'heading';
    if (displayType=='header2')
      displayType = 'heading2';
    var caption = theNode.getAttribute('caption');
    var format = theNode.getAttribute('format');
    var dataIndex = theNode.getAttribute('dataIndex');
    var labelfield = theNode.getAttribute('labelfield');
    var beforelabel = theNode.getAttribute('beforelabel');
    var afterlabel = theNode.getAttribute('afterlabel');
    var urlfield = theNode.getAttribute('urlfield');
    var beforeurl = theNode.getAttribute('beforeurl');
    var afterurl = theNode.getAttribute('afterurl');
    var altfield = theNode.getAttribute('altfield');
    var beforealt = theNode.getAttribute('beforealt');
    var afteralt = theNode.getAttribute('afteralt');
    var format = theNode.getAttribute('format');
    var labelfield = theNode.getAttribute('labelfield');
    var beforelabel = theNode.getAttribute('beforelabel');
    var afterlabel = theNode.getAttribute('afterlabel');
    var keyField = theNode.getAttribute('keyField');
    var themeLink = theNode.getAttribute('themeLink');
    var linkFieldQuotes = theNode.getAttribute('linkFieldQuotes');
    var themeId = theNode.getAttribute('themeId');
    var themeField = theNode.getAttribute('themeField');
    var themeFieldType = theNode.getAttribute('themeFieldType');
    var queryId = theNode.getAttribute('queryId');
    var queryLinkText = theNode.getAttribute('queryLinkText');
    templateStructure[templateIndex] = {
      displayType:displayType,
      blockIndex: parseInt(theNode.getAttribute('blockIndex')),
      caption: (!caption)?(''):(caption.unescapeHTML()),
      format: (!format)?(''):(format.unescapeHTML()),
      dataIndex: (!dataIndex)?(''):(dataIndex.unescapeHTML()),
      labelfield: (!labelfield)?(''):(labelfield.unescapeHTML()),
      beforelabel: (!beforelabel)?(''):(beforelabel.unescapeHTML()),
      afterlabel: (!afterlabel)?(''):(afterlabel.unescapeHTML()),
      urlfield: (!urlfield)?(''):(urlfield.unescapeHTML()),
      beforeurl: (!beforeurl)?(''):(beforeurl.unescapeHTML()),
      afterurl: (!afterurl)?(''):(afterurl.unescapeHTML()),
      altfield: (!altfield)?(''):(altfield.unescapeHTML()),
      beforealt: (!beforealt)?(''):(beforealt.unescapeHTML()),
      afteralt: (!afteralt)?(''):(afteralt.unescapeHTML()),
      format: (!format)?(''):(format.unescapeHTML()),
      labelfield: (!labelfield)?(''):(labelfield.unescapeHTML()),
      beforelabel: (!beforelabel)?(''):(beforelabel.unescapeHTML()),
      afterlabel: (!afterlabel)?(''):(afterlabel.unescapeHTML()),
      keyField: (!keyField)?(''):(keyField.unescapeHTML()),
      themeLink: (!themeLink)?(''):(themeLink.unescapeHTML()),
      linkFieldQuotes: (!linkFieldQuotes)?(''):(linkFieldQuotes.unescapeHTML()),
      themeId: (!themeId)?(''):(themeId.unescapeHTML()),
      themeField: (!themeField)?(''):(themeField.unescapeHTML()),
      themeFieldType: (!themeFieldType)?(''):(themeFieldType.unescapeHTML()),
      queryId: (!queryId)?(''):(queryId.unescapeHTML()),
      queryLinkText: (!queryLinkText)?(''):(queryLinkText.unescapeHTML())
    };
    //linked queries need special handling.
    templateStructure[templateIndex].queryVariables = new Object;
    if (templateStructure[templateIndex].displayType=='query')
    {
      var queryVariableString = unescapeHTML(templateStructureNode.childNodes[currentNode].getAttribute('queryVariables'));
      var queryVariables = queryVariableString.split(';');
      var queryVarSplit = null;
      for (var currentQueryVariable = 0; currentQueryVariable < queryVariables.length; currentQueryVariable++)
      {
        if (queryVariables[currentQueryVariable]!='')
        {
          queryVarSplit = queryVariables[currentQueryVariable].split('=');
          templateStructure[templateIndex].queryVariables[queryVarSplit[0]] = queryVarSplit[1];
        }
      }
    }
    templateIndex++;
  }
  return templateStructure;
};


XMLParser.prototype.parseProximitySearchConfig = function()
{
  //look up proximity search config element
  var configData = Array();
  var nodelist = this.xmlDoc.getElementsByTagName("proximitySearchConfig");
  if (nodelist==null)
    return null;
  var proxSearchParentNode = nodelist.item(0);
  if (proxSearchParentNode)
  {
  var proxSearchNodes = proxSearchParentNode.getElementsByTagName('proximitySearch');

  //local utility functions  
  var getInputListValues = function(inputNode)
  {
    var returnValue = Array();
    var optionNodes = inputNode.getElementsByTagName('option');
    for (var i=0;i<optionNodes.length;i++)
      returnValue.push({label:optionNodes[i].getAttribute('label'),value:optionNodes[i].getAttribute('value')});
    return returnValue;
  };
  
  var getResultConfig = function(resultConfigNode)
  {
    var returnValue = Array();
    var fieldNodes = resultConfigNode.getElementsByTagName('field');
    for (var i=0;i<fieldNodes.length;i++)
      returnValue.push({label:fieldNodes[i].getAttribute('label'),name:fieldNodes[i].getAttribute('name'),novalue:fieldNodes[i].getAttribute('novalue')});
    return returnValue;
  };
  
  var getInputConfig = function(inputConfigNode)
  {
    var inputFields = Array();
    var inputNodes = inputConfigNode.getElementsByTagName('input');
    for (var j=0;j<inputNodes.length;j++)
      inputFields.push({
        type:inputNodes[j].getAttribute('type'),
        label:inputNodes[j].getAttribute('label'),
        placeholder:inputNodes[j].getAttribute('placeholder'),
        listValues: getInputListValues(inputNodes[j]),
        defaultValue: inputNodes[j].getAttribute('defaultvalue'),
        element: null
      });
    return inputFields;
  };
  
  var getInputLookupTable = function(inputFieldsArray)
  {
    var inputLookuptable = {};
    for (var i=0;i<inputFieldsArray.length;i++)
      inputLookupTable[inputFieldsArray[i]['placeholder']] = i;
    return inputLookupTable;
  };
  
  //build the configuration structure
  for (var i=0;i<proxSearchNodes.length;i++)
  {
    configData.push({
      name:this.decodeSTRING(proxSearchNodes[i].getElementsByTagName('titleHTML')[0]),
      layerid:proxSearchNodes[i].getAttribute('layerid'),
      stylesheet:proxSearchNodes[i].getAttribute('stylesheet'),
      maxselect:parseInt(proxSearchNodes[i].getAttribute('maxselect')),
      descriptionHTML:this.decodeSTRING(proxSearchNodes[i].getElementsByTagName('descriptionHTML')[0]),
      formHTML:this.decodeSTRING(proxSearchNodes[i].getElementsByTagName('formHTML')[0]),
      whereclause:this.decodeSTRING(proxSearchNodes[i].getElementsByTagName('whereclause')[0]),
      inputFields:getInputConfig(proxSearchNodes[i].getElementsByTagName('inputConfig')[0]),
      resultFields:getResultConfig(proxSearchNodes[i].getElementsByTagName('resultConfig')[0])
    });
    var fieldList = Array();
    for (var j=0;j<configData[i]['resultFields'].length;j++)
    {
      fieldList.push(configData[i]['resultFields'][j]['name']);
    }
    configData[i]['fieldlist']=fieldList.join(',');
  }
  }
  return configData;
};

XMLParser.prototype.getMaptipConfig = function()
{
  var config = [];
  var maptipParent = this.xmlDoc.getElementsByTagName('maptipConfig');
  if (maptipParent.item(0))
  {
    var maptipNodes = maptipParent.item(0).getElementsByTagName('maptip');
    for (var i=0;i<maptipNodes.length;i++){
      var alias=maptipNodes[i].getAttribute('alias');
      config.push({layerid:maptipNodes[i].getAttribute('layerid'),fieldid:maptipNodes[i].getAttribute('fieldid'),delay:parseInt(maptipNodes[i].getAttribute('delay')),tolerance:parseFloat(maptipNodes[i].getAttribute('tolerance')),alias:((alias!=null)?alias:maptipNodes[i].getAttribute('fieldid'))});
    }
  }
  return config;
};

