#!/usr/bin/python2 import string from xml.sax import handler class Operation: """Класс для хранения операции с операндами""" def __init__(self): self._operands = [] def set_type(self, type): self._type = type def set_operand(self, operand): self._operands.append(operand) def eval(self): return eval(str(self)) def __str__(self): """Представление операции в виде строки""" if len(self._operands) == 1: return "(%s(%s))" % (self._operands, self._type) else: return "(%s)" % string.join( map(str, self._operands), str(self._type)) class ContentHandler(handler.ContentHandler): """Класс, методы которого вызываются для обработки событий""" def __init__(self): self.cur_data = "" # накопитель данных self.stack = [] # стек для хранения отложенных операций self.value = None # текущее значение def startElement(self, name, attrs): """Встретился открывающий тег name""" if name == "operation": self.stack.append(Operation()) elif name == "operand": self.value = None self.cur_data = "" def endElement(self, name): """Встретился закрывающий тег name""" if name == "expression": self.value = str(self.value.eval()) elif name == "operation": self.value = self.stack.pop() elif name == "type": self.stack[-1].set_type(self.cur_data.strip()) elif name == "operand": self.value = self.value or self.cur_data.strip() self.stack[-1].set_operand(self.value) self.cur_data = "" def characters(self, data): """Встретились "межтеговые" данные""" self.cur_data += data # Эти классы тоже можно было бы переопределить, но # мы оставим их как есть: # обработчик ошибок, ссылок на сущности и событий DTD-части class ErrorHandler(handler.ErrorHandler): pass class EntityResolver(handler.EntityResolver): pass class DTDHandler(handler.DTDHandler): pass