#include "wx/wxprec.h"
#include "wx/xml2.h"
#include "wx/dtd.h"
#include <wx/sstream.h>
#include <wx/mstream.h>
#include <wx/xml/xml.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#if !defined(__WXMSW__) && !defined(__WXPM__)
#include "mondrian.xpm"
#endif
class MyApp : public wxApp
{
public:
virtual bool OnInit();
int OnExit();
};
enum
{
Minimal_Quit = wxID_EXIT,
Minimal_About = wxID_ABOUT,
Minimal_LoadXML,
Minimal_LoadDTD,
Minimal_SaveSimple,
Minimal_SaveAdv,
Minimal_SaveDTD,
Minimal_Valid
};
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title);
~MyFrame();
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
wxTextCtrl *m_text;
void LoadXML(const wxString &filename);
void LoadDTD(const wxString &filename);
void OnLoadXML(wxCommandEvent& event);
void OnLoadDTD(wxCommandEvent& event);
void OnValid(wxCommandEvent& event);
void OnSaveSimple(wxCommandEvent& event);
void OnSaveAdv(wxCommandEvent& event);
void OnSaveDTD(wxCommandEvent& event);
private:
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
EVT_MENU(Minimal_LoadXML, MyFrame::OnLoadXML)
EVT_MENU(Minimal_LoadDTD, MyFrame::OnLoadDTD)
EVT_MENU(Minimal_SaveSimple, MyFrame::OnSaveSimple)
EVT_MENU(Minimal_SaveAdv, MyFrame::OnSaveAdv)
EVT_MENU(Minimal_SaveDTD, MyFrame::OnSaveDTD)
EVT_MENU(Minimal_Valid, MyFrame::OnValid)
END_EVENT_TABLE()
IMPLEMENT_APP(MyApp)
#if defined(__VISUALC__) && defined(__WXDEBUG__)
#define mcDETECT_MEMORY_LEAKS
#endif
#ifdef mcDETECT_MEMORY_LEAKS
#include <crtdbg.h>
#define mcDUMP_ON_EXIT { _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); }
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
class mcLeakDetector {
public:
mcLeakDetector() { mcDUMP_ON_EXIT; }
~mcLeakDetector() {}
};
static mcLeakDetector detector;
#endif
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame(_T("Minimal wxWindows App"));
#if 1
wxLogWindow *pwindow = new wxLogWindow(frame, wxT("log"));
pwindow->GetFrame()->Move(50, 50+350);
pwindow->GetFrame()->SetSize(800, 300);
frame->Show(true);
#endif
wxXml2::Init();
return true;
}
int MyApp::OnExit()
{
wxXml2::Cleanup();
return 0;
}
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxPoint(50, 50), wxSize(500, 300))
{
SetIcon(wxICON(mondrian));
#if 1
m_text = new wxTextCtrl(this, -1,
wxT("This program will provide some examples about the three main operations ")
wxT("it provides on XML files:\n\n")
wxT("\t- Loading: wxXml2 allows you to load any XML file including DTDs.\n")
wxT("\t- Editing: wxXml2 allows you to create, edit, manipulate any XML file.\n")
wxT("\t- Saving: wxXml2 can saves XML trees or DTDs to memory buffers or to files."),
wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE);
m_text->SetBackgroundColour(*wxWHITE);
#endif
#if wxUSE_MENUS
wxMenu *menuFile = new wxMenu;
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
menuFile->Append(Minimal_LoadXML, _T("Load XML..."), _T("Loads the given file and tries to parse it..."));
menuFile->Append(Minimal_LoadDTD, _T("Load DTD..."), _T("Loads the given file and tries to parse it..."));
menuFile->AppendSeparator();
menuFile->Append(Minimal_SaveSimple, _T("Save a simple HTML file..."), _T("Creates a sample HTML file and saves it in the given location."));
menuFile->Append(Minimal_SaveAdv, _T("Save an advanced XHTML file..."), _T("Creates a sample XHTML file and saves it in the given location."));
menuFile->Append(Minimal_SaveDTD, _T("Save a DTD file..."), _T("Creates a sample DTD file and saves it in the given location."));
menuFile->AppendSeparator();
menuFile->Append(Minimal_Valid, _T("Validate against DTD..."), _T("Validates an XML file against a DTD."));
menuFile->AppendSeparator();
menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
wxMenuBar *menuBar = new wxMenuBar();
menuBar->Append(menuFile, _T("&File"));
menuBar->Append(helpMenu, _T("&Help"));
SetMenuBar(menuBar);
#endif // wxUSE_MENUS
#if wxUSE_STATUSBAR
CreateStatusBar(2);
SetStatusText(_T("Welcome to wxWindows!"));
#endif // wxUSE_STATUSBAR
}
MyFrame::~MyFrame()
{
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxString msg;
msg.Printf( wxT("This is a little demonstration of wxXml2 wrappers for libxml2.\n\n")
wxT("They are based on original Vaclav Slavik's design but they\n")
wxT("use libxml2 (which is a widely-used, powerful cross-platform\n")
wxT("library) instead of EXPAT.\n\n")
wxT("The classes were rewritten by Francesco Montorsi (frm@users.sourceforge.net)\n")
wxT("and this sample is a modified version of the minimal sample of wxWidgets.\n\n")
wxT("This sample program was compiled with libxml2 version %s."),
wxXml2::GetLibxml2Version().c_str());
wxMessageBox(msg, _T("About Minimal"), wxOK | wxICON_INFORMATION, this);
}
#define STEP 4
void ParseNode(const wxXml2Node &node, wxString &str, int n)
{
if (node == wxXml2EmptyNode) return;
wxLogDebug(wxT("ParseNode - parsing [%s]"), node.GetName().c_str());
wxString toadd, spaces(wxT(' '), n);
toadd = node.GetName();
if (node.GetType() == wxXML2_TEXT_NODE ||
node.GetType() == wxXML2_COMMENT_NODE ||
node.GetType() == wxXML2_CDATA_SECTION_NODE) {
wxString content = node.GetContent();
if (content.Last() == wxT('\n')) content.RemoveLast();
if (content.GetChar(0) == wxT('\n')) content.Remove(0, 1);
wxString tmp = content.Trim();
if (tmp.IsEmpty())
toadd += wxT("node: [null]");
else
toadd += wxT("node: ") + content;
} else {
wxXml2Property prop(node.GetProperties());
while (prop != wxXml2EmptyProperty) {
toadd += wxT(" ") + prop.GetName() + wxT("=");
toadd += prop.GetValue();
prop = prop.GetNext();
}
}
str += spaces;
#ifdef SHOW_ANNOYING_NEWLINES
str += toadd;
#else
if (toadd != wxT("textnode: [null]")) str += toadd;
#endif
str += wxT("\n");
bool bClose = FALSE;
wxXml2Node child(node.GetFirstChild());
while (child != wxXml2EmptyNode) {
ParseNode(child, str, n+STEP);
child = child.GetNext();
bClose = TRUE;
}
if (bClose) str += wxString(wxT(' '), n) + wxT("/") + node.GetName() + wxT("\n");
}
void ParseNodeAndSiblings(const wxXml2Node &node, wxString &str, int n)
{
wxXml2Node curr(node);
do {
ParseNode(curr, str, n);
curr = curr.GetNext();
} while (curr != wxXml2EmptyNode);
}
void MyFrame::LoadXML(const wxString &filename)
{
wxXml2Document doc;
wxString err;
wxFileInputStream tmp(filename);
if (tmp.IsOk() && tmp.GetSize() > 2048)
wxLog::EnableLogging(false);
if (!doc.Load(filename, &err)) {
wxMessageBox(wxString::Format(
wxT("Couldn't parse the file you chose:\n%s"), err.c_str()), wxT("Error"));
return;
}
wxString tree;
wxXml2Node root = doc.GetRoot();
int indent = 3;
tree.Alloc(1024);
wxXml2DTD dtd(doc.GetDTD());
if (dtd != wxXml2EmptyDTD) {
tree += wxT("DTD name=") + dtd.GetName();
if (dtd.IsPublicSubset())
tree += wxT(" PUBLIC externalID=") + dtd.GetExternalID() +
wxT(" externalURI=") + dtd.GetExternalURI() + wxT("\n\n");
if (dtd.IsSystemSubset())
tree += wxT(" SYSTEM systemID=") + dtd.GetSystemID() + wxT("\n\n");
}
ParseNodeAndSiblings(root, tree, indent);
m_text->SetValue(tree);
dtd.DestroyIfUnlinked();
root.DestroyIfUnlinked();
doc.DestroyIfUnlinked();
wxLog::EnableLogging(true);
}
void MyFrame::LoadDTD(const wxString &filename)
{
wxXml2DTD doc;
wxString err;
if (!doc.Load(filename, &err)) {
wxMessageBox(wxString::Format(
wxT("Couldn't parse the file you chose:\n%s"), err.c_str()), wxT("Error"));
return;
}
wxStringOutputStream stream;
doc.Save(stream);
m_text->SetValue(stream.GetString());
doc.DestroyIfUnlinked();
}
void MyFrame::OnLoadXML(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog fd(this, wxT("Choose the XML file to load"), wxT(""), wxT(""),
wxT("XML and HTML files|*.xml;*.html;*.xhtml|All files|*.*"), wxOPEN);
if (fd.ShowModal() == wxID_CANCEL)
return;
LoadXML(fd.GetPath());
wxFileDialog fd2(this, wxT("Choose the XML file to save on"), wxT(""), wxT(""),
wxT("XML and HTML files|*.xml;*.html;*.xhtml|All files|*.*"), wxSAVE);
if (fd2.ShowModal() == wxID_CANCEL)
return;
wxXml2Document tmpDoc;
tmpDoc.Load(fd.GetPath());
tmpDoc.Save(fd2.GetPath());
}
void MyFrame::OnLoadDTD(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog fd(this, wxT("Choose the DTD to load"), wxT(""), wxT(""),
wxT("DTD files|*.dtd|All files|*.*"), wxOPEN);
if (fd.ShowModal() == wxID_CANCEL)
return;
LoadDTD(fd.GetPath());
}
void MyFrame::OnSaveSimple(wxCommandEvent& WXUNUSED(event))
{
wxXml2Document doc;
wxString err;
wxFileDialog fd(this, wxT("Save simple HTML example file as..."), wxT(""), wxT(""),
wxT("XML and HTML files|*.xml;*.html;*.xhtml|All files|*.*"),
wxSAVE | wxOVERWRITE_PROMPT );
if (fd.ShowModal() == wxID_CANCEL)
return;
doc.Create();
wxXml2Node html;
html.CreateRoot(doc, wxT("html"));
html.AddProperty(wxT("lang"), wxT("en"));
html.AddContainerChild(wxT("head"));
html.Get(wxT("head")).AddTextChild(wxT("title"), wxT("Hi! I'm a sample HTML file"));
wxXml2Node body = html.AddContainerChild(wxT("body"));
body.AddCommentChild(
wxT(" This is a dummy comment "));
body.AddTextChild(wxT("p"),
wxT(" HTML exported by wxXml2 wrappers for libxml2 - ") \
wxT(" write to frm@users.sourceforge.net if you encounter any ") \
wxT(" problem or if you want to give suggestions or advices. "));
if (doc.Save(fd.GetPath())) {
int ret = wxMessageBox(wxT("File correctly saved. Do you want to load it ?"),
wxT("Question"), wxYES_NO | wxICON_QUESTION);
if (ret == wxYES) LoadXML(fd.GetPath());
} else {
wxMessageBox(wxT("File could not be correctly saved !!!"),
wxT("Error"), wxOK | wxICON_ERROR);
}
html.DestroyIfUnlinked();
body.DestroyIfUnlinked();
doc.DestroyIfUnlinked();
}
void MyFrame::OnSaveAdv(wxCommandEvent &)
{
wxXml2Document doc;
wxString err;
wxFileDialog fd(this, wxT("Save advanced XHTML example file as..."), wxT(""), wxT(""),
wxT("XML and HTML files|*.xml;*.html;*.xhtml|All files|*.*"),
wxSAVE | wxOVERWRITE_PROMPT );
if (fd.ShowModal() == wxID_CANCEL)
return;
doc.Create();
wxXml2Node root;
root.CreateRoot(doc, wxT("advanced_sample"));
doc.SetMathMLDTD();
root.AddCDATAChild(wxT("my cdata block: this text is not parsed and it can ")
wxT("contain any special character like <>'\",! except for the characters ")
wxT("] ] > in sequence without spaces since they mark the end of this node"));
root.AddPIChild(wxT("xml-stylesheet"),
wxT("type=\"text/xsl\" href=\"http://www.w3.org/Math/XSL/mathml.xsl\""));
root.AddTextChild(wxT("refnode"), wxT("©"));
#if wxUSE_UNICODE
root.AddCommentChild(
wxT("In the followig text child, some non-ANSI (i.e. Unicode) characters are used; ")
wxT("If you see a greek ALPHA, BETA and GAMMA characters, it means that you are ")
wxT("using a viewer which supports the Unicode standard."));
wxString greekstring = wxT("\x3B1\x3B2\x3B3");
root.AddTextChild(wxT("textchild"), greekstring);
#endif
root.AddContainerChild(wxT("mydata"));
root.Get(wxT("mydata")).AddContainerChild(wxT("mysubdata"));
root.Get(wxT("mydata")).Get(wxT("mysubdata")).AddTextChild(wxT("subdata1"), wxT("mytext"));
root.Get(wxT("mydata")).Get(wxT("mysubdata")).AddTextChild(wxT("subdata2"), wxT("mytext"));
root.Get(wxT("mydata")).AddContainerChild(wxT("mysubdata3"));
root.Get(wxT("mydata")).Get(wxT("mysubdata3")).Encapsulate(wxT("mysubdata2"));
root.Get(wxT("mydata")).Get(wxT("mysubdata2")).Get(wxT("mysubdata3")).AddTextChild(wxT("subdata2"), wxT("mytext"));
if (doc.Save(fd.GetPath(), wxT("utf8"),
wxXML2DOC_USE_NATIVE_NEWLINES | wxXML2DOC_USE_INDENTATION)) {
int ret = wxMessageBox(wxT("File correctly saved. Do you want to load it ?"),
wxT("Question"), wxYES_NO | wxICON_QUESTION);
if (ret == wxYES) LoadXML(fd.GetPath());
} else {
wxMessageBox(wxT("File could not be correctly saved !!!"),
wxT("Error"), wxOK | wxICON_ERROR);
}
root.DestroyIfUnlinked();
doc.DestroyIfUnlinked();
}
void MyFrame::OnSaveDTD(wxCommandEvent &)
{
wxXml2DTD doc;
wxString err;
wxFileDialog fd(this, wxT("Save DTD example file as..."), wxT(""), wxT(""),
wxT("DTD files|*.dtd|All files|*.*"),
wxSAVE | wxOVERWRITE_PROMPT );
if (fd.ShowModal() == wxID_CANCEL)
return;
doc.Create(wxXml2EmptyDoc, wxT("mydtd"), wxT("none"), wxT("none"));
wxXml2ElemContent content(wxT("myelement"), wxXML2_ELEMENT_CONTENT_PCDATA);
doc.AddElemDecl(wxT("myelement"), wxXML2_ELEMENT_TYPE_ELEMENT, content);
wxXml2ElemContent content2(wxT("myelement2"), wxXML2_ELEMENT_CONTENT_ELEMENT, wxXML2_ELEMENT_CONTENT_MULT);
doc.AddElemDecl(wxT("myelement2"), wxXML2_ELEMENT_TYPE_ELEMENT, content2);
wxXml2Enumeration values(wxT("text|link"));
doc.AddAttrDecl(wxT("mydata"), wxT("type"), wxXml2EmptyNamespace,
wxXML2_ATTRIBUTE_ENUMERATION, wxXML2_ATTRIBUTE_REQUIRED,
wxT("default"), values);
wxXml2Enumeration values2(values);
doc.AddAttrDecl(wxT("mydata"), wxT("data"), wxXml2EmptyNamespace,
wxXML2_ATTRIBUTE_ENUMERATION, wxXML2_ATTRIBUTE_REQUIRED,
wxT("default"), values2);
doc.AddEntityDecl(wxT("myentity"), wxXML2_INTERNAL_GENERAL_ENTITY,
wxT(""), wxT(""), wxT("mycontent"));
if (doc.Save(fd.GetPath())) {
int ret = wxMessageBox(wxT("File correctly saved. Do you want to load it ?"),
wxT("Question"), wxYES_NO | wxICON_QUESTION);
if (ret == wxYES) LoadDTD(fd.GetPath());
} else {
wxMessageBox(wxT("File could not be correctly saved !!!"),
wxT("Error"), wxOK | wxICON_ERROR);
}
doc.DestroyIfUnlinked();
}
void MyFrame::OnValid(wxCommandEvent &)
{
wxFileDialog fd(this, wxT("Choose the XML file to validate"), wxT(""), wxT(""),
wxT("XML and HTML files|*.xml;*.html;*.xhtml|All files|*.*"), wxOPEN);
if (fd.ShowModal() == wxID_CANCEL)
return;
wxXml2Document doc;
wxString err;
if (!doc.Load(fd.GetPath(), &err)) {
wxMessageBox(wxString::Format(
wxT("Couldn't parse the file you chose:\n%s"), err.c_str()), wxT("Error"));
return;
}
wxXml2DTD dtd(doc.GetDTD());
if (dtd == wxXml2EmptyDTD) {
wxFileDialog dlg(this, wxT("Choose the DTD to use"), wxT(""), wxT(""),
wxT("DTD files|*.dtd|All files|*.*"), wxOPEN);
if (dlg.ShowModal() == wxID_CANCEL)
return;
wxXml2DTD dtd;
if (!dtd.Load(dlg.GetPath(), &err)) {
wxMessageBox(wxT("Couldn't load that DTD:\n") + err,
wxT("Load failed"), wxOK | wxICON_ERROR);
return;
}
doc.SetDTD(dtd);
} else if (dtd.IsExternalReference()) {
if (!dtd.LoadFullDTD(&err)) {
wxMessageBox(wxT("Couldn't load that DTD:\n") + err,
wxT("Load failed"), wxOK | wxICON_ERROR);
return;
}
} else {
wxASSERT(dtd.IsOk());
}
if (!doc.IsDTDValid(&err, TRUE)) {
wxMessageBox(wxT("The document is not valid for the given DTD:\n\n") + err,
wxT("Validation failed"), wxOK | wxICON_ERROR);
return;
}
wxMessageBox(wxT("The document is valid for the given DTD !!"),
wxT("Validation successful"), wxOK | wxICON_EXCLAMATION);
doc.DestroyIfUnlinked();
}