Hi Francesco,
Sorry for the delay.
could you submit it as a patch?
It's much easier to apply in that form (just do a "cvs diff -bu2
>sample.patch" in wxXml2\sample).
Well I am very new to CVS and SVN so I dont know how to prepare the
patch. But in any case, I moved to SVN and currently I don't have CVS
installed, so I can not execute the suggested command.
Therefore I am sending you the full modified source file. I built the
sample and tested it. It works ok: external entities are detected and
replaced correctly. There was a bug in the code I sketched in my
previous e-mail, as it only worked ok if the xml file being processed
has only one external entity defined. If it has more than one
definition, I have discovered that after a node of type
wxXML_ENTITY_REF_NODE you will find, as children, the full list of
declared external entities. So I had to modify the code to choose the
proper one. The attached code is tested and works ok.
Hope this is OK for you.
Regards,
Cecilio
2006/12/13, Francesco Montorsi <[EMAIL PROTECTED]>:
Hi Cecilio,
sorry again for the delay...
cecilio ha scritto:
> This is just to confirm you that replacing external entities on the
> fly works.
very good!
> The following code is the modification to add to your
> sample code:
>
> else if (node.GetType() == wxXML_ENTITY_DECL)
> {
> wxXml2EntityDecl* pNode = (wxXml2EntityDecl*)&node;
> toadd += wxString::Format(_T(", NodeType=%d, Name='%s',
> SystemID='%s'\n"),
> node.GetType(), pNode->GetSystemID() );
>
> // insert here the referenced xml tree
>
> // load the referebced XML file as tree of nodes
> wxXml2Document oDoc;
> wxString sError;
> wxFileName oFN(m_sMainFilename);
> oFN.SetFullName(pNode->GetSystemID());
> wxString sFilename = oFN.GetFullPath();
> if (!oDoc.Load(sFilename, &sError)) {
> wxLogMessage(_T("Error parsing file %s\nError:%s"),
> sFilename, sError);
> return; // or continue?
> }
> //Process it recursively
> wxXml2Node oRoot = oDoc.GetRoot();
> wxString sChildTree;
> ParseNodeAndSiblings(oRoot, sChildTree, n);
> toadd += sChildTree;
> }
great - nice addition to the sample; could you submit it as a patch?
It's much easier to apply in that form (just do a "cvs diff -bu2
>sample.patch" in wxXml2\sample).
>
> Two important issues:
>
> 1. You will see global variable m_sMainFilename. This is needed
> because the external entity URL could be relative to main file. So we
> need to know the main file URL. A second issue is that in this sample
> code I am assuming that the external entity URL is just
> "filename.ext", so that it will be located at the same folder than
> main XML file.
> This is a non-valid assuption and so, more code must be
> inserted to compose the rigth URL.
aren't these two issues the same ?
I'd simply write:
wxFileName oFN(pNode->GetSystemID());
if (oFN.IsRelative())
oFN.MakeAbsolute(wxPathOnly(m_sMainFilename));
> - I did not tested this code in the sample, but in my app, so maybe
> there is some bug in last line (toadd += sChildTree).
I'll look at it....
Thanks,
Francesco
////////////////////////////////////////////////////////////////////////////
// Name: minimal.cpp
// Purpose: Minimal wxWindows sample
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id: minimal.cpp,v 1.16 2005/02/07 13:12:41 frm Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#include "wx/xml2.h" // include libxml2 wrapper
definitions
#include "wx/dtd.h" // include libxml2 wrapper
definitions
#include "wx/filename.h"
#include <wx/mstream.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWindows headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon (under Windows and OS/2 it is in resources and even
// though we could still include the XPM here it would be unused)
#if !defined(__WXMSW__) && !defined(__WXPM__)
#include "mondrian.xpm"
#endif
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class MyApp : public wxApp
{
public:
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit();
int OnExit();
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
Minimal_Quit = wxID_EXIT,
// it is important for the id corresponding to the "About" command to have
// this standard value as otherwise it won't be handled properly under Mac
// (where it is special and put into the "Apple" menu)
Minimal_About = wxID_ABOUT,
Minimal_LoadXML, // these were added by me
Minimal_LoadDTD,
Minimal_SaveSimple,
Minimal_SaveAdv,
Minimal_SaveDTD,
Minimal_Valid
};
// Define a new frame type: this is going to be our main frame
class MyFrame : public wxFrame
{
public:
// ctor(s)
MyFrame(const wxString& title);
~MyFrame();
// event handlers (these functions should _not_ be virtual)
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:
// any class wishing to process wxWindows events must use this macro
DECLARE_EVENT_TABLE()
};
void ParseNodeAndSiblings(const wxXml2Node &node, wxString &str, int n, const
wxString &filename);
// ----------------------------------------------------------------------------
// event tables and other macros for wxWindows
// ----------------------------------------------------------------------------
// the event tables connect the wxWindows events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
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()
// Create a new application object: this macro will allow wxWindows to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also implements the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
IMPLEMENT_APP(MyApp)
// ============================================================================
// implementation
// ============================================================================
// first of all, decide if we can use the system...
#if defined(__VISUALC__)
#define mcDETECT_MEMORY_LEAKS
#endif
#ifdef mcDETECT_MEMORY_LEAKS
// "crtdbg.h" is included only with MSVC++ and Borland, I think...
// "stackwalker.h" instead, contains a set of stack walker functions
// created by Jochen Kalmbach (thanks !!!) which allow to read the
// intercept unhandled exceptions and memory-leaks.
// To be used, the file must be part of the project; this is why
// it's contained (with its CPP counterpart) in the folder of this
// test program. Anyway, you can find it also online at:
// http://www.codeproject.com/tools/leakfinder.asp
#include <crtdbg.h>
// define some useful macros
#define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
#define mcDUMP_ON_EXIT { _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
| _CRTDBG_ALLOC_MEM_DF); }
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
// this little class is used to access Stackwalker functions
// without changing a line of code...
class mcLeakDetector {
public:
mcLeakDetector() { mcDUMP_ON_EXIT; }
~mcLeakDetector() {}
};
// ...infact, instancing a STATIC mcLeakDetector class, we
// can start memory-leak detection at the very beginning of
// the program (when the main() or winmain() has not been
// called yet, that is, when the framework is creating the
// static variables of the program) and end it at the very
// end of the program (when, after the main() or winmain(),
// the framework removes the static variables).
static mcLeakDetector detector;
#endif
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
// wxT('Main program') equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
// create the main application window
MyFrame *frame = new MyFrame(_T("Minimal wxWindows App"));
#if 1
// create an useful log window
wxLogWindow *pwindow = new wxLogWindow(frame, wxT("log"));
pwindow->GetFrame()->Move(50, 50+350);
pwindow->GetFrame()->SetSize(800, 300);
// and show it (the frames, unlike simple controls, are not shown when
// created initially)
frame->Show(true);
#endif
//wxXml2::Init();
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned false here, the
// application would exit immediately.
return true;
}
int MyApp::OnExit()
{
//wxXml2::Cleanup();
return 0;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxPoint(50, 50), wxSize(500, 300))
{
// set the frame icon
SetIcon(wxICON(mondrian));
#if 1
// create the wxTextCtrl where the file structure is shown
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
// create a menu bar
wxMenu *menuFile = new wxMenu;
// the "About" item should be in the help menu
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"));
// now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar();
menuBar->Append(menuFile, _T("&File"));
menuBar->Append(helpMenu, _T("&Help"));
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
#endif // wxUSE_MENUS
#if wxUSE_STATUSBAR
// create a status bar just for fun (by default with 1 pane only)
CreateStatusBar(2);
SetStatusText(_T("Welcome to wxWindows!"));
#endif // wxUSE_STATUSBAR
}
MyFrame::~MyFrame()
{
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
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 ([EMAIL PROTECTED])\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
// helper recursive function: THIS IS ONLY A "DIDACTIVE" EXAMPLE OF A
// RECURSIVE FUNCTION WHICH CAN BE USED TO WALK AN XML TREE...
// IF YOU JUST NEED TO OUTPUT THE CONTENTS OF AN XML TREE YOU CAN USE
// THE wxXml2Document::Save FUNCTION ON A wxMemoryOutputStream AS
// MyFrame::LoadDTD DOES TO SHOW TO THE USER THE STRUCTURE OF AN XML DTD.
void ParseNode(const wxXml2Node &node, wxString &str, int n, const wxString
&filename)
{
static bool m_fExtEntity=false; //processing an external entity
static wxString m_sExtEntityName; // the anem of the external
entity
if (node == wxXml2EmptyNode) return;
wxLogDebug(wxT("ParseNode - parsing [%s]"), node.GetName().c_str());
wxString toadd, spaces(wxT(' '), n);
// concatenate the name of this node
toadd = node.GetName();
// if this is a text node, then add also the contents...
if (node.GetType() == wxXML_TEXT_NODE ||
node.GetType() == wxXML_COMMENT_NODE ||
node.GetType() == wxXML_CDATA_SECTION_NODE) {
wxString content = node.GetContent();
if (content.Last() == wxT('\n')) content.RemoveLast();
if (content.GetChar(0) == wxT('\n')) content.Remove(0, 1);
// a little exception: libxml2 when loading a document creates a
// lot of text nodes containing just a simple \n;
// in this cases, just show "[null]"
wxString tmp = content.Trim();
if (tmp.IsEmpty())
toadd += wxT("node: [null]");
else
toadd += wxT("node: ") + content;
}
else if (node.GetType() == wxXML_ENTITY_REF_NODE)
{
//A reference to an entity. It is like a text node, but this node
contains
//only an "entity". Entities are strings like: & or " or <
....
//It must have an wxXML_ENTITY_DECL child
toadd += wxString::Format(_T(", Reference to external entity &%s;"),
node.GetName());
// Save the name of the node
m_fExtEntity = true;
m_sExtEntityName = node.GetName();
}
else if (node.GetType() == wxXML_ENTITY_DECL)
{
//As children of an external reference node we will find the list of
all declared
//external entities, a node per entity. The first one will be the one
corresponding
//to the previously found wxXML_ENTITY_REF_NODE.
wxXml2EntityDecl* pNode = (wxXml2EntityDecl*)&node;
toadd += wxString::Format(_T(", Entity declaration, name='%s',
SystemID='%s'\n"),
node.GetName(), pNode->GetSystemID() );
// if this decalarion is the taht corresponds to the refeneced external
entity
// insert here the referenced xml tree
if (m_fExtEntity && m_sExtEntityName == node.GetName())
{
// load the referenced XML file as tree of nodes
wxXml2Document oDoc;
wxString sError;
//TODO:
//In this sample I am assuming that the external entity URL is just
//"filename.ext", that is, it is located at the same folder than
//main XML file.
//In general, this is a non-valid assuption and so, more code must
be
//inserted to compose the rigth URL.
//----------------------------------------------
wxFileName oFN(filename);
oFN.SetFullName(pNode->GetSystemID());
wxString sFilename = oFN.GetFullPath();
if (!oDoc.Load(sFilename, &sError)) {
wxLogMessage(_T("Error parsing file %s\nError:%s"),
sFilename, sError);
return; // or continue?
}
//Process it recursively
m_fExtEntity = false;
m_sExtEntityName = wxEmptyString;
wxXml2Node oRoot = oDoc.GetRoot();
toadd += spaces;
toadd += wxString::Format(_T("Inserting and processing file %s\n"),
sFilename);
toadd += spaces + _T("------------------------------------\n");
wxString sChildTree;
ParseNodeAndSiblings(oRoot, sChildTree, n, sFilename);
toadd += sChildTree;
toadd += spaces + _T("------------------------------------\n");
toadd += spaces + _T("Returning to previous file\n");
toadd += spaces + _T("------------------------------------\n");
}
}
else { // if it's not a text node, then add the properties...
wxXml2Property prop(node.GetProperties());
while (prop != wxXml2EmptyProperty) {
toadd += wxT(" ") + prop.GetName() + wxT("=");
toadd += prop.GetValue();
prop = prop.GetNext();
}
}
str += spaces;
//#define SHOW_ANNOYING_NEWLINES
#ifdef SHOW_ANNOYING_NEWLINES
// text nodes with newlines and/or spaces will be shown as [null]
str += toadd;
#else
// text nodes with newlines won't be shown at all
if (toadd != wxT("textnode: [null]")) str += toadd;
#endif
// go one line down
str += wxT("\n");
// do we must add the close tag ?
bool bClose = FALSE;
// and then, a step more indented, its children
wxXml2Node child(node.GetFirstChild());
while (child != wxXml2EmptyNode) {
ParseNode(child, str, n+STEP, filename);
child = child.GetNext();
// add a close tag because at least one child is present...
bClose = TRUE;
}
if (bClose) str += wxString(wxT(' '), n) + wxT("/") + node.GetName() +
wxT("\n");
}
// another helper function
void ParseNodeAndSiblings(const wxXml2Node &node, wxString &str, int n, const
wxString &filename)
{
wxXml2Node curr(node);
do {
ParseNode(curr, str, n, filename);
curr = curr.GetNext();
} while (curr != wxXml2EmptyNode);
}
void MyFrame::LoadXML(const wxString &filename)
{
wxXml2Document doc;
wxString err;
// parse the file
if (!doc.Load(filename, &err)) {
wxMessageBox(wxString::Format(
wxT("Couldn't parse the file you chose:\n%s"),
err.c_str()), wxT("Error"));
return;
}
// show the wxXml2Node tree in a simple format...
wxString tree;
wxXml2Node root = doc.GetRoot();
int indent = 3;
tree.Alloc(1024);
// show the DTD declaration, if present
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");
}
// get a string with the tree structure...
ParseNodeAndSiblings(root, tree, indent, filename);
// show it to the user
m_text->SetValue(tree);
// cleanup
dtd.DestroyIfUnlinked();
root.DestroyIfUnlinked();
doc.DestroyIfUnlinked();
}
void MyFrame::LoadDTD(const wxString &filename)
{
wxXml2DTD doc;
wxString err;
// parse the file
if (!doc.Load(filename, &err)) {
wxMessageBox(wxString::Format(
wxT("Couldn't parse the file you chose:\n%s"),
err.c_str()), wxT("Error"));
return;
}
// show the wxXml2DTD tree in a simple format...
wxStringOutputStream stream;
// we won't use the ParseNodeAndSiblings because it requires
// wxXml2Nodes to parse: here we have instead wxXml2ElemDecl,
// wxXml2AttrDecl... node types.
doc.Save(stream);
m_text->SetValue(stream.GetStr());
doc.DestroyIfUnlinked();
}
void MyFrame::OnLoadXML(wxCommandEvent& WXUNUSED(event))
{
// ask the user which file we must load...
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());
}
void MyFrame::OnLoadDTD(wxCommandEvent& WXUNUSED(event))
{
// ask the user which file we must load...
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;
// ask the user where we must save
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;
// create an XML version 1.0
doc.Create();
// create the HTML header if required
wxXml2Node html;
html.CreateRoot(doc, wxT("html"));
// set HTML header:
// <html lang="en">
//
html.AddProperty(wxT("lang"), wxT("en"));
// add the head, title & body tags:
// <HEAD><TITLE> [title] </TITLE></HEAD>
// <BODY></BODY>
//
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"));
// and a comment:
// <!-- [sample comment] -->.
//
body.AddCommentChild(
wxT(" This is a dummy comment "));
// also add a simple paragraph... <P>text</P>
body.AddTextChild(wxT("p"),
wxT(" HTML exported by wxXml2 wrappers for libxml2 - ") \
wxT(" write to [EMAIL PROTECTED] if you encounter any ") \
wxT(" problem or if you want to give suggestions or advices.
"));
// now, save the file where the user choose
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;
// ask the user where we must save
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;
// create an XML version 1.0
doc.Create();
// create the HTML header if required
wxXml2Node root;
root.CreateRoot(doc, wxT("advanced_sample"));
// create a MathML DTD and set it for this doc
doc.SetMathMLDTD();
// create a CDATA node
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"));
// create a PI node: even if we create it here, it will be automatically
// linked at the beginning of the document...
root.AddPIChild(wxT("xml-stylesheet"),
wxT("type=\"text/xsl\"
href=\"http://www.w3.org/Math/XSL/mathml.xsl\""));
// create a node containing a reference to an entity:
// if everything works good, it will be recognized and embedded into
// a wxXML_REFERENCE_NODE by wxXml2
root.AddTextChild(wxT("refnode"), wxT("©"));
#if wxUSE_UNICODE
// then, do a little check for 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
// create some simple nodes just to highlight the indentation feature
used below...
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"));
// let's test the Encapsulate function
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"));
// now, save the file where the user choose
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;
// ask the user where we must save
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;
// create the DTD document:
// NOTE: THE WXXML2 APIs FOR DTD CREATION ARE NOT VERY EXTENDED:
// THIS IS BECAUSE USUALLY DTD ARE NOT CREATED FROM A PROGRAM:
// USUALLY THEY ARE WRITTEN BY HAND AND THE PROGRAMS USE THEM
// TO VALIDATE XML DOCUMENTS.
// IF YOU NEED AN EXTENSION OF THESE FUNCTIONS, PLEASE CONTACT
ME...
doc.Create(wxXml2EmptyDoc, wxT("mydtd"), wxT("none"), wxT("none"));
// create an element declaration and set the root
// some errors have been experienced with some libxml2 versions
previous to 2.6.16
// (which is the one I use): unfortunately I haven't time to dig into
these ones...
wxXml2ElemContent content(wxT("myelement"),
wxXML_ELEMENT_CONTENT_PCDATA);
doc.AddElemDecl(wxT("myelement"), wxXML_ELEMENT_TYPE_ELEMENT, content);
wxXml2ElemContent content2(wxT("myelement2"),
wxXML_ELEMENT_CONTENT_ELEMENT, wxXML_ELEMENT_CONTENT_MULT);
doc.AddElemDecl(wxT("myelement2"), wxXML_ELEMENT_TYPE_ELEMENT,
content2);
wxXml2Enumeration values(wxT("text|link"));
doc.AddAttrDecl(wxT("mydata"), wxT("type"), wxXml2EmptyNamespace,
wxXML_ATTRIBUTE_ENUMERATION,
wxXML_ATTRIBUTE_REQUIRED,
wxT("default"), values);
wxXml2Enumeration values2(values);
doc.AddAttrDecl(wxT("mydata"), wxT("data"), wxXml2EmptyNamespace,
wxXML_ATTRIBUTE_ENUMERATION,
wxXML_ATTRIBUTE_REQUIRED,
wxT("default"), values2);
doc.AddEntityDecl(wxT("myentity"), wxXML_INTERNAL_GENERAL_ENTITY,
wxT(""), wxT(""),
wxT("mycontent"));
// now, save the file where the user choose
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 &)
{
// ask the user which file we must load...
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;
// try to do everything
wxXml2Document doc;
wxString err;
// parse the file
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) { // if it misses a DTD...
// ...ask the user which DTD we must load...
wxFileDialog dlg(this, wxT("Choose the DTD to use"), wxT(""),
wxT(""),
wxT("DTD files|*.dtd|All files|*.*"), wxOPEN);
if (dlg.ShowModal() == wxID_CANCEL)
return;
// load the DTD
wxXml2DTD dtd;
if (!dtd.Load(dlg.GetPath(), &err)) {
wxMessageBox(wxT("Couldn't load that DTD:\n") + err,
wxT("Load failed"), wxOK |
wxICON_ERROR);
return;
}
// and set it for our doc
doc.SetDTD(dtd);
} else if (dtd.IsExternalReference()) { // if it's external
// load it
if (!dtd.LoadFullDTD(&err)) {
wxMessageBox(wxT("Couldn't load that DTD:\n") + err,
wxT("Load failed"), wxOK |
wxICON_ERROR);
return;
}
} else {
wxASSERT(dtd.IsOk());
}
// validate the document using the DTD it now has embedded
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();
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
wxCode-users mailing list
wxCode-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wxcode-users