Skip to content

15. تمرين [حساب الضرائب] باستخدام XML

في هذا التمرين، الذي تناولناه مرارًا وتكرارًا، يعيد الخادم النتائج إلى العميل في شكل دفق XML:

  • <response><error>msg</error></response> في حالة حدوث خطأ؛
  • <response><tax>value</tax></response> إذا أمكن حساب الضريبة.

نستخدم ما تعلمناه للتو حول تحليل مستند XML.

15.1. خدمة الويب

لا تختلف خدمة الويب هذه عن تلك التي تمت دراستها سابقًا، باستثناء أن استجابة XML المرسلة إلى العميل تختلف قليلاً. وتبقى البنية كما هي:


خدمة الويب (impots_web_02)

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

#    -*- coding=Utf-8 -*-
#    import of Impots* class module
from impots import *
import cgi,cgitb,re

#    allow debugging information to be displayed
cgitb.enable()

# ------------------------------------------------ 
#  tax web service
# ------------------------------------------------ 

#  the data required to calculate the tax has been placed in table mysqL TABLE
#  belonging to the BASE database. The table has the following structure
#    limits decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2)
#  taxable person parameters (marital status, number of children, annual salary)
#  are sent by the customer in the form params=marital status, number of children, annual salary
#  results (marital status, number of children, annual salary, tax payable) are returned to the customer
#  in the form <impot>value</impot>
#  or as <error>msg</error>, if parameters are invalid

#  the server returns unformatted text to the client
print "Content-Type: text/plain\n"
#    start of answer
print "<reponse>"

#    definition of constants
USER="root"
PWD=""
HOTE="localhost"
BASE="dbimpots"
TABLE="impots"

#    instantiation layer [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()

#  retrieve the line sent by the client to the server
params=cgi.FieldStorage().getlist('params')
#  if no parameters then error
if not params:
    print "<erreur>Le parametre [params] est absent<erreur></reponse>"
    sys.exit()

#  we use the params parameter  
#   print "parameters received --> %s\n" %(params)
items=params[0].strip().lower().split(',')
#  there must be only 3 fields
if len(items)!=3:
    print "<erreur>[%s] : nombre de parametres invalide</erreur></reponse>" % (params[0])
    sys.exit()
#  first parameter (marital status) must be yes/no
marie=items[0].strip()
if marie!="oui" and marie != "non":
    print "<erreur>[%s] : 1er parametre invalide</erreur></reponse>\n"% (params[0])
    sys.exit()
#  the second parameter (number of children) must be an integer
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])
#  the third parameter (salary) must be an integer
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])
#  tax calculation
impot=metier.calculer(marie,enfants,salaire)
#  return the result
print "<impot>%s</impot></reponse>\n" % (impot)
#    end

ملاحظات:

تختلف هذه الخدمة الإلكترونية عن الخدمة السابقة فقط في طبيعة استجابتها:

<response><error>msg</error></response> في حالة حدوث خطأ بدلاً من <error>msg</error>

<response><tax>value</tax></response> إذا أمكن حساب الضريبة بدلاً من <tax>value</tax>

15.2. تطبيق العميل

يجب على عميلنا تحليل استجابة XML المرسلة من خدمة الويب. نطبق ما تعلمناه في تحليل مستند XML.


البرنامج (client_impots_web_02)

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

import httplib,urllib,re
import xml.sax, xml.sax.handler
#    management class XML
class XmlHandler(xml.sax.handler.ContentHandler):

    #  function called when a start tag is encountered
    def startElement(self,name,attributs):
        #  note the current element
        global elementcourant
        elementcourant=name.strip().lower()

    #  the function called when an end tag is encountered
    def endElement(self,name):
        #    we do nothing
        pass

    #  the data management function
    def characters(self,data):
        #    data
        global elementcourant,elements

        #  data are retrieved
        match=re.match(r"^\s*(.+?)\s*$",data)
        if match:
            elements[elementcourant]=match.groups()[0].lower()

def getResultatsXml(reponse):
    #  we analyze the XML response
    xml.sax.parseString(reponse,XmlHandler())
    #  we return the results
    if elements.has_key('erreur'):
        return (elements['erreur'],"")
    else:
        return ("",elements['impot'])

#    ------------------------------------------------------------ main
#    constant
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 variables
elementcourant=""
elements={}

#    connection
connexion=httplib.HTTPConnection(HOST)
#    follow-up
#   connexion.set_debuglevel(1)
#  loop over the data to be sent to the server
for params in data:
    #  parameters must be encoded before being sent to the server
    parametres = urllib.urlencode({'params': params})
    #  send request
    connexion.request("POST",URL,parametres)
    #    response processing (stream XML)
    reponse=connexion.getresponse().read()
    #    xml file processing
    (erreur,impot)=getResultatsXml(reponse)
    if not erreur:
        print "impot[%s]=%s" % (params,impot)
    else:
        print "erreur[%s]=%s" % (params,erreur)

ملاحظات:

  • تتم معالجة موجز XML من خدمة الويب بواسطة الدالة getResultatsXml (السطر 60)؛
  • السطر 29: دالة getResultatsXml؛
  • السطر 31: يتم تحليل استجابة XML لخدمة الويب بواسطة مثيل لفئة XmlHandler المحددة في السطر 6؛
  • السطر 6: تنفذ فئة XmlHandler الطرق الثلاث startElement و endElement و characters. باستخدام هذه الطرق الثلاث، يتم إنشاء قاموس. المفاتيح هي أسماء العلامات <error> و <import>، والقيم هي البيانات المرتبطة بهاتين العلامتين؛
  • الأسطر 33–36: تُرجع الدالة getResultatsXml مجموعة ذات عنصرين:
    • (error, "") إذا اكتشف تحليل دفق XML العلامة <error>. يمثل error عندئذ محتوى هذه العلامة؛
    • ("", impot) إذا كشف تحليل دفق XML عن وجود علامة <impot>. عندئذٍ يمثل impot محتوى هذه العلامة.
  • السطر 60: يتم استرداد نتيجة دالة getResultatsXml ثم معالجتها في الأسطر 61–64.

15.3. النتائج

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