#!/usr/bin/env python

from xml.dom import minidom
import sets

def uniq(alist): # Fastest order preserving.
  s = sets.Set(alist)
  del alist[:]
  for a in s:
    alist.append(a)

def load(xmlfile, tag, has_name=True, do_array=None, do_special=None):
  dom = minidom.parse(xmlfile)
  xmlNodes = dom.getElementsByTagName(tag)

  dictionary = {}
  for xmlNode in xmlNodes:
    mdic = {}
    # Name is stored as a property and not a node.
    if(has_name):
      name = xmlNode.attributes["name"].value

    # Process the nodes.
    for bignode in filter(lambda x: x.nodeType==x.ELEMENT_NODE, xmlNode.childNodes):
      # Load the nodes.
      
      # Figure out if we need an array or dictionary.
      if bignode.nodeName in do_array:
        array = []
        use_array = True
      else:
        section = {}
        use_array = False

      for node in filter(lambda x: x.nodeType==x.ELEMENT_NODE,
          bignode.childNodes):
          
          # Big ugly hack to use list instead of array.
          if bignode.nodeName in do_array:
            use_array = True
            array.append(node.firstChild.data)

          # Uglier hack for special things.
          elif do_special != None and bignode.nodeName in do_special.keys():
            section[node.firstChild.data] = node.attributes[do_special[bignode.nodeName]].value

          # Normal way (but will overwrite lists).
          else:
            section[node.nodeName] = node.firstChild.data

      if use_array:
        mdic[bignode.nodeName] = array
      else:
        mdic[bignode.nodeName] = section

    # Append the element to the dictionary.
    dictionary[name] = mdic

  dom.unlink()
  return dictionary

def save(xmlfile, data, basetag, tag, has_name=True, do_array=None, do_special=None):
  """
  do_array is a DICTIONARY, not a list here
  """
  xml = minidom.Document()

  base = xml.createElement(basetag)

  for key, value in data.items():

    elem = xml.createElement(tag)
    if has_name:
      elem.setAttribute("name", key)

    for key2, value2 in value.items():
      node = xml.createElement(key2)

      # Check if it needs to parse an array instead of a dictionary.
      if do_array != None and key2 in do_array.keys():
        for text in value2:
          node2 = xml.createElement(do_array[key2])
          txtnode = xml.createTextNode(str(text))
          node2.appendChild(txtnode)
          node.appendChild(node2)

      # Check to see if we need to run the ULTRA_UBER_HACK.
      elif do_special != None and key2 in do_special.keys():
        for key3, value3 in value2.items():
          node2 = xml.createElement(do_special[key2][0])
          node2.setAttribute(do_special[key2][1], value3)
          txtnode = xml.createTextNode(str(key3))
          node2.appendChild(txtnode)
          node.appendChild(node2)
      
      # Standard dictionary approach.
      else:
        for key3, value3 in value2.items():
          node2 = xml.createElement(key3)
          txtnode = xml.createTextNode(str(value3))
          node2.appendChild(txtnode)
          node.appendChild(node2)

      elem.appendChild(node)
    base.appendChild(elem)
  xml.appendChild(base)

  fp = open(xmlfile, "w")
  xml.writexml(fp, "", "", "", "UTF-8")
  
  xml.unlink()