Example #1
0
class UploadXMLHandler(DefaultHandler2):
    """Класс SAX-парсера, производящий разбор xml и вставку данных в таблицу"""

    parentTag = None
    currentCell = None
    flag = 0
    currentString = u''
    currentEncoding = u"utf8"

    def __init__(self, tableInstance, action):
        self.tableInstance = tableInstance

        # возможность настраивать, нужно ли обновлять записи и вставлять новые
        def actionUI(ins):
            if not ins.tryInsert():
                ins.update()

        def actionU(ins):
            ins.tryUpdate()

        def actionI(ins):
            ins.tryInsert()

        # определяем, какую функцию нам нужно использовать
        self.funcAction = locals()['action%s' % action.upper()]

    def startElement(self, namespaceURI, lname, qname, attrs):

        if self.parentTag == 'field':
            if self.flag == 0:
                self.stringWriter = StringWriter()
                self.xmlWriter = XMLOutputFactory.newInstance(
                ).createXMLStreamWriter(self.stringWriter, "UTF-8")
            self.flag += 1
            self.xmlWriter.writeStartElement(qname)
            for i in range(0, attrs.getLength()):
                self.xmlWriter.writeAttribute(attrs.getQName(i),
                                              attrs.getValue(i))
        elif qname == 'table' and self.flag == 0:
            if self.parentTag is not None:
                raise CelestaException(u"Неверный формат файла")

            self.parentTag = qname
            if not attrs.getValue('name'):
                raise CelestaException(
                    u"Атрибут 'name' отсутствует в теге 'table'")
            elif attrs.getValue('name') != self.tableInstance.meta().getName():
                raise CelestaException(
                    u"Имя таблицы %s не соответствует значению атрибута 'name'"
                    % self.tableInstance.meta().getName())
        elif qname == 'row' and self.flag == 0:
            if self.parentTag != 'table':
                raise CelestaException(u"Неверный формат файла")
            self.parentTag = qname
        elif qname == 'field' and self.flag == 0:
            if self.parentTag != 'row':
                raise CelestaException(u"Неверный формат файла")
            self.currentEncoding = attrs.getValue('encoding') or u"utf8"
            self.currentCell = attrs.getValue('name')
            self.parentTag = qname
            self.currentString = u''
        else:
            raise CelestaException(u"Неверный формат файла")

    def endElement(self, uri, lname, qname):
        if qname == 'table' and self.flag == 0:
            self.parentTag = None
        elif qname == 'row' and self.flag == 0:
            # обновляем или вставляем записи
            self.funcAction(self.tableInstance)
            self.tableInstance.clear()
            self.parentTag = 'table'
        elif qname == 'field' and self.flag == 0:
            # Вставка данных в поле таблицы, отдельно рассмотрен случай если данные в формате XML
            if hasattr(self, 'stringWriter') and self.stringWriter:
                self.xmlWriter.close()
                # Вставка данных в поле типа blob
                if self.tableInstance.meta().columns[
                        self.currentCell].getCelestaType() == 'BLOB':
                    getattr(self.tableInstance, "calc%s" % self.currentCell)()
                    blobField = self.tableInstance.__dict__[
                        self.currentCell].getOutStream()
                    blobField.write(self.stringWriter.strip())
                else:
                    self.tableInstance.__setattr__(
                        self.currentCell, self.stringWriter.toString())
                self.stringWriter.flush()
                self.stringWriter = None
                self.xmlWriter = None
            else:
                # проверка на None
                if self.currentString.strip() != 'None':
                    self.currentString = self.currentString.strip()
                    # Вставка данных в поле типа blob
                    if self.tableInstance.meta().columns[
                            self.currentCell].getCelestaType() == 'BLOB':
                        getattr(self.tableInstance,
                                "calc%s" % self.currentCell)()
                        blobField = self.tableInstance.__dict__[
                            self.currentCell].getOutStream()
                        if self.currentEncoding == u"utf8":
                            blobField.write(self.currentString)
                        elif self.currentEncoding == u"base64":
                            blobField.write(
                                base64.b64decode(self.currentString))
                        else:
                            raise CelestaException(u"Неверная кодировка")
                    elif self.tableInstance.meta().columns[
                            self.currentCell].getCelestaType() == 'DATETIME':
                        sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
                        self.tableInstance.__setattr__(
                            self.currentCell, sdf.parse(self.currentString))
                    elif self.tableInstance.meta().columns[
                            self.currentCell].getCelestaType() == 'BIT':
                        self.tableInstance.__setattr__(
                            self.currentCell,
                            self.currentString.lower() == "true")
                    else:
                        if self.currentCell == 'prefix':
                            pass
                        self.tableInstance.__setattr__(self.currentCell,
                                                       self.currentString)
            self.parentTag = 'row'
            self.currentCell = None
            self.currentString = None
        elif self.parentTag == 'field':
            self.xmlWriter.writeEndElement()
            self.flag -= 1

    def characters(self, ch, start, length):
        if self.parentTag == 'field' and self.flag > 0:
            self.xmlWriter.writeCharacters(ch, start, length)
        elif self.currentCell:
            self.currentString += unicode(String(ch[start:start + length]))

    def comment(self, ch, start, length):
        if self.parentTag == 'field' and self.flag > 0:
            self.xmlWriter.writeComment(ch.tostring()[start:start + length])

    def startPrefixMapping(self, prefix, uri):
        if self.parentTag == 'field' and self.flag > 0:
            if prefix == "":
                self.xmlWriter.setDefaultNamespace(uri)
            else:
                self.xmlWriter.setPrefix(prefix, uri)

    def processingInstruction(self, target, data):
        if self.parentTag == 'field' and self.flag > 0:
            self.xmlWriter.writeProcessingInstruction(target, data)

    def skippedEntity(self, name):
        if self.parentTag == 'field' and self.flag > 0:
            self.xmlWriter.writeEntityRef(name)