SAX i Python
Python har et apparat for SAX. Siden SAX er en eventdrevet mekanisme, finner vi en implementasjon som ligner den vi finner i andre eventdrevne omgivelser. Python har en parser som leser en string og detekterer de substringene som skal gi opphav til et event. Det er vår oppgave å fortelle Pythonparseren hva som skal skje når et event intreffer. Dette gjør vi ved å angi callback-funksjoner. Det vil si at vi forteller parseren hvilke av våre egendefinerte funksjoner som skal kalles ved de respektive begivenhetene. Dette er en strategi som er helt parallell til den vi bruker når vi lager programmer som er styrt av brukerbegivenheter. Vi skriver da metoder for å plukke opp museklikk osv. Her ligger det også en "parser" i bakgrunnen som sender en melding eller kaller opp vår funksjon når det inntreffer en begivenhet som vi har meldt vår interesse i. I en SAX-parsing er ikke begivenhetene museklikk men symboler i den stringen som analyseres.
Vi bruker resultatfila fra olympiade-eksempelet, se modulene: Olympiade og Noen datasett . De aktuelle resultatene er ordnet i en XML-fil: all_results.xml
Eksempel 1
import xml.parsers.expat """ Simple demo of sax. B. Stenseth 2002 Use: Show(filename) See below for default filename """ #--------------------- # helper to load a text file def getTextFile(filename): try: file=open(filename,'r') intext=file.read() file.close() return intext except: print 'Error reading file ',filename return None #------------------------------------------------------- # 3 primitive handler functions used by show def start_element(name, attrs): print 'Start:', name, attrs def end_element(name): print 'End:', name def char_data(data): #print 'Data:', repr(data) if(not data.isspace()): print 'Data:', data def showAll(afile): p = xml.parsers.expat.ParserCreate() p.returns_unicode = 0 p.StartElementHandler = start_element p.EndElementHandler = end_element p.CharacterDataHandler = char_data content=getTextFile(afile) if(content!=None): p.Parse(content) def showData(afile): p = xml.parsers.expat.ParserCreate() p.returns_unicode = 0 p.CharacterDataHandler = char_data content=getTextFile(afile) if(content!=None): p.Parse(content) # basic testing if __name__=="__main__": showData('c:\\web\\dw\\pydom\\all_results.xml') #showAll('c:\\web\\dw\\pydom\\all_results.xml')
Det er disse linjene som setter opp koplingen:
p.StartElementHandler = start_element p.EndElementHandler = end_element p.CharacterDataHandler = char_data
der start_element, end_element og char_data er våre funksjoner. Se Python dokumentasjonen for en komplett liste av hvilke events vi kan plukke opp.
Eksempel 2
Nedenfor finner du et eksempel som plukker ut og rapporterer verdien til alle elementer med tagnavn "name".
import xml.parsers.expat,string """ Simple demo of sax. demosax2 selects content of element: name B. Stenseth 2002 Use: Show(filename) See below for default filename """ # helper to load a text file def getTextFile(filename): try: file=open(filename,'r') intext=file.read() file.close() return intext except: print 'Error reading file ',filename return None # global flag navnFlag=-1 #------------------------------------------------------- # 3 primitive handler functions used by show def start_element(name, attrs): global navnFlag navnFlag= string.find(name,'name') def end_element(name): global navnFlag navnFlag=-1 def char_data(data): global navnFlag if navnFlag>=0: print data # doit def show(afile): p = xml.parsers.expat.ParserCreate() p.returns_unicode = 0 p.StartElementHandler = start_element p.EndElementHandler = end_element p.CharacterDataHandler = char_data content=getTextFile(afile) if content!=None: p.Parse(content) # basic testing if __name__=="__main__": show('c:\\web\\dw\\pydom\\all_results.xml')
Eksempel 3
Nedenfor finner du et eksempel som skriver en indentert utskrift av alle olympiader, øvelser og deltagere.
import xml.parsers.expat,string """ Simple demo of sax. demosax2 selects content of element: name B. Stenseth 2006 Use: Show(filename) """ # helper to load a text file def getTextFile(filename): try: file=open(filename,'r') intext=file.read() file.close() return intext except: print 'Error reading file ',filename return None # global flag navnFlag=-1 # indentation when writing indent=' ' #------------------------------------------------------- # 3 primitive handler functions used by show def start_element(name, attrs): global navnFlag navnFlag= string.find(name,'name') if name.find('OlympicGame')!=-1: print attrs['place'] if name.find('event')!=-1: print indent+attrs['dist'] def end_element(name): global navnFlag navnFlag=-1 def char_data(data): global navnFlag if navnFlag>=0: print indent+indent+data # default filename for demopurposes, change it def show(afile): p = xml.parsers.expat.ParserCreate() p.returns_unicode = 0 p.StartElementHandler = start_element p.EndElementHandler = end_element p.CharacterDataHandler = char_data content=getTextFile(afile) if content!=None: p.Parse(content) # basic testing if __name__=="__main__": show('c:\\web\\dw\\pydom\\all_results.xml')