[Edu-sig] Rich Data Structures (cont.)

Kirby Urner urnerk at qwest.net
Thu Nov 3 01:12:09 CET 2005


> A useful curriculum segment would be to take the above xml and run it
> through a parser to create a bunch of city objects with lat and long
> attributes, i.e. XML used to instantiate objects.  That'd be a good "cave
> painting" (= simplification, many essential aspects conveyed) of many real
> world applications (e.g. XAML).
> 
> Kirby

Just to round this out:

My cities dict --> XML function made the mistake of not creating a 'root'
tag, i.e. the <city></city> elements floated outside any container.  The SAX
parser (SAX = Simple API for XML) didn't like that.

So...

A fixed function:

# whatever path
thepath = "c:/documents and settings/kirby/My Documents/"

def makexml(thefile):

    """
    dict --> XML file
    The dict in question is on file here:
    http://mail.python.org/pipermail/edu-sig/2005-October/005500.html
    """

    f = open(thepath + thefile, 'w')
    f.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
    f.write('<cities>\n')
    for city in cities:  # cities is a global in this context
        loc = tuple([s.strip() for s in city.split(',')])
        if len(loc)==3:
            f.write('<city name="%s" state="%s" country="%s">\n' % loc)
        else:
            f.write('<city name="%s" state="%s">\n' % loc)
        f.write('\t<lat  deg="%s" min="%s" dir="%s" />\n' % cities[city][0])
        f.write('\t<long deg="%s" min="%s" dir="%s" />\n' % cities[city][1])
        f.write('</city>\n')
    f.write('</cities>\n')
    f.close()


And here's another to read back the XML so generated, and recreate the dict.
Not very elaborate or general, but enough to give some ideas I think.

from xml.sax import make_parser
from xml.sax.handler import ContentHandler

class CityHandler(ContentHandler):
    """
    Run through an XML file in a specific format:

    <cities>
    <city name="Toronto" state="Ont." country="Can.">
	 <lat  deg="43" min="40" dir="W" />
	 <long deg="79" min="24" dir="N" />
    </city>
    <city name="Nashville" state="Tenn.">
	  <lat  deg="36" min="10" dir="W" />
	  <long deg="86" min="47" dir="N" />
    </city>
    </cities>

    Create a dictionary like the one used to create 
    the XML in the first place.
    """

    def __init__(self):
        self.thedict = {}
        self.key = ''
        self.latlong = []

    def startElement(self, name, attrs):
        if name=='city':
            key = "%s, %s" % (str(attrs.get('name')),
                              str(attrs.get('state')))

            country = str(attrs.get('country','')) # optional attribute

            if country<>'':
                key = key + ", " + country
            self.key = key
            
        if name in ['lat','long']:

		# build a list of two tuples of form (deg, min, dir)
            # using str because we don't want unicode
            self.latlong.append(
                (int(attrs.get('deg')),
                 int(attrs.get('min')),
                 str(attrs.get('dir'))))

            if name=='long':
		    # time to create a new dict entry and start new city
                self.thedict[self.key]=self.latlong
                self.latlong=[]
                self.key=''

def makecities(thefile):
    """
    Take the xml file created above and reconstitute the same dictionary.
    """
    parser = make_parser()
    thehandler = CityHandler()
    parser.setContentHandler(thehandler)
    parser.parse(thepath + thefile)
    print thehandler.thedict

OK, I think that's enough for now.  XML freaks could go a *lot* further.  My
goal is to keep it basic basic.
    
Kirby




More information about the Edu-sig mailing list