Рубрики
Без рубрики

WXPYPHON: извлечение XML из RichTextCTRL

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Я недавно наткнулся на Stackoverflow вопрос Там, где парень спросил, как получить XML-данные Wxpython’s RichtextCtrl, чтобы он мог сохранить его в базе данных. Я не знаю много об этом контроле, но после быстрого поиска Google я нашел Статья С 2008 года дал мне необходимую информацию. Я взял этот пример и сократил его до следующего примера:

import wx
import wx.richtext

from StringIO import StringIO


########################################################################
class MyFrame(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, title='Richtext Test')

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.rt = wx.richtext.RichTextCtrl(self)
        self.rt.SetMinSize((300,200))

        save_button = wx.Button(self, label="Save")
        save_button.Bind(wx.EVT_BUTTON, self.on_save)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.rt, 1, wx.EXPAND|wx.ALL, 6)
        sizer.Add(save_button, 0, wx.EXPAND|wx.ALL, 6)

        self.SetSizer(sizer)
        self.Show()


    #----------------------------------------------------------------------
    def on_save(self, event):
        out = StringIO()
        handler = wx.richtext.RichTextXMLHandler()
        rt_buffer = self.rt.GetBuffer()
        handler.SaveStream(rt_buffer, out)
        self.xml_content = out.getvalue()
        print self.xml_content


#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

Давайте немного сломаемся. Сначала мы создаем наше прекрасное приложение и добавьте экземпляр RichTextCtrl Виджет в рамку вместе с кнопкой для сохранения того, что мы случаемся, чтобы написать в указанном виджете. Далее мы устанавливаем привязку для кнопки и макета виджетов. Наконец, мы создаем наш обработчик событий. Это где происходит волшебство. Здесь мы создаем Richtextxmlandler и возьмите буфер RichtextCTRL, чтобы мы могли выписать данные. Но вместо того, чтобы писать в файл, мы пишем в файловый объект, который является нашим Stringio пример. Мы делаем это, поэтому мы можем написать данные в память, а затем прочитать его обратно. Причина, по которой мы делаем это, заключается в том, что человек в штабелее будет способ извлечь XML, что RichTextCTRL генерирует и записывает его в базу данных. Сначала мы могли бы написать его на диск, а затем прочитать этот файл, но это менее грязно и быстрее.

Обратите внимание, однако, что если кто-то написал роман в RichTextCTRL, то это было бы плохой идеей! Хотя вполне вероятно, что у нас закончилось бы из комнаты, определенно много текстовых файлов, которые превышают память вашего компьютера. Если вы знаете, что файл, который вы загружаете, собирается занять много памяти, то вы не пойду на этот маршрут. Вместо этого вы бы читали и написали данные в кусках. Во всяком случае, этот код работает для того, что мы хотели сделать. Я надеюсь, что вы нашли это полезно. Это было, безусловно, было весело выяснить.

К сожалению, этот код примера не работает в ** wxpython phoenix **. В этом следующем разделе мы обновим пример, чтобы он будет!

Обновление для Phoenix/wxpython 4

Первая проблема, с которой вы столкнулись при запуске приведенного выше приведенного выше в WXPYHON 4 (AKA PHOENIX), это то, что Savestream Метод больше не существует. Вам нужно будет использовать SaveFile вместо. Другая проблема на самом деле одна введена Python 3. Если вы запустите этот код в Python 3, вы обнаружите, что Stringio Модуль не существует, и вам нужно будет использовать Ио вместо. Таким образом, для нашего следующего примера я обновил код для поддержки как Python 3, так и WxPython Phoenix. Давайте посмотрим, как это отличается:

# wxPython 4 (Phoenix) / Python 3 Version

import wx
import wx.richtext

from io import BytesIO


class MyFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title='Richtext Test')

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.rt = wx.richtext.RichTextCtrl(self)
        self.rt.SetMinSize((300,200))

        save_button = wx.Button(self, label="Save")
        save_button.Bind(wx.EVT_BUTTON, self.on_save)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.rt, 1, wx.EXPAND|wx.ALL, 6)
        sizer.Add(save_button, 0, wx.EXPAND|wx.ALL, 6)

        self.SetSizer(sizer)
        self.Show()

    def on_save(self, event):
        out = BytesIO()
        handler = wx.richtext.RichTextXMLHandler()
        rt_buffer = self.rt.GetBuffer()
        handler.SaveFile(rt_buffer, out)
        self.xml_content = out.getvalue()
        print(self.xml_content)


if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

Основные различия лежат в разделе импорта в начале и on_save метод. Вы отметите, что мы используем модуль IO Bytesio класс. Затем мы получаем остальные данные так же, как и раньше, за исключением того, где мы поменяем Savestream с SaveSile. XML, который напечатан, представляет собой двоичную строку, поэтому, если вы планируете проанализировать, что вам может потребоваться отбрасывать это в строку. У меня были некоторые анализаторы XML, которые не будут работать с бинарными строками правильно.

Упаковка

В то время как эта статья охватывает только экстракцию XML, вы можете легко расширить его для извлечения других форматов, которые поддерживает HTMLEXTCTRL, такие как HTML или сам богатый текстовый формат (RTF). Это может быть полезным инструментом, чтобы вам нужно было сохранить данные в вашем приложении к базе данных или в некоторых других хранилище данных.