[XML-SIG] Simple wxPython XSLT Testing Tool using MSXML

Clark C. Evans cce@clarkevans.com
Wed, 28 Mar 2001 01:33:11 -0500 (EST)


Title says it all... I was wondering if Uche or someone
else would replace "TransformStage" so that it used
the FourThought XSLT processor...

One item... the file "msxml" is generated using makepy,
I'm opting for the "very static" approach; this could
be written to use the dynamic methods as detailed on P204
of the Python Programming On Windows.  I'm not using
this method since I have a very small stripped down
"msxml" that only has the items I need for my program.

This is a development tool that I've been using to 
test XSLT.  

Share & Enjoy,

Clark

P.S.  coding comments would be greatly apprechiated
      as I'm relatively new to python....

...

import sys, os
import msxml
import pythoncom
from   wxPython.wx         import *
from   wxPython.html       import *
from   wxPython.lib        import wxpTag

class OutputHtmlWindow(wxHtmlWindow):
    def __init__(self, parent, id):
        wxHtmlWindow.__init__(self, parent, id)

    def OnLinkClicked(self, linkinfo):
        self.base_OnLinkClicked(linkinfo)

    def OnSetTitle(self, title):
        self.base_OnSetTitle(title)

class OpenFileLine(wxWindow):
    def __init__(self,parent,id,pos,mode,label):
        wxWindow.__init__(self,parent,id,pos,wxSize(400,30))
        self.mode = mode
        wxStaticText(self, -1, label,
wxPoint(0,5),wxSize(75,25),wxALIGN_RIGHT)
        self.text = wxTextCtrl(self,-1,"",wxPoint(75,0),wxSize(200,25))
        wxButton(self,10,"Change",wxPoint(275,0))
        EVT_BUTTON(self, 10, self.OnClick)
        EVT_SET_FOCUS

    def OnClick(self, event):
        dlg = wxFileDialog(self, "Choose a file", ".", "*.*",
"*.xml,*.xslt,*.xsl,*.html,*.xhtml", self.mode)
        if dlg.ShowModal() == wxID_OK:
            if os.path.exists(dlg.GetPath()):
                self.text.SetValue(dlg.GetPath())
        dlg.Destroy()

    def OnSetFocus(self,event):
        wxMessageBox("Focus!")
        self.text.SetFocus()

    def SetValue(self,str):
        self.text.SetValue(str)
        self.text.SetInsertionPoint(0)

    def GetValue(self): return self.text.GetValue()


class OpenFileDlg(wxDialog):
    def __init__(self, parent,mode):
        if mode is wxOPEN:
            wxDialog.__init__(self,parent, -1, "Open Files",
wxDefaultPosition, wxSize(450, 250))
        else:
            if mode is wxSAVE:
                wxDialog.__init__(self,parent, -1, "Save Files",
wxDefaultPosition, wxSize(450, 250))
            else:
                raise TypeError("Expected wxOpen or wxSave")
        self.mode = mode
        self.metaxslt = OpenFileLine(self,-1,wxPoint(20,5),self.mode,"Meta
X&SLT:")
        self.metadata =
OpenFileLine(self,-1,wxPoint(20,35),self.mode,"Meta D&ATA:")
        self.mainxslt =
OpenFileLine(self,-1,wxPoint(20,65),self.mode,"Main &XSLT:")
        self.maindata =
OpenFileLine(self,-1,wxPoint(20,95),self.mode,"Main &DATA:")
        self.output   =
OpenFileLine(self,-1,wxPoint(20,125),self.mode,"&Output:")
        wxButton(self, wxID_OK,     " OK ", wxPoint(75, 175),
wxDefaultSize).SetDefault()
        wxButton(self, wxID_CANCEL, " Cancel ", wxPoint(200, 175),
wxDefaultSize)

    def ReadNames(self,conf):
        self.metaxslt.SetValue(conf.Read("metaxslt"))
        self.metadata.SetValue(conf.Read("metadata"))
        self.mainxslt.SetValue(conf.Read("mainxslt"))
        self.maindata.SetValue(conf.Read("maindata"))
        self.output.SetValue(conf.Read("output"))

    def WriteNames(self,conf):
        conf.Write("metaxslt",self.metaxslt.GetValue())
        conf.Write("metadata",self.metadata.GetValue())
        conf.Write("mainxslt",self.mainxslt.GetValue())
        conf.Write("maindata",self.maindata.GetValue())
        conf.Write("output",self.output.GetValue())

class MainFrame(wxFrame):
    def __init__(self, parent, ID, title):
        ID_ABOUT = 101
        ID_OPEN  = 102
        ID_SAVE  = 103
        ID_META  = 104
        ID_TRAN  = 105
        ID_PRINT = 106
        ID_EXIT  = 107

        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition, wxSize(600, 400))

        self.CreateStatusBar()
        self.SetStatusText("This is the statusbar")
        menu = wxMenu()
        menu.Append(ID_ABOUT, "&About",
                    "More information about this program")
        menu.Append(ID_OPEN, "&Open\tCtrl+O",
                    "Open files.")
        menu.Append(ID_SAVE, "&Save\tCtrl+S",
                    "Save files." )
        menu.Append(ID_TRAN, "&Transform\tCtrl+T",
                    "Run XSLT Transform")
        menu.Append(ID_META, "&Meta\tCtrl+M",
                    "Show meta frame")
        menu.Append(ID_PRINT, "&Print\tCtrl+P",
                    "Print HTML." )
        menu.AppendSeparator()
        menu.Append(ID_EXIT, "E&xit", "Terminate the program")
        menuBar = wxMenuBar()
        menuBar.Append(menu, "&File");
        self.SetMenuBar(menuBar)
        EVT_MENU(self, ID_ABOUT, self.OnAbout)
        EVT_MENU(self, ID_OPEN,  self.OnOpen)
        EVT_MENU(self, ID_SAVE,  self.OnSave)
        EVT_MENU(self, ID_META,  self.ShowMeta)
        EVT_MENU(self, ID_EXIT,  self.TimeToQuit)
        EVT_MENU(self, ID_PRINT, self.OnPrint)
        EVT_MENU(self, ID_TRAN,  self.OnTransform)

        self.primary    = wxSplitterWindow(self,-1,wxDefaultPosition,
wxDefaultSize, wxSP_3D)
        self.meta       =
