Skip to content

15. [IMPOTS] alıştırması ile XML

Daha önce birçok kez incelenen bu alıştırmada, sunucu sonuçları XML akışı biçiminde istemciye geri gönderir:

  • Hata durumunda <reponse><erreur>msg</erreur></reponse>;
  • Vergi hesaplanabildiyse <reponse><impot>valeur</impot></reponse>.

XML belgesinin analiziyle ilgili az önce öğrendiklerimizi kullanıyoruz.

15.1. Web hizmeti

Web hizmeti, müşteriye gönderilen XML yanıtının biraz farklı olması dışında, daha önce incelediğimiz web hizmetinden farklı değildir. Mimari aynı kalır:


Web hizmeti (impots_web_02)


#!D:\Programs\ActivePython\Python2.7.2\python.exe

# -*- coding=Utf-8 -*-
# Impots* sınıfları modülünün içe aktarılması
from impots import *
import cgi,cgitb,re

# hata ayıklama bilgilerinin görüntülenmesine izin verilir
cgitb.enable()

# ------------------------------------------------ 
# vergi web hizmeti
# ------------------------------------------------ 

# vergi hesaplaması için gerekli veriler mysqL TABLE
# tabloya yerleştirilmiştir. Tablonun yapısı şöyledir
# sınırlar decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2)
# vergi mükelleflerine ait parametreler (medeni durum, çocuk sayısı, yıllık maaş)
# müşteri tarafından params=medeni durum, çocuk sayısı, yıllık maaş biçiminde gönderilir
# sonuçlar (medeni durum, çocuk sayısı, yıllık maaş, ödenecek vergi) müşteriye geri gönderilir
# <vergi>değer</vergi> biçiminde
# veya parametreler geçersizse <hata>msg</hata> biçiminde

# sunucu, müşteriye biçimlendirilmemiş metin gönderir
print "Content-Type: text/plain\n"
# yanıtın başlangıcı
print "<reponse>"

# sabitlerin tanımlanması
USER="root"
PWD=""
HOTE="localhost"
BASE="dbimpots"
TABLE="impots"

# [metier] katmanının örneklenmesi
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()

# istemci tarafından sunucuya gönderilen satırı alıyoruz
params=cgi.FieldStorage().getlist('params')
# parametre yoksa hata verilir
if not params:
    print "<erreur>Le parametre [params] est absent<erreur></reponse>"
    sys.exit()

# params parametresini işliyoruz  
#print "alınan parametreler --> %s\n" %(params)
items=params[0].strip().lower().split(',')
# sadece 3 alan olmalı
if len(items)!=3:
    print "<erreur>[%s] : nombre de parametres invalide</erreur></reponse>" % (params[0])
    sys.exit()
# ilk parametre (medeni durum) evet/hayır şeklinde olmalıdır
marie=items[0].strip()
if marie!="oui" and marie != "non":
    print "<erreur>[%s] : 1er parametre invalide</erreur></reponse>\n"% (params[0])
    sys.exit()
# ikinci parametre (çocuk sayısı) bir tamsayı olmalıdır
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])
# üçüncü parametre (maaş) bir tamsayı olmalıdır
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])
# vergi hesaplanır
impot=metier.calculer(marie,enfants,salaire)
# sonuç döndürülür
print "<impot>%s</impot></reponse>\n" % (impot)
# son

Notlar:

Bu web hizmeti, önceki hizmetten yalnızca yanıtının niteliği bakımından farklılık gösterir:

Hata durumunda <reponse><erreur>msg</erreur></reponse> yerine <erreur>msg</erreur>

Vergi hesaplanabildiyse <impot>valeur</impot> yerine <reponse><impot>valeur</impot></reponse>

15.2. Programlanmış istemci

Müşterimiz, web hizmeti tarafından gönderilen XML yanıtını analiz etmelidir. XML belgesinin analizinde görülenleri burada da uygularız.


Program (client_impots_web_02)


# -*- coding=utf-8 -*-

import httplib,urllib,re
import xml.sax, xml.sax.handler
# yönetim sınıfı XML
class XmlHandler(xml.sax.handler.ContentHandler):

    # başlangıç etiketiyle karşılaşıldığında çağrılan işlev
    def startElement(self,name,attributs):
        # geçerli öğe kaydedilir
        global elementcourant
        elementcourant=name.strip().lower()

    # bitiş etiketiyle karşılaşıldığında çağrılan işlev
    def endElement(self,name):
        # hiçbir işlem yapılmaz
        pass

    # veri yönetimi işlevi
    def characters(self,data):
        # veriler
        global elementcourant,elements

        # veriler alınır
        match=re.match(r"^\s*(.+?)\s*$",data)
        if match:
            elements[elementcourant]=match.groups()[0].lower()
    
def getResultatsXml(reponse):
    # yanıt analiz edilir XML
    xml.sax.parseString(reponse,XmlHandler())
    # sonuçlar veriliyor
    if elements.has_key('erreur'):
        return (elements['erreur'],"")
    else:
        return ("",elements['impot'])

# ------------------------------------------------------------ ana
# sabitler
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");
# global değişkenler
elementcourant=""
elements={}

# bağlantı
connexion=httplib.HTTPConnection(HOST)
# izleme
#connexion.set_debuglevel(1)
# sunucuya gönderilecek veriler üzerinde döngü yapılıyor
for params in data:
    # parametreler sunucuya gönderilmeden önce kodlanmalıdır
    parametres = urllib.urlencode({'params': params})
    # isteğin gönderilmesi
    connexion.request("POST",URL,parametres)
    # yanıtın işlenmesi (XML akışı)
    reponse=connexion.getresponse().read()
    # xml dosyasının işlenmesi
    (erreur,impot)=getResultatsXml(reponse)
    if not erreur:
        print "impot[%s]=%s" % (params,impot)
    else:
        print "erreur[%s]=%s" % (params,erreur)

Notlar:

  • web hizmetinin XML akışı, getResultatsXml işlevi tarafından işlenir (60. satır);
    1. satır: getResultatsXml işlevi;
  • satır 31: web hizmetinin XML yanıtı, satır 6'da tanımlanan XmlHandler sınıfının bir örneği tarafından analiz edilir;
    1. satır: XmlHandler sınıfı, startElement, endElement ve characters adlı 3 yöntemi uygular. Bu 3 yöntem yardımıyla bir sözlük oluşturulur. Anahtarlar, <erreur> ve <impot> etiketlerinin adlarıdır; değerler ise bu iki etikete ait verilerdir;
  • 33-36. satırlar: getResultatsXml işlevi, 2 elemanlı bir tuple döndürür:
    • (erreur,""), XML akışının analizinde <erreur> etiketinin varlığı tespit edilirse. Bu durumda erreur, bu etiketin içeriğini temsil eder;
    • ("",impot), XML akışının analizinde <impot> etiketinin varlığı tespit edilmişse. Bu durumda impot, bu etiketin içeriğini temsil eder.
    1. satır: getResultatsXml işlevinin sonucu alınır ve 61-64. satırlarda işlenir.

15.3. Sonuçlar

1
2
3
4
5
6
7
8
impot[oui,2,200000]=22504.0
impot[non,2,200000]=33388.0
impot[oui,3,200000]=16400.0
impot[non,3,200000]=22504.0
erreur[x,y,z,t]=[x,y,z,t] : nombre de parametres invalide
erreur[x,2,200000]=[x,2,200000] : 1er parametre invalide
erreur[oui,x,200000]=[oui,x,200000] : 2ieme parametre invalide
erreur[oui,2,x]=[oui,2,x] : 2ieme parametre invalide