Index: fedd/federation/topdl.py
===================================================================
--- fedd/federation/topdl.py	(revision 807b5caa8a3078f2c04b185e1f7d440f3380e92d)
+++ fedd/federation/topdl.py	(revision d608a907ebea6177128f5b6bb8938fd76688c6d4)
@@ -3,4 +3,7 @@
 import re
 import xml.parsers.expat
+from xml.sax.saxutils import escape
+from base64 import b64encode
+from string import join
 
 from fedid import fedid as fedid_class
@@ -78,4 +81,7 @@
     def to_dict(self):
 	return { 'attribute': self.attribute, 'value': self.value }
+    def to_xml(self):
+	return "<attribute>%s</attribute><value>%s</value>" % \
+		(escape(self.attribute), escape(self.value))
 
 class Capacity(base):
@@ -90,4 +96,7 @@
 	return { 'rate': float(self.rate), 'kind': self.kind }
 
+    def to_xml(self):
+	return "<rate>%f</rate><kind>%s</kind>" % (self.rate, self.kind)
+
 class Latency(base):
     def __init__(self, time, kind):
@@ -100,4 +109,7 @@
     def to_dict(self):
 	return { 'time': float(self.time), 'kind': self.kind }
+
+    def to_xml(self):
+	return "<time>%f</time><kind>%s</kind>" % (self.time, self.kind)
 
 class Substrate(base):
@@ -132,4 +144,16 @@
 	return rv
 
+    def to_xml(self):
+	rv = "<name>%s</name>" % escape(self.name)
+	if self.capacity is not None:
+	    rv += "<capacity>%s</capacity>" % self.capacity.to_xml()
+	if self.latency is not None:
+	    rv += "<latency>%s</latency>" % self.latency.to_xml()
+	
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 class CPU(base):
     def __init__(self, type, attribute=[]):
@@ -147,4 +171,12 @@
 	    rv['attribute'] = [ a.to_dict() for a in self.attribute ]
 	return rv
+
+    def to_xml(self):
+	rv = "<type>%s</type>" % escape(self.type)
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 
 class Storage(base):
@@ -164,4 +196,13 @@
 	    rv['attribute'] = [ a.to_dict() for a in self.attribute ]
 	return rv
+
+    def to_xml(self):
+	rv = "<amount>%f</amount><persistence>%s</persistence>" % \
+		(self.amount, escape(self.persistence))
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 
 class OperatingSystem(base):
@@ -186,9 +227,26 @@
 	if self.name: rv['name'] = self.name
 	if self.version: rv['version'] = self.version
-	if self.distribution: rv['version'] = self.distribution
-	if self.distributionversion: rv['version'] = self.distributionversion
+	if self.distribution: rv['distribution'] = self.distribution
+	if self.distributionversion: 
+	    rv['distributionversion'] = self.distributionversion
 	if self.attribute:
 	    rv['attribute'] = [ a.to_dict() for a in self.attribute ]
 	return rv
+
+    def to_xml(self):
+	rv = ""
+	if self.name: rv += "<name>%s</name>" % escape(self.name)
+	if self.version: rv += "<version>%s</version>" % escape(self.version)
+	if self.distribution: 
+	    rv += "<distribution>%s</distribution>" % escape(self.distribution)
+	if self.distributionversion: 
+	    rv += "<distributionversion>%s</distributionversion>" % \
+		    escape(self.distributionversion)
+	
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 
 class Software(base):
@@ -209,4 +267,13 @@
 	    rv['attribute'] = [ a.to_dict() for a in self.attribute ]
 	return rv
+
+    def to_xml(self):
+	rv = "<location>%s</location>" % escape(self.location)
+	if self.install: rv += "<install>%s</install>" % self.install
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 
 class Interface(base):
@@ -243,4 +310,18 @@
 	    rv['attribute'] = [ a.to_dict() for a in self.attribute ]
 	return rv
+
+    def to_xml(self):
+	rv = join(["<substrate>%s</substrate>" % escape(s) \
+		for s in self.substrate], "")
+	rv += "<name>%s</name>" % self.name
+	if self.capacity:
+	    rv += "<capacity>%s</capacity>" % self.capacity.to_xml()
+	if self.latency:
+	    rv += "<latency>%s</latency>" % self.latency.to_xml()
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 
 class ID(base):
@@ -264,4 +345,15 @@
 	if self.localname: rv['localname'] = self.localname
 	if self.kerberosUsername: rv['kerberosUsername'] = self.kerberosUsername
+	return rv
+
+    def to_xml(self):
+	if self.uuid: rv = "<uuid>%s</uuid>" % b64encode(self.uuid)
+	elif self.fedid: rv = "<fedid>%s</fedid>" % b64encode(self.fedid)
+	elif self.uri: rv = "<uri>%s</uri>" % escape(self.uri)
+	elif self.localname: 
+	    rv = "<localname>%s</localname>" % escape(self.localname)
+	elif self.kerberosUsername: 
+	    rv = "<kerberosUsername>%s</kerberosUsername>" % \
+		    escape(self.kerberosUsername)
 	return rv
 
