#!/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
    
    # Append the element to the dictionary.
    for bignode in filter(lambda x: x.nodeType==x.ELEMENT_NODE, xmlNode.childNodes):
      mdic[bignode.nodeName], size = load_Tag(bignode, do_array, do_special)

    dictionary[name] = mdic

  dom.unlink()
  return dictionary

def load_Tag(node, do_array=None, do_special=None):
  i = 0

  # Figure out if we need an array or dic.
  array = []
  section = {}
  if(do_array != None and node.nodeName in do_array) or \
      (do_special != None and node.nodeName in do_special):
    use_array = True
  else:
    use_array = False

  for child in filter(lambda x: x.nodeType == x.ELEMENT_NODE, node.childNodes):
    n = 0
    
    children, n = load_Tag(child, do_array, do_special)

    # Just slap the children on.
    if n > 0:
      section[child.nodeName] = children

    # Big ugly hack to use list instead of array.
    elif use_array and node.nodeName in do_array:
      array.append(child.firstChild.data)

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

    elif n > 0:
      section[child.nodeName] = children

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

    i = i+1

  # Return.
  if use_array:
    return array, i
  else:
    return section, i
  
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)

      save_Tag(xml, elem, value, do_array, do_special)
    base.appendChild(elem)
  xml.appendChild(base)

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

def save_Tag(xml, parent, data, do_array=None, do_special=None):
  for key, value in data.items():
    node = xml.createElement(key)

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

    # Check see if we need to run the ULTRA UBER HACK!
    elif do_special != None and key in do_special.keys():
      for item in value:
        for key2, value2 in item.items(): # Should only be one member.
          node2 = xml.createElement(do_special[key][0])
          node2.setAttribute(do_special[key][1], value2)
          txtnode = xml.createTextNode(str(key2))
          node2.appendChild(txtnode)
          node.appendChild(node2)
        

    elif isinstance(value, dict):
      save_Tag(xml, node, value, do_array, do_special)

    # Standard dictionary approach.
    else:
      txtnode = xml.createTextNode(str(value))
      node.appendChild(txtnode)

    parent.appendChild(node)