> Can someone help me do this? I have grossly hacked up code from the archive
> that nested strings which I can do, but translating that to dictionaries is
> beyond me. The deal is that there is a main dictionary of arbitrarily
> nested dictionaries. The program will not know how deep. Dictionary example
> is available but probably unnecessary. Innermost dictionary is contains
> many elements. Actually I'd prefer the innermost to be a tuple, but I
> thought it would be easier with an innermost dictionary to not mix types.
> The code I have so far is below. As is obvious, I don't quite understand
> the underlying philosophy. I'm sure that once I see it it will make sense.
> For one, there's a tuple returning Thank you.
I did something similar a few weeks ago. I had nested dictionaries representing
a tree structure which I wanted to store in XML files (and display as a CTree).
It seems to me, that your problem is the unknown depth of the tree, right?
A possible solution to this problem would be recursion.
I will attach my tree data type. Maybe studying the code can help you. Creating a CTree
from this is no big problem.
Bye, Martin Grimme --- http://www.pycage.de
from xml import sax
import urllib
SEPARATOR = ":"
class DataTree:
__INDEX_TYPE = 0
__INDEX_VALUE = 1
__INDEX_INFO = 2
#
# Creates a new DataTree object.
#
def __init__(self):
self.__tree = {}
#
# Returns the node at the given path.
#
def __get_node(self, path):
if (path):
parts = path.split(SEPARATOR)
else:
parts = []
node = self.__tree
for i in parts:
node = node[i]
return node
#
# Converts types.
#
def __convert_type(self, value, to_type):
if (value == ""): return ""
if (to_type == "string"):
out = str(value)
elif (to_type == "int"):
out = int(value)
elif (to_type == "float"):
out = float(value)
elif (to_type == "bool"):
out = int(value)
else:
out = value
return out
#
# Creates a new folder node.
#
def new_folder(self, path, name):
node = self.__get_node(path)
if (not node.has_key(name)):
node[name] = {}
#
# Creates a new entry node.
#
def new_entry(self, path, name, type):
node = self.__get_node(path)
node[name] = [type, "", ""]
#
# Returns the value stored at the given path.
#
def get(self, path):
try:
node = self.__get_node(path)
if (type(node) == type([])):
typ = node[self.__INDEX_TYPE]
value = self.__convert_type(node[self.__INDEX_VALUE], typ)
else:
value = None
except:
value = None
return value
#
# Sets the value for the given path.
#
def set(self, path, value):
node = self.__get_node(path)
if (type(node) == type([])):
node[self.__INDEX_VALUE] = self.__convert_type(value, "string")
#
# Returns an info stored stored at the given path.
#
def get_info(self, path):
node = self.__get_node(path)
info = node[self.__INDEX_INFO]
return info
#
# Sets the info string of the given path.
#
def set_info(self, path, info):
node = self.__get_node(path)
node[self.__INDEX_INFO] = info
#
# Lists all children of the node at the given path.
#
def list(self, path):
try:
node = self.__get_node(path)
except:
node = []
if (type(node) == type([])):
return []
else:
return node.keys()
#
# Removes the node at the given path (folder or entry).
#
def remove(self, path):
parts = path.split(SEPARATOR)
path = SEPARATOR.join(parts[:-1])
name = parts[-1]
node = self.__get_node(path)
del node[name]
#
# Converts the tree to XML.
#
def to_xml(self, node = None, indent = 0):
out = ""
if (node == None):
out += "<datatree>\n"
out += self.to_xml(self.__tree, indent + 2)
out += "</datatree>\n"
else:
children = node.keys()
for name in children:
child = node[name]
namestring = urllib.quote(name)
if (type(child) == type([])):
value = urllib.quote(child[self.__INDEX_VALUE])
dtype = urllib.quote(child[self.__INDEX_TYPE])
info = urllib.quote(child[self.__INDEX_INFO])
out += " " * indent
out += "<entry name=\"" + namestring +"\" " \
+ "value=\"" + value + "\" " \
+ "type=\"" + dtype + "\" "\
+ "info=\"" + info + "\"/>\n"
else:
out += " " * indent
out += "<folder name=\"" + namestring + "\">\n"
out += self.to_xml(child, indent + 2)
out += " " * indent
out += "</folder>\n"
#end if
#end for
#end if
return out
#
# Creates a tree from XML.
#
def from_xml(self, xmldata):
handler = _TreeBuilder(self)
parser = sax.make_parser()
parser.setContentHandler(handler)
parser.feed(xmldata)
parser.close()
#
# This class parses XML data and creates a tree.
#
class _TreeBuilder(sax.handler.ContentHandler):
def __init__(self, tree):
self.__tree = tree
self.__path = ""
def startElement(self, ename, attrs):
if (ename == "folder"):
name = urllib.unquote(attrs["name"]).encode("LATIN-1")
self.__tree.new_folder(self.__path, name)
if (self.__path):
self.__path = self.__path + SEPARATOR + name
else:
self.__path = name
elif (ename == "entry"):
name = urllib.unquote(attrs["name"]).encode("LATIN-1")
dtype = urllib.unquote(attrs["type"]).encode("LATIN-1")
value = urllib.unquote(attrs["value"]).encode("LATIN-1")
info = urllib.unquote(attrs["info"]).encode("LATIN-1")
self.__tree.new_entry(self.__path, name, dtype)
if (self.__path):
self.__path = self.__path + SEPARATOR + name
else:
self.__path = name
self.__tree.set(self.__path, value)
self.__tree.set_info(self.__path, info)
def endElement(self, ename):
parts = self.__path.split(SEPARATOR)
self.__path = SEPARATOR.join(parts[:-1])
#
# Example usage for this datatype.
#
if (__name__ == "__main__"):
# build a tree
tree = DataTree()
tree.new_folder("", "files")
tree.new_folder("", "mimetypes")
tree.new_folder("mimetypes", "text/html")
tree.new_folder("mimetypes:text/html", "icons")
tree.new_folder("mimetypes:text/html", "actions")
tree.new_entry("mimetypes:text/html:actions", "open", "string")
tree.set("mimetypes:text/html:actions:open", "galeon %s")
tree.set_info("mimetypes:text/html:actions:open",
"The action for opening HTML files.")
# convert to XML
d = tree.to_xml()
# build a new tree and load the XML data of the old tree
newtree = DataTree()
newtree.from_xml(d)
# test the tree
print "Open: " + newtree.get("mimetypes:text/html:actions:open")
print
# convert to XML again... is should still be the same XML text
print newtree.to_xml()