@@ -314,4 +406,25 @@
 	return { 'computer': rv }
 
+    def to_xml(self):
+	rv = "<name>%s</name>" % escape(self.name)
+	if self.cpu:
+	    rv += join(["<cpu>%s</cpu>" % c.to_xml() for c in self.cpu], "")
+	if self.os:
+	    rv += join(["<os>%s</os>" % o.to_xml() for o in self.os], "")
+	if self.software:
+	    rv += join(["<software>%s</software>" % s.to_xml() \
+		    for s in self.software], "")
+	if self.storage:
+	    rv += join(["<stroage>%s</stroage>" % s.to_xml() \
+		    for s in self.stroage], "")
+	if self.interface:
+	    rv += join(["<interface>%s</interface>" % i.to_xml() 
+		for i in self.interface], "")
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return "<computer>%s</computer>" % rv
+
+
 
 class Testbed(base):
@@ -338,4 +451,17 @@
 	    rv['attribute'] = [ a.to_dict() for a in self.attribute]
 	return { 'testbed': rv }
+
+    def to_xml(self):
+	rv = "<uri>%s</uri><type>%s</type>" % \
+		(escape(self.uri), escape(self.type))
+	if self.interface:
+	    rv += join(["<interface>%s</interface>" % i.to_xml() 
+		for i in self.interface], "")
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return "<testbed>%s</testbed>" % rv
+
+	
 
 class Segment(base):
@@ -365,4 +491,14 @@
 	return { 'segment': rv }
 
+    def to_xml(self):
+	rv = "<id>%s</id><uri>%s</uri><type>%s</type>" % \
+		(id.to_xml(), escape(self.uri), escape(self.type))
+	if self.interface:
+	    rv += join(["<interface>%s</interface>" % i.to_xml() 
+		for i in self.interface], "")
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return "<segment>%s</segment>" % rv
 
 class Other(base):
@@ -385,4 +521,13 @@
 	return {'other': rv }
 
+    def to_xml(self):
+	rv = ""
+	if self.interface:
+	    rv += join(["<interface>%s</interface>" % i.to_xml() 
+		for i in self.interface], "")
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return "<other>%s</other>" % rv
 
 class Topology(base):
@@ -490,4 +635,18 @@
 	    rv['attribute'] = [ s.to_dict() for s in self.attribute]
 	return rv
+
+    def to_xml(self):
+	rv = ""
+	if self.substrates:
+	    rv += join(["<substrates>%s</substrates>" % s.to_xml() \
+		    for s in self.substrates], "")
+	if self.elements:
+	    rv += join(["<elements>%s</elements>" % e.to_xml() \
+		    for e in self.elements], "")
+	if self.attribute:
+	    rv += join(["<attribute>%s</attribute>" % a.to_xml() \
+		    for a in self.attribute], "")
+	return rv
+
 
 def topology_from_xml(string=None, file=None, filename=None, top="topology"):
@@ -576,36 +735,10 @@
 def topology_to_xml(t, top=None):
     """
-    Print the topology as XML.  This is quick and dirty, but should work for
-    many purposes.  Convert the topology to a dict and print it recursively.
+    Print the topology as XML, recursively using the internal classes to_xml()
+    methods.
     """
-    from xml.sax.saxutils import escape
-
-    def dict_to_xml(e, top=None):
-	if top: rv = "<%s>" % top
-	else: rv = ""
-
-	for k in e.keys():
-	    if isinstance(e[k], basestring):
-		rv += "<%s>%s</%s>" % (k, escape(e[k]), k)
-	    elif isinstance(e[k], (int, float, long)):
-		rv += "<%s>%d</%s>" % (k, e[k], k)
-	    elif isinstance(e[k], dict):
-		rv += "<%s>%s</%s>" % (k, dict_to_xml(e[k]), k)
-	    elif getattr(e[k], '__iter__', None):
-		for ee in e[k]:
-		    if isinstance(ee, dict):
-			rv += "<%s>%s</%s>" % (k, dict_to_xml(ee), k)
-		    else:
-			rv += "<%s>%s</%s>" % (k, escape(ee), k)
-	    else:
-		try:
-		    rv += "<%s>%s</%s>" % (k, e[k], k)
-		except Exception:
-		    raise ConsistencyError("What is this?? %s %s" % (k, e[k]))
-	if top: rv += "</%s>" % top
-	return rv
-
-    return dict_to_xml(t.to_dict(), top)
-
+
+    if top: return "<%s>%s</%s>" % (top, t.to_xml(), top)
+    else: return t.to_xml()
 
 def topology_to_vtopo(t):
