15. Übung [IMPOTS] mit XML
In dieser bereits mehrfach behandelten Übung sendet der Server die Ergebnisse in Form eines XML-Datenstroms an den Client zurück:
- <reponse><erreur>msg</erreur></reponse> im Fehlerfall;
- <reponse><impot>valeur</impot></reponse>, wenn die Steuer berechnet werden konnte.
Wir wenden das soeben Gelernte auf die Analyse eines XML-Dokuments an.
![]() |
15.1. Der Webservice
Der Webdienst unterscheidet sich nicht von dem zuvor behandelten Webdienst, abgesehen davon, dass die an den Client gesendete Antwort XML geringfügig abweicht. Die Architektur bleibt dieselbe:
![]() |
#!D:\Programme\ActivePython\Python2.7.2\python.exe
# -*- coding=Utf-8 -*-
# Import des Moduls „Impots*“
from impots import *
import cgi,cgitb,re
# Anzeige von Debugging-Informationen zulassen
cgitb.enable()
# ------------------------------------------------
# Der Webdienst der Steuerbehörde
# ------------------------------------------------
# Die für die Steuerberechnung erforderlichen Daten wurden in die Tabelle mysqL TABLE
# der Datenbank BASE. Die Tabelle hat folgende Struktur
# Grenzwerte decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2)
# die Angaben zu den Steuerpflichtigen (Familienstand, Anzahl der Kinder, Jahresgehalt)
# werden vom Kunden in der Form „params=Familienstand, Anzahl der Kinder, Jahresgehalt“ übermittelt
# Die Ergebnisse (Familienstand, Anzahl der Kinder, Jahresgehalt, zu zahlende Steuer) werden an den Kunden zurückgesendet
# in der Form <Steuer>Wert</Steuer>
# oder in der Form <Fehler>Meldung</Fehler>, wenn die Parameter ungültig sind
# Der Server sendet unformatierten Text an den Client zurück
print "Content-Type: text/plain\n"
# Beginn der Antwort
print "<reponse>"
# Definition der Konstanten
USER="root"
PWD=""
HOTE="localhost"
BASE="dbimpots"
TABLE="impots"
# Instanziierung der Schicht [metier]
try:
metier=ImpotsMetier(ImpotsMySQL(HOTE,USER,PWD,BASE,TABLE))
except (IOError, ImpotsError) as infos:
print ("<erreur>Une erreur s'est produite : {0}</erreur>".format(infos))
sys.exit()
# Die vom Client an den Server gesendete Zeile wird abgerufen
params=cgi.FieldStorage().getlist('params')
# Wenn keine Parameter vorhanden sind, wird ein Fehler ausgegeben
if not params:
print "<erreur>Le parametre [params] est absent<erreur></reponse>"
sys.exit()
# Der Parameter „params“ wird ausgewertet
#print "Empfangene Parameter --> %s\n" %(params)
items=params[0].strip().lower().split(',')
# Es dürfen nur 3 Felder vorhanden sein
if len(items)!=3:
print "<erreur>[%s] : nombre de parametres invalide</erreur></reponse>" % (params[0])
sys.exit()
# Der erste Parameter (Familienstand) muss „ja“ oder „nein“ sein
marie=items[0].strip()
if marie!="oui" and marie != "non":
print "<erreur>[%s] : 1er parametre invalide</erreur></reponse>\n"% (params[0])
sys.exit()
# Der zweite Parameter (Anzahl der Kinder) muss eine ganze Zahl sein
match=re.match(r"^\s*(\d+)\s*$",items[1])
if not match:
print "<erreur>[%s] : 2ieme parametre invalide</erreur></reponse>\n"% (params[0])
sys.exit()
enfants=int(match.groups()[0])
# Der dritte Parameter (Gehalt) muss eine ganze Zahl sein
match=re.match(r"^\s*(\d+)\s*$",items[2])
if not match:
print "<erreur>[%s] : 2ieme parametre invalide</erreur></reponse>\n"% (params[0])
sys.exit()
salaire=int(match.groups()[0])
# Die Steuer wird berechnet
impot=metier.calculer(marie,enfants,salaire)
# Das Ergebnis wird zurückgegeben
print "<impot>%s</impot></reponse>\n" % (impot)
# Ende
Anmerkungen:
Dieser Webdienst unterscheidet sich vom vorherigen lediglich durch die Art seiner Antwort:
<reponse><erreur>msg</erreur></reponse> im Fehlerfall anstelle von <erreur>msg</erreur>
<reponse><impot>valeur</impot></reponse>, wenn die Steuer berechnet werden konnte, anstelle von <impot>valeur</impot>
15.2. Der programmierte Client
Unser Client muss die vom Webdienst gesendete Antwort XML analysieren. Wir wenden dabei das an, was wir bei der Analyse eines Dokuments XML gesehen haben.
# -*- coding=utf-8 -*-
import httplib,urllib,re
import xml.sax, xml.sax.handler
# Verwaltungsklasse XML
class XmlHandler(xml.sax.handler.ContentHandler):
# Funktion, die beim Auftreten eines Start-Tags aufgerufen wird
def startElement(self,name,attributs):
# das aktuelle Element wird notiert
global elementcourant
elementcourant=name.strip().lower()
# die Funktion, die beim Auftreten eines End-Tags aufgerufen wird
def endElement(self,name):
# Es wird nichts unternommen
pass
# die Funktion zur Datenverwaltung
def characters(self,data):
# Daten
global elementcourant,elements
# Die Daten werden abgerufen
match=re.match(r"^\s*(.+?)\s*$",data)
if match:
elements[elementcourant]=match.groups()[0].lower()
def getResultatsXml(reponse):
# die Antwort wird analysiert XML
xml.sax.parseString(reponse,XmlHandler())
# die Ergebnisse werden ausgegeben
if elements.has_key('erreur'):
return (elements['erreur'],"")
else:
return ("",elements['impot'])
# ------------------------------------------------------------ main
# Konstanten
HOST="localhost"
URL="/cgi-bin/impots_web_02b.py"
data=("oui,2,200000","non,2,200000","oui,3,200000","non,3,200000","x,y,z,t","x,2,200000", "oui,x,200000","oui,2,x");
# globale Variablen
elementcourant=""
elements={}
# Verbindung
connexion=httplib.HTTPConnection(HOST)
# Nachverfolgung
#connexion.set_debuglevel(1)
# Es wird eine Schleife über die an den Server zu sendenden Daten durchlaufen
for params in data:
# Die Parameter müssen vor dem Senden an den Server kodiert werden
parametres = urllib.urlencode({'params': params})
# Senden der Anfrage
connexion.request("POST",URL,parametres)
# Verarbeitung der Antwort (Datenstrom XML)
reponse=connexion.getresponse().read()
# Auswertung der XML-Datei
(erreur,impot)=getResultatsXml(reponse)
if not erreur:
print "impot[%s]=%s" % (params,impot)
else:
print "erreur[%s]=%s" % (params,erreur)
Anmerkungen:
- Der Webservice-Flow XML wird von der Funktion getResultatsXml (Zeile 60) verarbeitet;
- Zeile 29: die Funktion getResultatsXml;
- Zeile 31: Die Antwort XML des Webdienstes wird von einer Instanz der in Zeile 6 definierten Klasse XmlHandler analysiert;
- Zeile 6: Die Klasse XmlHandler implementiert die drei Methoden startElement, endElement und characters. Mit Hilfe dieser drei Methoden wird ein Dictionary erstellt. Die Schlüssel sind die Namen der Tags <erreur> und <impot>, und die Werte sind die diesen beiden Tags zugeordneten Daten;
- Zeilen 33–36: Die Funktion getResultatsXml gibt ein Tupel mit zwei Elementen zurück:
- (erreur,""), wenn die Analyse des Datenstroms XML das Vorhandensein des Tags <erreur> ergeben hat. erreur stellt dann den Inhalt dieses Tags dar;
- ("",impot), wenn die Analyse des Datenstroms XML das Vorhandensein des Tags <impot> ergeben hat. impot stellt dann den Inhalt dieses Tags dar.
- Zeile 60: Das Ergebnis der Funktion getResultatsXml wird abgerufen und anschließend in den Zeilen 61–64 ausgewertet.