wxSplitterWindow(self.primary,-1,wxDefaultPosition,  wxDefaultSize,
wxSP_3D)
        self.metaxslt  = wxTextCtrl(self.meta, -1, "", wxDefaultPosition,
wxDefaultSize,
                                     wxTE_MULTILINE|wxSUNKEN_BORDER)
        self.metadata  = wxTextCtrl(self.meta, -1, "", wxDefaultPosition,
wxDefaultSize,
                                     wxTE_MULTILINE|wxSUNKEN_BORDER)
        self.meta.SplitHorizontally(self.metaxslt,self.metadata)
        self.meta.SetMinimumPaneSize(100)
        self.meta.Show(0)

        self.secondary  =
wxSplitterWindow(self.primary,-1,wxDefaultPosition,  wxDefaultSize,
wxSP_3D)

        self.main       =
wxSplitterWindow(self.secondary,-1,wxDefaultPosition, wxDefaultSize,
wxSP_3D)
        self.mainxslt  = wxTextCtrl(self.main, -1, "", wxDefaultPosition,
wxDefaultSize,
                                     wxTE_MULTILINE|wxSUNKEN_BORDER)
        self.maindata  = wxTextCtrl(self.main, -1, "", wxDefaultPosition,
wxDefaultSize,
                              wxTE_MULTILINE|wxSUNKEN_BORDER)
        self.main.SplitHorizontally(self.mainxslt,self.maindata)
        self.main.SetMinimumPaneSize(100)

        self.out        =
