CMarkup
is powerful XML parser posted on CodeProject (see article
here). It is fast and intuitive. Here I introduce a derived class of CMarkup
called CMarkupArchive
that adds even more features. You can derive
it from free CMarkup Lite (found here at
http://www.codeproject.com/soap/markupclass.asp) or from CMarkup
Evaluation (found at www.firstobject.com
with licensing options explained there). All the addition are encapsulated in
code of CMarkupArchive
and CMarkup
is left unchanged.
The main features of this extension are:
-
File handling for loading/storing data with zipping support (using zlib),
-
CArchive
style, get rid of your old Serialize
functions and use XML instead!
-
New find method :
Find(Child)ElemAttrib
, find an element
matching a tag, containing an attribute matching a desired value,
-
Adding and Getting helper functions: add/get numerical values without bothering
about string conversion! All the classical types are supported :
bool
,
int
, UINT
, double,
, std::vector
,
std::list
and std::valarray
.
-
Find and get helper functions: find a tag, and load numerical value if needed.
-
Namespace support: automatically append a namespace to the tags.
The article does not contain any demo but only the source code. To get a demo, try
the one shipped with CMarkup
article.
File Handling and CArchive
style
CMarkupArchive
will do the dirty work of handling files for you. Just
specify the filename, open it and you're ready to parse:
using namespace markup;
CMarkupArchive xml( ArchiveModeNotZipped |
ArchiveModeStoring );
if ( xml.Open(_T("myXMLfile.xml"))
{
xml.Close();
}
It uses zlib for in-code zipping, unzipping of XML. However you can disable
this option by using the corresponding flag (see above). The state of the
archive can be retrieved using classical functions like IsStoring
,
IsLoading
and IsOpen
.
New find method
bool FindElemAttrib( LPCTSTR szName, LPCTSTR szAttrib, LPCTSTR szAttribValue );
bool FindChildElemAttrib( LPCTSTR szName , LPCTSTR szAttrib, LPCTSTR szAttribValue );
With this method, you can find a (child) element matching szName
,
containing an attribute szAttrib
matching the value szAttribValue
.
Here's a typical example of application. Consider the following piece of XML:
<employe name="Jack">
...
</employe>
<employe name="Bill">
...
</employe>
Finding the employe name Bill is a piece of cake:
if( xml.FindChildElemAttrib( _T("employe") , _T("name"), _T("Bill") ))
{
}
Numerical values helpers
Stop bothering about converting numerical values to string or the inverse. A whole
set of helper functions is available.
Storing data
bool AddElemEx(LPCTSTR szName, Type _Type );
bool AddChildElemEx(LPCTSTR szName, Type _Type );
bool AddAttribEx(LPCTSTR szName, bool _Type);
bool AddChildAttribEx(LPCTSTR szName, bool _Type);
where type
is one of the following: bool
, int
,
UINT
, DWORD
, float
, double
,
std::vector<double-float-int-BYTE>
, std::list<double-float-int-BYTE>
,
std::valarray<double-float-int-BYTE>
. They use Add(...)
from CMarkup
.
A typical example is:
bool correct;
double value;
...
xml.AddChildElemEx(_T("Corret"), correct);
xml.AddChildAttribEx(_T("Value"), value);
Loading data
To load data, use the following
Type GetData[Type]();
Type GetChildData[Type]();
Type GetAttribData[Type](LPCTSTR szAttrib);
Type GetChildAttribData[Type](LPCTSTR szAttrib);
These functions are the duals of the storing helper functions and use Get(...)Data
from CMarkup
.
Other specialized function do the following: find element and get the data if found:
bool FindGetData(LPCTSTR szName, Type& _Type);
bool FindGetChildData(LPCTSTR szName, Type& _Type);
Typical use will look like
bool correct;
double value;
...
xml.FindGetElem(_T("Corret"), correct);
xml.FindGetChildElem(_T("Value"), value);
Namespace handling
You can add namespace automatically to your tags by using the following
(self-explanatory) functions:
bool SetNameSpace(LPCTSTR szNameSpace);
CString GetNameSpace() const;
The following piece of code
...
xml.SetNameSpace(_T("myNameSpace"));
...
xml.AddChildElem(_T("element"), _T("..."));
will output
<myNameSpace:element>
...
</myNameSpace:element>
Encoding string
You can modifiy the xml encoding string: when saving to a file or string, the
following line is added:
<?xml version="1.0" encoding="ISO-8859-1" ?>
The
value ISO-8859-1 can be modified using
SetEncodingString
.
Integrating CMarkupArchive
in your existing projects
CMarkupArchive
is inherited from CMarkup
and therefore you
can use it in any project using CMarkup
even if you're working
with version other than Lite! The source comes as a static libary. Here are the
installation steps:
-
Copy your version of CMarkup
in the XMLMarkup directory,
-
Integrate them into the static library project,
-
Enclose the CMarkup
declaration and implementation in the markup
namespace,
-
Declare as virtual
the following functions in CMarkup
declaration
(needed for namespace handling):
virtual bool AddElem( LPCTSTR szName, LPCTSTR szData=NULL);
virtual bool AddChildElem( LPCTSTR szName, LPCTSTR szData=NULL);
virtual bool FindElem( LPCTSTR szName=NULL);
virtual bool FindChildElem( LPCTSTR szName=NULL);
-
Recompile the static library. It should output an XMLParser(d,u,ud).lib (respectively
for release, debug, UNICODE debug and UNICODE release),
-
Include MarkupArchive.h in your projects where it's needed. As it is
given as a static library, the header will automatically tell the linker to
look for the .lib (make sure they are in the path).
-
Parse and parse again.
Update History
10-14-2002
-
Fixed a bug when trying to open a non-existing file
-
Added STL2String template to handle string to stl and stl to string conversions
- Fixed some bugs about namespaces
10-10-2002
-
A lot of contributions from Albert van Peppen,
-
Changed
Add(Child)(Attrib-Elem)[Type]
to Add(Child)(Attrib-Elem)Ex
,
better and easier, AVP,
-
Added list and valarray support,
-
Fixed bugs in
Find(Child)ElemAttrib
-
Move EArchive enum into the class, - Added namespace markup