diff options
Diffstat (limited to 'src/XmlParser.py')
-rw-r--r-- | src/XmlParser.py | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/src/XmlParser.py b/src/XmlParser.py new file mode 100644 index 0000000..1af755b --- /dev/null +++ b/src/XmlParser.py @@ -0,0 +1,449 @@ +# -*- coding: iso-8859-1 -*- + +######################################### +######## PARSER XML ##################### +######################################### + +# imports +import sys +import os +import math +import string +import random + +#test du module expat +try: + from xml.parsers import pyexpat +except ImportError: + # Possibly the pyexpat module hasn't been installed; we may be + # running an initial "make test" just after compiling the + # package. Try importing pyexpat directly. + import pyexpat + + +## +# classe entry +# cette classe est un representation d'un noeud en xml (entree) +# +class entry: + + ## + # methode __init__ + # methode initialisant les attributs de la classe + # + def __init__(self): + self.type = '' # Type de la données (déclarée dans DTD) + self.name = '' # Nom de la donnée : si Présence de l'attribut 'name' + self.cdata = '' # Données CDATA de l'élément (entre la balise ouvrante et la balise fermante + self.attribs = {} # Attributs : Clé nom de l'attribut + self.entries = [] # Liste des sous éléments + self.namedentries = {} # Dictionnaire des sous éléments nommés (recherche accélérée) + + ## + # methode setname + # mutateur de l'attribut name + # @param name : nom du noeud + # + def setname(self, name): + self.name = name + + ## + # methode getname + # accesseur à l'attribut name + # @return self.name + # + def getname(self): + return self.name + + ## + # methode setcdata + # mutateur de l'attribut cdata + # @param cdata : données entre balise ouvrantes et fermantes + # + def setcdata(self, cdata): + self.cdata = cdata + + ## + # methode getcdata + # accesseur à l'attribut cdata + # @return self.cdata + # + def getcdata(self): + return self.cdata + + ## + # methode setattribs + # mutateur de l'attribut attribs + # @param attribs : attribut du noeuds + # + def setattribs(self, attribs): + self.attribs = attribs + + ## + # methode getattribs + # accesseur à l'attribut attribs + # @return self.attribs + # + def getattribs(self): + return self.attribs + + ## + # methode hasattrib + # methode verifiant si un attribut de nom attribname est dans la liste des attributs + # @param attribname : nom de l'attribut + # @return true ou false + # + def hasattrib(self, attribname): + if self.attribs.has_key (attribname): + return 1 + else: + return 0 + + ## + # methode findattrib + # methode recherchant un attribut dans la liste et renvoyant sa valeur ou la valeur par default en cas d'abscense + # @param attribname : nom de 'attribut dont on charche la valeur + # @param defaultvalue :valeur a retourner en cas d'abscence de l'attribut + # @return valeur de l'attribut ou la valeur par default + # + def findattrib(self, attribname, defaultvalue): + if self.attribs.has_key (attribname): + return self.attribs[attribname] + else: + return defaultvalue + + ## + # methode findforceattrib + # methode cherchant la valeur d'un attribut et forçant une valeur non nulle comme valeur de retour + # @param attribname: nom de l'attribut + # @param defalutvalue : valeur par default + # @return une valeur non nulle + # + def findforceattrib(self, attribname, defaultvalue): + if self.attribs.has_key (attribname): + ret = self.attribs[attribname] + if ret == None or ret == "": + return defaultvalue + return ret + else: + return defaultvalue + + ## + # methode settype + # mutateur de l'attribut type + # @param type : le type du noeud + # + def settype(self, type): + self.type = type + + ## + # methode gettype + # accesseur à l'attribut type + # @return le type du noeud + # + def gettype(self): + return self.type + + ## + # methode addentry + # methode ajoutant une entry à la liste des sous noeuds + # @param entry : reference au noeud + # @param name : nom du noeuds + # + def addentry(self, entry, name): + self.entries.append (entry) + if name != "": + self.namedentries[name] = entry + + ## + # methode printlevel_recurs + # methode affichant recursivement les attributs se trouvant sous le noeud + # @param level : le niveau du noeud pour debuter l'affichage + # + def printlevel_recurs(self, level): + #affichage des attributs. + space = ' '*level + attstr = '' + for attkey in self.attribs.keys (): + attrib = self.attribs[attkey] + attstrloc = attkey + ' = ' + attrib + ', ' + attstr = attstr + attstrloc + toprint = space + 'Node type : ' + self.type + ', CData : ' + self.cdata + ', Attributes : ' + attstr + try: + print toprint + except: + print "##################################################" + print "Erreur de DUMP" + print self.__dict__ + print "##################################################" + + #affichage des fils. + for entry in self.entries: + entry.printlevel_recurs (level + 1) + + ## + # methode findentry + # methode recherchant un noeud dans la liste des sous noeuds en utilisant son type, un attribut et la valeur de celui-ci + # @param entrytype : type du noeuds recherche + # @param attribname : nom de l'attribut rechercher + # @param attribvalue : valeur de l'attribut + # @return l'attribut trouve ou None + # + def findentry(self, entrytype, attribname, attribvalue): + for entry in self.entries: + if entry.type == entrytype: + if entry.attribs.has_key (attribname): + attrib = entry.attribs[attribname] + if attrib == attribvalue: + return entry + return None + + ## + # methode findtype + # methode rechercahant un noeuds en fnction de son type + # @param entrytype : type du noeud + # @return le noeud ou None + # + def findtype(self, entrytype): + for entry in self.entries: + if entry.type == entrytype: + return entry + return None + + ## + # methode findnamedentry + # methode recherchant un noeud par son nom + # @param entryname : nom du noeud + # @return le noeud ou None + # + def findnamedentry(self, entryname): + if self.namedentries.has_key (entryname): + return self.namedentries[entryname] + else: + return None + + + +# +# Cette classe implemente un l'objet issue de la configuration +# + +## +# classe property_server +# cette classe est en charge de parser le fichier xml et de fournir les informations +# contenu dans le fichiers +# +class property_server: + + ## + # methode __init__ + # initialisation des attributs + # + def __init__(self): + self.configurationread = 0 + self.verbose = 0 + # Parametres de la ligne de commande + self.config_file = 'Message.xml' + self.messageDict = {} + self.regexpDict = {} + + ## + # methode setconfigfile + # mutateur de l'attribut config_file contenant le nom du fichier xml + # @param configfile : nouveau nom du fichier à parser + # + def setconfigfile (self, configfile): + self.config_file = configfile + + ## + # methode readconfig + # methode lisant et parsant le fichier xml + # @param verbose : falg d'affichage du resultat du parsing + # + def readconfig (self, verbose=0): + if self.configurationread != 0: + return + + self.verbose = verbose + self.configurationread = 1 + self.out = Outputter() + self.parser = pyexpat.ParserCreate() + self.parser.StartElementHandler = self.out.startelt + self.parser.EndElementHandler = self.out.endelt + self.parser.CharacterDataHandler = self.out.cdata + self.parser.ProcessingInstructionHandler = self.out.inst + if self.verbose == 1: + print ("Configuration file used : %s" % self.config_file) + self.data = open (self.config_file).read() + self.rv = self.parser.Parse (self.data, 1) + + if self.verbose == 1: + print ("Parser returned %s" % self.rv) + if self.rv == 0: + print ("** Error %s" % self.parser.ErrorCode) + print ("** Line %s" % self.parser.ErrorLineNumber) + print ("** Column %s" % self.parser.ErrorColumnNumber) + print ("** Byte %s" % self.parser.ErrorByteIndex) + print ('Summary of XML parser upcalls:') + print ("start elements: %s" % self.out.startcount) + print ("end elements: %s" % self.out.endcount) + print ("character data: %s" % self.out.cdatacount) + print ("processing instructions: %s" % self.out.instcount) + print ('browsing Tree') + + self.root = self.out.getroot () + + if self.verbose == 1: + self.root.printlevel_recurs (1) + + ## + # methode readMessages + # parsing des messages et regular expressions + # rangement des regexp et messages dans des dictionanires + # + def readMessages(self): + root = self.root.findtype("ivytester") + messages = root.findtype("messages") + i = 0 + for entry in messages.entries: + regexp = entry.findtype("regexp") + msg = entry.findtype("msg") + self.regexpDict[i] = regexp.findattrib("value","") + self.messageDict[i] = msg.findattrib("value","") + i = i+1 + + self.dictionnarySize = i + + ## + # methode getRandomMessage + # methode renvoyant aleatoirement un message du dictionnaire + # @return une string contenant le message à envoyer + # + def getRandomMessage(self): + value = random.randint(0, self.dictionnarySize-1) + return self.messageDict[value] + + ## + # methode getDictionnarySize + # methode renvoyant la taille des dictionnaires + # @return int repesentant le nombre d'element dans les dictionnaires regex et messages + # + def getDictionnarySize(self): + return self.dictionnarySize + + ## + # methode getMessages + # accesseur au dictionnaire de messages + # @return le dictionnaire de message + # + def getMessages(self): + return self.messageDict + + ## + # methode getRegexp + # accesseur au dictionnaire de regexp + # @return le dictionnaire de regexp + # + def getRegexp(self): + return self.regexpDict + + +## +# classe Outputter +# classe permettant la recuperation du parsing du fichier xml +# +class Outputter: + + ## + # methode __init__ + # initialisation des attributs + # + def __init__(self): + self.startcount = 0 + self.endcount = 0 + self.cdatacount = 0 + self.instcount = 0 + self.indlevel = 0 + self.currlevel = {} + new_entry = entry () + self.currlevel[self.indlevel] = new_entry + + ## + # methode startelt + # callaback de recuperation de l'element parse + # @param type : type du noeuds + # @param attrs : attribut du noeuds + # + def startelt(self, type, attrs): + father = self.currlevel[self.indlevel] + self.indlevel = self.indlevel + 1 + new_entry = entry () + self.currlevel[self.indlevel] = new_entry + attribs = {} + name = '' + self.startcount = self.startcount + 1 + if (sys.version[:3] == "1.5"): + for i in range(0, len(attrs), 2): + attribs[attrs[i]] = attrs[i+1] + if attrs[i] == 'name': + name = attrs[i+1] + else: + for attkey in attrs.keys (): + attrib = attrs[attkey] + attribs[attkey] = attrib + if attkey == 'name': + name = attrib + + new_entry.settype (type) + new_entry.setname (name) + new_entry.setattribs (attribs) + if name == '': + father.addentry (new_entry, type) + else: + father.addentry (new_entry, name) + + ## + # methode endelt + # callback appele sur parsing du dernier element + # @param name : nom de l'element (non utilise) + # + def endelt(self, name): + self.indlevel = self.indlevel - 1 + self.endcount = self.endcount + 1 + + ## + # methode cdata + # callback de recuperation des characteres data + # @param data : les characteres data parses + # + def cdata(self, data): + new_entry = self.currlevel[self.indlevel] + new_entry.setcdata (data) + self.cdatacount = self.cdatacount + 1 + + ## + # methode inst + # methode recuperant les instructions de parsing + # @param target : cible de l'instruction + # @param data : donnees recuperees + # + def inst(self, target, data): + self.instcount = self.instcount + 1 + + ## + # methode getroot + # methode recuperrant le noeud racine de l'arbre + # @return noeud racine + # + def getroot(self): + return self.currlevel[0] + + +Properties = property_server () + +if __name__ == '__main__': + print "programme main" + Properties.setconfigfile ("Message.xml") + Properties.readconfig (verbose=0) + Properties.readMessages() + print Properties.getRandomMessage()
\ No newline at end of file |