wxSplitterWindow(self.secondary,-1,wxDefaultPosition, wxDefaultSize,
wxSP_3D)
        self.output   = wxTextCtrl(self.out, -1, "", wxDefaultPosition,
wxDefaultSize,
                                     wxTE_MULTILINE|wxSUNKEN_BORDER)
        self.html = OutputHtmlWindow(self.out, -1)
        self.html.SetRelatedFrame(self, "wxXSLT: %s")
        self.html.SetRelatedStatusBar(0)

        self.out.SplitHorizontally(self.output,self.html)
        self.out.SetMinimumPaneSize(100)

        self.primary.SplitVertically(self.meta,self.secondary)
        self.primary.SetMinimumPaneSize(0)
        self.primary.SetSashPosition(0)

        self.secondary.SplitVertically(self.main,self.out)
        self.secondary.SetMinimumPaneSize(50)
        self.secondary.SetSashPosition(300)
        self.main.SetSashPosition(200)
        self.out.SetSashPosition(200)
        self.meta.SetSashPosition(200)

        self.LoadFrames()

    def ShowMeta(self,event):
        if self.meta.IsShown():
            self.meta.Show(0)
            self.primary.SetSashPosition(0)
        else:
            self.meta.Show(1)
            size = self.GetSize()
            self.primary.SetSashPosition(size.width/3)

    def OnAbout(self, event):
        dlg = wxMessageDialog(self, "This program can be used to\n"
                              "test XSLT within a Python Environment.",
                              "About Me", wxOK | wxICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def TimeToQuit(self, event):
        self.Close(true)

    def OnPrint(self, event):
        printer = wxHtmlEasyPrinting()
        printer.PrintFile(self.html.GetOpenedPage())

    def LoadFrames(self):
        conf = wxConfig("PythonXSLTTester")
        def Load(ctl,conf,str,bad):
            try:
                 if conf.Read(str):
                     file = open(conf.Read(str),"r")
                     ctl.SetValue(file.read())
                     file.close()
                 else:
                     ctl.SetValue("")
                 return bad
            except IOError, value:
                return "%s\n%s" % (bad,value)

        bad = Load(self.metaxslt,conf,"metaxslt","")
        bad = Load(self.metadata,conf,"metadata",bad)
        bad = Load(self.mainxslt,conf,"mainxslt",bad)
        bad = Load(self.maindata,conf,"maindata",bad)
        bad = Load(self.output,conf,"output",bad)
        if bad:
            wxMessageBox(bad,"Could Not Open One Or More Files")

    def OnOpen(self,event):
        win = OpenFileDlg(self,wxOPEN)
        conf = wxConfig("PythonXSLTTester")
        win.ReadNames(conf)
        val = win.ShowModal()
        if val == wxID_OK:
            win.WriteNames(conf)
            self.LoadFrames()

    def OnSave(self,event):
        conf = wxConfig("PythonXSLTTester")
        def Save(ctl,conf,str,bad):
            try:
                 if conf.Read(str):
                     val = ctl.GetValue()
                     if val:
                         file = open(conf.Read(str),"w")
                         file.write(val)
                         file.close()
                 return bad
            except IOError, value:
                return "%s\n%s" % (bad,value)

        bad = Save(self.metaxslt,conf,"metaxslt","")
        bad = Save(self.metadata,conf,"metadata",bad)
        bad = Save(self.mainxslt,conf,"mainxslt",bad)
        bad = Save(self.maindata,conf,"maindata",bad)
        bad = Save(self.output,conf,"output",bad)
        if bad:
            wxMessageBox(bad,"Could Not Save One Or More Files")

    def ErrorToString(self,hr,msg,exc,arg):
        ret = "%d: %s" % (hr,msg)
        if exc:
            wcode, source, text, helpFile, helpID, scode = exc
            ret = "%s\nSource: %s\nText: %s" % (ret, source,text)
        return ret

    def OnTransform(self,event):
        if self.meta.IsShown():
            temp =
self.TransformStage(self.metaxslt.GetValue(),self.metadata.GetValue())
            if temp:
                self.mainxslt.SetValue(temp)
            else:
                return
        temp =
self.TransformStage(self.mainxslt.GetValue(),self.maindata.GetValue())
        if temp:
            self.output.SetValue(temp)
            try:
                self.html.SetPage(temp)
            except: pass

    def TransformStage(self,xslt,data):
        try:
            domxslt =
msxml.DOMDocument.default_interface(msxml.FreeThreadedDOMDocument())
            domdata =
msxml.DOMDocument.default_interface(msxml.DOMDocument())

            domdata.validateOnParse = 0
            domdata.async = 0
            domdata.preserveWhiteSpace = 1


            domxslt.validateOnParse = 1
            domxslt.async = 0
            domxslt.preserveWhiteSpace = 1

            try:
                domdata.loadXML(data)
            except pythoncom.com_error, ( hr, msg, exc, arg ):
                wxMessageBox("%s\n\n%s\nline:%d col:%d\ntext: %s" %
                             ( self.ErrorToString(hr,msg,exc,arg),
                               domdata.parseError.reason,
                               domdata.parseError.line,
                               domdata.parseError.linepos,
                               domdata.parseError.srcText), "Error Parsing
Data")
                return None

            try:
                domxslt.loadXML(xslt)
            except pythoncom.com_error, ( hr, msg, exc, arg):
                wxMessageBox("%s\n\n%s\nline:%d col:%d\ntext: %s" %
                             ( self.ErrorToString(hr,msg,exc,arg),
                               domdata.parseError.reason,
                               domdata.parseError.line,
                               domdata.parseError.linepos,
                               domdata.parseError.srcText), "Error Parsing
XSLT")
                return None


            templ =
msxml.XSLTemplate.default_interface(msxml.XSLTemplate())
            templ.stylesheet = domxslt
            proc = templ.createProcessor()
            proc.input = domdata
            proc.transform()
            return proc.output.encode("ISO8859-1")
        except pythoncom.com_error, ( hr, msg, exc, arg):
            wxMessageBox(self.ErrorToString(hr,msg,exc,arg), "Error
Transforming")
            return None

class TheApp(wxApp):
    def OnInit(self):
        frame = MainFrame(NULL, -1, "Python XSLT Testing Tool")
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

if __name__ == '__main__':
    app = TheApp(0)
    app.MainLoop()