2014-04-01 18:44:30 +02:00
/****************************************************************************/
/*! \mainpage XMLParser library
* \ section intro_sec Introduction
*
* This is a basic XML parser written in ANSI C + + for portability .
* It works by using recursion and a node tree for breaking
* down the elements of an XML document .
*
* @ version V2 .41
* @ author Frank Vanden Berghen
*
* The following license terms for the " XMLParser library from Business-Insight " apply to projects
* that are in some way related to
* the " mcpat project " , including applications
* using " mcpat project " and tools developed
* for enhancing " mcpat project " . All other projects
* ( not related to " mcpat project " ) have to use the " XMLParser library from Business-Insight "
* code under the Aladdin Free Public License ( AFPL )
* See the file " AFPL-license.txt " for more informations about the AFPL license .
* ( see http : //www.artifex.com/downloads/doc/Public.htm for detailed AFPL terms)
*
* Redistribution and use of the " XMLParser library from Business-Insight " in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of Frank Vanden Berghen nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY Business - Insight ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL Business - Insight BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* Copyright ( c ) 2002 , Business - Insight
2014-06-03 22:32:59 +02:00
* Copyright ( c ) 2010 - 2013 Advanced Micro Devices , Inc .
2014-04-01 18:44:30 +02:00
* < a href = " http://www.Business-Insight.com " > Business - Insight < / a >
* All rights reserved .
*
* \ section tutorial First Tutorial
* You can follow a simple < a href = " ../../xmlParser.html " > Tutorial < / a > to know the basics . . .
*
* \ section usage General usage : How to include the XMLParser library inside your project .
*
* The library is composed of two files : < a href = " ../../xmlParser.cpp " > xmlParser . cpp < / a > and
* < a href = " ../../xmlParser.h " > xmlParser . h < / a > . These are the ONLY 2 files that you need when
* using the library inside your own projects .
*
* All the functions of the library are documented inside the comments of the file
* < a href = " ../../xmlParser.h " > xmlParser . h < / a > . These comments can be transformed in
* full - fledged HTML documentation using the DOXYGEN software : simply type : " doxygen doxy.cfg "
*
* By default , the XMLParser library uses ( char * ) for string representation . To use the ( wchar_t * )
* version of the library , you need to define the " _UNICODE " preprocessor definition variable
* ( this is usually done inside your project definition file ) ( This is done automatically for you
* when using Visual Studio ) .
*
* \ section example Advanced Tutorial and Many Examples of usage .
*
* Some very small introductory examples are described inside the Tutorial file
* < a href = " ../../xmlParser.html " > xmlParser . html < / a >
*
* Some additional small examples are also inside the file < a href = " ../../xmlTest.cpp " > xmlTest . cpp < / a >
* ( for the " char* " version of the library ) and inside the file
* < a href = " ../../xmlTestUnicode.cpp " > xmlTestUnicode . cpp < / a > ( for the " wchar_t* "
* version of the library ) . If you have a question , please review these additionnal examples
* before sending an e - mail to the author .
*
* To build the examples :
* - linux / unix : type " make "
* - solaris : type " make -f makefile.solaris "
* - windows : Visual Studio : double - click on xmlParser . dsw
* ( under Visual Studio . NET , the . dsp and . dsw files will be automatically converted to . vcproj and . sln files )
*
* In order to build the examples you need some additional files :
* - linux / unix : makefile
* - solaris : makefile . solaris
* - windows : Visual Studio : * . dsp , xmlParser . dsw and also xmlParser . lib and xmlParser . dll
*
* \ section debugging Debugging with the XMLParser library
*
* \ subsection debugwin Debugging under WINDOWS
*
* Inside Visual C + + , the " debug versions " of the memory allocation functions are
* very slow : Do not forget to compile in " release mode " to get maximum speed .
* When I had to debug a software that was using the XMLParser Library , it was usually
* a nightmare because the library was sooOOOoooo slow in debug mode ( because of the
* slow memory allocations in Debug mode ) . To solve this
* problem , during all the debugging session , I am now using a very fast DLL version of the
* XMLParser Library ( the DLL is compiled in release mode ) . Using the DLL version of
* the XMLParser Library allows me to have lightening XML parsing speed even in debug !
* Other than that , the DLL version is useless : In the release version of my tool ,
* I always use the normal , " .cpp " - based , XMLParser Library ( I simply include the
* < a href = " ../../xmlParser.cpp " > xmlParser . cpp < / a > and
* < a href = " ../../xmlParser.h " > xmlParser . h < / a > files into the project ) .
*
* The file < a href = " ../../XMLNodeAutoexp.txt " > XMLNodeAutoexp . txt < / a > contains some
* " tweaks " that improve substancially the display of the content of the XMLNode objects
* inside the Visual Studio Debugger . Believe me , once you have seen inside the debugger
* the " smooth " display of the XMLNode objects , you cannot live without it anymore !
*
* \ subsection debuglinux Debugging under LINUX / UNIX
*
* The speed of the debug version of the XMLParser library is tolerable so no extra
* work . has been done .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef __INCLUDE_XML_NODE__
# define __INCLUDE_XML_NODE__
# include <stdlib.h>
# ifdef _UNICODE
// If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
// This is useful when you get error messages like:
// 'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
// The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
// must be defined) or utf8-mode(the pre-processor variable must be undefined).
# define _XMLWIDECHAR
# endif
# if defined(WIN32) || defined(UNDER_CE) || defined(_WIN32) || defined(WIN64) || defined(__BORLANDC__)
// comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET) or Borland
# define _XMLWINDOWS
# endif
# ifdef XMLDLLENTRY
# undef XMLDLLENTRY
# endif
# ifdef _USE_XMLPARSER_DLL
# ifdef _DLL_EXPORTS_
# define XMLDLLENTRY __declspec(dllexport)
# else
# define XMLDLLENTRY __declspec(dllimport)
# endif
# else
# define XMLDLLENTRY
# endif
// uncomment the next line if you want no support for wchar_t* (no need for the <wchar.h> or <tchar.h> libraries anymore to compile)
//#define XML_NO_WIDE_CHAR
# ifdef XML_NO_WIDE_CHAR
# undef _XMLWINDOWS
# undef _XMLWIDECHAR
# endif
# ifdef _XMLWINDOWS
# include <tchar.h>
# else
# define XMLDLLENTRY
# ifndef XML_NO_WIDE_CHAR
# include <wchar.h> // to have 'wcsrtombs' for ANSI version
2014-06-03 22:32:59 +02:00
// to have 'mbsrtowcs' for WIDECHAR version
2014-04-01 18:44:30 +02:00
# endif
# endif
// Some common types for char set portable code
# ifdef _XMLWIDECHAR
2014-06-03 22:32:59 +02:00
# define _CXML(c) L ## c
# define XMLCSTR const wchar_t *
# define XMLSTR wchar_t *
# define XMLCHAR wchar_t
2014-04-01 18:44:30 +02:00
# else
2014-06-03 22:32:59 +02:00
# define _CXML(c) c
# define XMLCSTR const char *
# define XMLSTR char *
# define XMLCHAR char
2014-04-01 18:44:30 +02:00
# endif
# ifndef FALSE
2014-06-03 22:32:59 +02:00
# define FALSE 0
2014-04-01 18:44:30 +02:00
# endif /* FALSE */
# ifndef TRUE
2014-06-03 22:32:59 +02:00
# define TRUE 1
2014-04-01 18:44:30 +02:00
# endif /* TRUE */
/// Enumeration for XML parse errors.
2014-06-03 22:32:59 +02:00
typedef enum XMLError {
2014-04-01 18:44:30 +02:00
eXMLErrorNone = 0 ,
eXMLErrorMissingEndTag ,
eXMLErrorNoXMLTagFound ,
eXMLErrorEmpty ,
eXMLErrorMissingTagName ,
eXMLErrorMissingEndTagName ,
eXMLErrorUnmatchedEndTag ,
eXMLErrorUnmatchedEndClearTag ,
eXMLErrorUnexpectedToken ,
eXMLErrorNoElements ,
eXMLErrorFileNotFound ,
eXMLErrorFirstTagNotFound ,
eXMLErrorUnknownCharacterEntity ,
eXMLErrorCharacterCodeAbove255 ,
eXMLErrorCharConversionError ,
eXMLErrorCannotOpenWriteFile ,
eXMLErrorCannotWriteFile ,
eXMLErrorBase64DataSizeIsNotMultipleOf4 ,
eXMLErrorBase64DecodeIllegalCharacter ,
eXMLErrorBase64DecodeTruncatedData ,
eXMLErrorBase64DecodeBufferTooSmall
} XMLError ;
/// Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
2014-06-03 22:32:59 +02:00
typedef enum XMLElementType {
eNodeChild = 0 ,
eNodeAttribute = 1 ,
eNodeText = 2 ,
eNodeClear = 3 ,
eNodeNULL = 4
2014-04-01 18:44:30 +02:00
} XMLElementType ;
/// Structure used to obtain error details if the parse fails.
2014-06-03 22:32:59 +02:00
typedef struct XMLResults {
2014-04-01 18:44:30 +02:00
enum XMLError error ;
2014-06-03 22:32:59 +02:00
int nLine ;
int nColumn ;
2014-04-01 18:44:30 +02:00
} XMLResults ;
/// Structure for XML clear (unformatted) node (usually comments)
typedef struct XMLClear {
2014-06-03 22:32:59 +02:00
XMLCSTR lpszValue ;
XMLCSTR lpszOpenTag ;
XMLCSTR lpszCloseTag ;
2014-04-01 18:44:30 +02:00
} XMLClear ;
/// Structure for XML attribute.
typedef struct XMLAttribute {
2014-06-03 22:32:59 +02:00
XMLCSTR lpszName ;
XMLCSTR lpszValue ;
2014-04-01 18:44:30 +02:00
} XMLAttribute ;
/// XMLElementPosition are not interchangeable with simple indexes
typedef int XMLElementPosition ;
struct XMLNodeContents ;
/** @defgroup XMLParserGeneral The XML parser */
/// Main Class representing a XML node
/**
* All operations are performed using this class .
* \ note The constructors of the XMLNode class are protected , so use instead one of these four methods to get your first instance of XMLNode :
* < ul >
* < li > XMLNode : : parseString < / li >
* < li > XMLNode : : parseFile < / li >
* < li > XMLNode : : openFileHelper < / li >
* < li > XMLNode : : createXMLTopNode ( or XMLNode : : createXMLTopNode_WOSD ) < / li >
* < / ul > */
2014-06-03 22:32:59 +02:00
typedef struct XMLDLLENTRY XMLNode {
private :
2014-04-01 18:44:30 +02:00
struct XMLNodeDataTag ;
/// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
XMLNode ( struct XMLNodeDataTag * pParent , XMLSTR lpszName , char isDeclaration ) ;
/// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
XMLNode ( struct XMLNodeDataTag * p ) ;
2014-06-03 22:32:59 +02:00
public :
2014-04-01 18:44:30 +02:00
static XMLCSTR getVersion ( ) ; ///< Return the XMLParser library version number
/** @defgroup conversions Parsing XML files/strings to an XMLNode structure and Rendering XMLNode's to files/string.
* @ ingroup XMLParserGeneral
* @ { */
/// Parse an XML string and return the root of a XMLNode tree representing the string.
2014-06-03 22:32:59 +02:00
static XMLNode parseString ( XMLCSTR lpXMLString , XMLCSTR tag = NULL ,
XMLResults * pResults = NULL ) ;
2014-04-01 18:44:30 +02:00
/**< The "parseString" function parse an XML string and return the root of a XMLNode tree. The "opposite" of this function is
* the function " createXMLString " that re - creates an XML string from an XMLNode tree . If the XML document is corrupted , the
* " parseString " method will initialize the " pResults " variable with some information that can be used to trace the error .
* If you still want to parse the file , you can use the APPROXIMATE_PARSING option as explained inside the note at the
* beginning of the " xmlParser.cpp " file .
*
* @ param lpXMLString the XML string to parse
* @ param tag the name of the first tag inside the XML file . If the tag parameter is omitted , this function returns a node that represents the head of the xml document including the declaration term ( < ? . . . ? > ) .
* @ param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error . You can have a user - friendly explanation of the parsing error with the " getError " function .
*/
/// Parse an XML file and return the root of a XMLNode tree representing the file.
2014-06-03 22:32:59 +02:00
static XMLNode parseFile ( XMLCSTR filename , XMLCSTR tag = NULL ,
XMLResults * pResults = NULL ) ;
2014-04-01 18:44:30 +02:00
/**< The "parseFile" function parse an XML file and return the root of a XMLNode tree. The "opposite" of this function is
* the function " writeToFile " that re - creates an XML file from an XMLNode tree . If the XML document is corrupted , the
* " parseFile " method will initialize the " pResults " variable with some information that can be used to trace the error .
* If you still want to parse the file , you can use the APPROXIMATE_PARSING option as explained inside the note at the
* beginning of the " xmlParser.cpp " file .
*
* @ param filename the path to the XML file to parse
* @ param tag the name of the first tag inside the XML file . If the tag parameter is omitted , this function returns a node that represents the head of the xml document including the declaration term ( < ? . . . ? > ) .
* @ param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error . You can have a user - friendly explanation of the parsing error with the " getError " function .
*/
/// Parse an XML file and return the root of a XMLNode tree representing the file. A very crude error checking is made. An attempt to guess the Char Encoding used in the file is made.
2014-06-03 22:32:59 +02:00
static XMLNode openFileHelper ( XMLCSTR filename , XMLCSTR tag = NULL ) ;
2014-04-01 18:44:30 +02:00
/**< The "openFileHelper" function reports to the screen all the warnings and errors that occurred during parsing of the XML file.
* This function also tries to guess char Encoding ( UTF - 8 , ASCII or SHIT - JIS ) based on the first 200 bytes of the file . Since each
* application has its own way to report and deal with errors , you should rather use the " parseFile " function to parse XML files
* and program yourself thereafter an " error reporting " tailored for your needs ( instead of using the very crude " error reporting "
* mechanism included inside the " openFileHelper " function ) .
*
* If the XML document is corrupted , the " openFileHelper " method will :
* - display an error message on the console ( or inside a messageBox for windows ) .
* - stop execution ( exit ) .
*
* I strongly suggest that you write your own " openFileHelper " method tailored to your needs . If you still want to parse
* the file , you can use the APPROXIMATE_PARSING option as explained inside the note at the beginning of the " xmlParser.cpp " file .
*
* @ param filename the path of the XML file to parse .
* @ param tag the name of the first tag inside the XML file . If the tag parameter is omitted , this function returns a node that represents the head of the xml document including the declaration term ( < ? . . . ? > ) .
*/
static XMLCSTR getError ( XMLError error ) ; ///< this gives you a user-friendly explanation of the parsing error
/// Create an XML string starting from the current XMLNode.
2014-06-03 22:32:59 +02:00
XMLSTR createXMLString ( int nFormat = 1 , int * pnSize = NULL ) const ;
2014-04-01 18:44:30 +02:00
/**< The returned string should be free'd using the "freeXMLString" function.
*
* If nFormat = = 0 , no formatting is required otherwise this returns an user friendly XML string from a given element
* with appropriate white spaces and carriage returns . if pnSize is given it returns the size in character of the string . */
/// Save the content of an xmlNode inside a file
XMLError writeToFile ( XMLCSTR filename ,
2014-06-03 22:32:59 +02:00
const char * encoding = NULL ,
char nFormat = 1 ) const ;
2014-04-01 18:44:30 +02:00
/**< If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element with appropriate white spaces and carriage returns.
* If the global parameter " characterEncoding==encoding_UTF8 " , then the " encoding " parameter is ignored and always set to " utf-8 " .
* If the global parameter " characterEncoding==encoding_ShiftJIS " , then the " encoding " parameter is ignored and always set to " SHIFT-JIS " .
* If " _XMLWIDECHAR=1 " , then the " encoding " parameter is ignored and always set to " utf-16 " .
* If no " encoding " parameter is given the " ISO-8859-1 " encoding is used . */
/** @} */
/** @defgroup navigate Navigate the XMLNode structure
* @ ingroup XMLParserGeneral
* @ { */
XMLCSTR getName ( ) const ; ///< name of the node
XMLCSTR getText ( int i = 0 ) const ; ///< return ith text field
int nText ( ) const ; ///< nbr of text field
XMLNode getParentNode ( ) const ; ///< return the parent node
XMLNode getChildNode ( int i = 0 ) const ; ///< return ith child node
XMLNode getChildNode ( XMLCSTR name , int i ) const ; ///< return ith child node with specific name (return an empty node if failing). If i==-1, this returns the last XMLNode with the given name.
XMLNode getChildNode ( XMLCSTR name , int * i = NULL ) const ; ///< return next child node with specific name (return an empty node if failing)
2014-06-03 22:32:59 +02:00
XMLNode * getChildNodePtr ( XMLCSTR name , int * j ) const ;
2014-04-01 18:44:30 +02:00
XMLNode getChildNodeWithAttribute ( XMLCSTR tagName ,
XMLCSTR attributeName ,
XMLCSTR attributeValue = NULL ,
int * i = NULL ) const ; ///< return child node with specific name/attribute (return an empty node if failing)
XMLNode getChildNodeByPath ( XMLCSTR path , char createNodeIfMissing = 0 , XMLCHAR sep = ' / ' ) ;
2014-06-03 22:32:59 +02:00
///< return the first child node with specific path
2014-04-01 18:44:30 +02:00
XMLNode getChildNodeByPathNonConst ( XMLSTR path , char createNodeIfMissing = 0 , XMLCHAR sep = ' / ' ) ;
2014-06-03 22:32:59 +02:00
///< return the first child node with specific path.
2014-04-01 18:44:30 +02:00
int nChildNode ( XMLCSTR name ) const ; ///< return the number of child node with specific name
int nChildNode ( ) const ; ///< nbr of child node
XMLAttribute getAttribute ( int i = 0 ) const ; ///< return ith attribute
XMLCSTR getAttributeName ( int i = 0 ) const ; ///< return ith attribute name
XMLCSTR getAttributeValue ( int i = 0 ) const ; ///< return ith attribute value
char isAttributeSet ( XMLCSTR name ) const ; ///< test if an attribute with a specific name is given
XMLCSTR getAttribute ( XMLCSTR name , int i ) const ; ///< return ith attribute content with specific name (return a NULL if failing)
XMLCSTR getAttribute ( XMLCSTR name , int * i = NULL ) const ; ///< return next attribute content with specific name (return a NULL if failing)
int nAttribute ( ) const ; ///< nbr of attribute
XMLClear getClear ( int i = 0 ) const ; ///< return ith clear field (comments)
int nClear ( ) const ; ///< nbr of clear field
XMLNodeContents enumContents ( XMLElementPosition i ) const ; ///< enumerate all the different contents (attribute,child,text, clear) of the current XMLNode. The order is reflecting the order of the original file/string. NOTE: 0 <= i < nElement();
int nElement ( ) const ; ///< nbr of different contents for current node
char isEmpty ( ) const ; ///< is this node Empty?
char isDeclaration ( ) const ; ///< is this node a declaration <? .... ?>
XMLNode deepCopy ( ) const ; ///< deep copy (duplicate/clone) a XMLNode
static XMLNode emptyNode ( ) ; ///< return XMLNode::emptyXMLNode;
/** @} */
~ XMLNode ( ) ;
XMLNode ( const XMLNode & A ) ; ///< to allow shallow/fast copy:
XMLNode & operator = ( const XMLNode & A ) ; ///< to allow shallow/fast copy:
XMLNode ( ) : d ( NULL ) { } ;
static XMLNode emptyXMLNode ;
static XMLClear emptyXMLClear ;
static XMLAttribute emptyXMLAttribute ;
/** @defgroup xmlModify Create or Update the XMLNode structure
* @ ingroup XMLParserGeneral
* The functions in this group allows you to create from scratch ( or update ) a XMLNode structure . Start by creating your top
* node with the " createXMLTopNode " function and then add new nodes with the " addChild " function . The parameter ' pos ' gives
* the position where the childNode , the text or the XMLClearTag will be inserted . The default value ( pos = - 1 ) inserts at the
* end . The value ( pos = 0 ) insert at the beginning ( Insertion at the beginning is slower than at the end ) . < br >
*
* REMARK : 0 < = pos < nChild ( ) + nText ( ) + nClear ( ) < br >
*/
/** @defgroup creation Creating from scratch a XMLNode structure
* @ ingroup xmlModify
* @ { */
static XMLNode createXMLTopNode ( XMLCSTR lpszName , char isDeclaration = FALSE ) ; ///< Create the top node of an XMLNode structure
XMLNode addChild ( XMLCSTR lpszName , char isDeclaration = FALSE , XMLElementPosition pos = - 1 ) ; ///< Add a new child node
XMLNode addChild ( XMLNode nodeToAdd , XMLElementPosition pos = - 1 ) ; ///< If the "nodeToAdd" has some parents, it will be detached from it's parents before being attached to the current XMLNode
XMLAttribute * addAttribute ( XMLCSTR lpszName , XMLCSTR lpszValuev ) ; ///< Add a new attribute
XMLCSTR addText ( XMLCSTR lpszValue , XMLElementPosition pos = - 1 ) ; ///< Add a new text content
XMLClear * addClear ( XMLCSTR lpszValue , XMLCSTR lpszOpen = NULL , XMLCSTR lpszClose = NULL , XMLElementPosition pos = - 1 ) ;
/**< Add a new clear tag
* @ param lpszOpen default value " <![CDATA[ "
* @ param lpszClose default value " ]]> "
*/
/** @} */
/** @defgroup xmlUpdate Updating Nodes
* @ ingroup xmlModify
* Some update functions :
* @ {
*/
XMLCSTR updateName ( XMLCSTR lpszName ) ; ///< change node's name
XMLAttribute * updateAttribute ( XMLAttribute * newAttribute , XMLAttribute * oldAttribute ) ; ///< if the attribute to update is missing, a new one will be added
2014-06-03 22:32:59 +02:00
XMLAttribute * updateAttribute ( XMLCSTR lpszNewValue , XMLCSTR lpszNewName = NULL , int i = 0 ) ; ///< if the attribute to update is missing, a new one will be added
XMLAttribute * updateAttribute ( XMLCSTR lpszNewValue , XMLCSTR lpszNewName , XMLCSTR lpszOldName ) ; ///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
2014-04-01 18:44:30 +02:00
XMLCSTR updateText ( XMLCSTR lpszNewValue , int i = 0 ) ; ///< if the text to update is missing, a new one will be added
XMLCSTR updateText ( XMLCSTR lpszNewValue , XMLCSTR lpszOldValue ) ; ///< if the text to update is missing, a new one will be added
XMLClear * updateClear ( XMLCSTR lpszNewContent , int i = 0 ) ; ///< if the clearTag to update is missing, a new one will be added
2014-06-03 22:32:59 +02:00
XMLClear * updateClear ( XMLClear * newP , XMLClear * oldP ) ; ///< if the clearTag to update is missing, a new one will be added
2014-04-01 18:44:30 +02:00
XMLClear * updateClear ( XMLCSTR lpszNewValue , XMLCSTR lpszOldValue ) ; ///< if the clearTag to update is missing, a new one will be added
/** @} */
/** @defgroup xmlDelete Deleting Nodes or Attributes
* @ ingroup xmlModify
* Some deletion functions :
* @ {
*/
/// The "deleteNodeContent" function forces the deletion of the content of this XMLNode and the subtree.
void deleteNodeContent ( ) ;
/**< \note The XMLNode instances that are referring to the part of the subtree that has been deleted CANNOT be used anymore!!. Unexpected results will occur if you continue using them. */
void deleteAttribute ( int i = 0 ) ; ///< Delete the ith attribute of the current XMLNode
void deleteAttribute ( XMLCSTR lpszName ) ; ///< Delete the attribute with the given name (the "strcmp" function is used to find the right attribute)
void deleteAttribute ( XMLAttribute * anAttribute ) ; ///< Delete the attribute with the name "anAttribute->lpszName" (the "strcmp" function is used to find the right attribute)
void deleteText ( int i = 0 ) ; ///< Delete the Ith text content of the current XMLNode
void deleteText ( XMLCSTR lpszValue ) ; ///< Delete the text content "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the right text)
void deleteClear ( int i = 0 ) ; ///< Delete the Ith clear tag inside the current XMLNode
void deleteClear ( XMLCSTR lpszValue ) ; ///< Delete the clear tag "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the clear tag)
void deleteClear ( XMLClear * p ) ; ///< Delete the clear tag "p" inside the current XMLNode (direct "pointer-to-pointer" comparison on the lpszName of the clear tag is used to find the clear tag)
/** @} */
/** @defgroup xmlWOSD ???_WOSD functions.
* @ ingroup xmlModify
* The strings given as parameters for the " add " and " update " methods that have a name with
* the postfix " _WOSD " ( that means " WithOut String Duplication " ) ( for example " addText_WOSD " )
* will be free ' d by the XMLNode class . For example , it means that this is incorrect :
* \ code
* xNode . addText_WOSD ( " foo " ) ;
* xNode . updateAttribute_WOSD ( " #newcolor " , NULL , " color " ) ;
* \ endcode
* In opposition , this is correct :
* \ code
* xNode . addText ( " foo " ) ;
* xNode . addText_WOSD ( stringDup ( " foo " ) ) ;
* xNode . updateAttribute ( " #newcolor " , NULL , " color " ) ;
* xNode . updateAttribute_WOSD ( stringDup ( " #newcolor " ) , NULL , " color " ) ;
* \ endcode
* Typically , you will never do :
* \ code
* char * b = ( char * ) malloc ( . . . ) ;
* xNode . addText ( b ) ;
* free ( b ) ;
* \ endcode
* . . . but rather :
* \ code
* char * b = ( char * ) malloc ( . . . ) ;
* xNode . addText_WOSD ( b ) ;
* \ endcode
* ( ' free ( b ) ' is performed by the XMLNode class )
* @ { */
static XMLNode createXMLTopNode_WOSD ( XMLSTR lpszName , char isDeclaration = FALSE ) ; ///< Create the top node of an XMLNode structure
XMLNode addChild_WOSD ( XMLSTR lpszName , char isDeclaration = FALSE , XMLElementPosition pos = - 1 ) ; ///< Add a new child node
XMLAttribute * addAttribute_WOSD ( XMLSTR lpszName , XMLSTR lpszValue ) ; ///< Add a new attribute
XMLCSTR addText_WOSD ( XMLSTR lpszValue , XMLElementPosition pos = - 1 ) ; ///< Add a new text content
XMLClear * addClear_WOSD ( XMLSTR lpszValue , XMLCSTR lpszOpen = NULL , XMLCSTR lpszClose = NULL , XMLElementPosition pos = - 1 ) ; ///< Add a new clear Tag
XMLCSTR updateName_WOSD ( XMLSTR lpszName ) ; ///< change node's name
XMLAttribute * updateAttribute_WOSD ( XMLAttribute * newAttribute , XMLAttribute * oldAttribute ) ; ///< if the attribute to update is missing, a new one will be added
2014-06-03 22:32:59 +02:00
XMLAttribute * updateAttribute_WOSD ( XMLSTR lpszNewValue , XMLSTR lpszNewName = NULL , int i = 0 ) ; ///< if the attribute to update is missing, a new one will be added
XMLAttribute * updateAttribute_WOSD ( XMLSTR lpszNewValue , XMLSTR lpszNewName , XMLCSTR lpszOldName ) ; ///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
2014-04-01 18:44:30 +02:00
XMLCSTR updateText_WOSD ( XMLSTR lpszNewValue , int i = 0 ) ; ///< if the text to update is missing, a new one will be added
XMLCSTR updateText_WOSD ( XMLSTR lpszNewValue , XMLCSTR lpszOldValue ) ; ///< if the text to update is missing, a new one will be added
XMLClear * updateClear_WOSD ( XMLSTR lpszNewContent , int i = 0 ) ; ///< if the clearTag to update is missing, a new one will be added
2014-06-03 22:32:59 +02:00
XMLClear * updateClear_WOSD ( XMLClear * newP , XMLClear * oldP ) ; ///< if the clearTag to update is missing, a new one will be added
2014-04-01 18:44:30 +02:00
XMLClear * updateClear_WOSD ( XMLSTR lpszNewValue , XMLCSTR lpszOldValue ) ; ///< if the clearTag to update is missing, a new one will be added
/** @} */
/** @defgroup xmlPosition Position helper functions (use in conjunction with the update&add functions
* @ ingroup xmlModify
* These are some useful functions when you want to insert a childNode , a text or a XMLClearTag in the
* middle ( at a specified position ) of a XMLNode tree already constructed . The value returned by these
* methods is to be used as last parameter ( parameter ' pos ' ) of addChild , addText or addClear .
* @ { */
XMLElementPosition positionOfText ( int i = 0 ) const ;
XMLElementPosition positionOfText ( XMLCSTR lpszValue ) const ;
XMLElementPosition positionOfClear ( int i = 0 ) const ;
XMLElementPosition positionOfClear ( XMLCSTR lpszValue ) const ;
XMLElementPosition positionOfClear ( XMLClear * a ) const ;
XMLElementPosition positionOfChildNode ( int i = 0 ) const ;
XMLElementPosition positionOfChildNode ( XMLNode x ) const ;
XMLElementPosition positionOfChildNode ( XMLCSTR name , int i = 0 ) const ; ///< return the position of the ith childNode with the specified name if (name==NULL) return the position of the ith childNode
/** @} */
/// Enumeration for XML character encoding.
2014-06-03 22:32:59 +02:00
typedef enum XMLCharEncoding {
char_encoding_error = 0 ,
char_encoding_UTF8 = 1 ,
char_encoding_legacy = 2 ,
char_encoding_ShiftJIS = 3 ,
char_encoding_GB2312 = 4 ,
char_encoding_Big5 = 5 ,
char_encoding_GBK = 6 // this is actually the same as Big5
2014-04-01 18:44:30 +02:00
} XMLCharEncoding ;
/** \addtogroup conversions
* @ { */
/// Sets the global options for the conversions
static char setGlobalOptions ( XMLCharEncoding characterEncoding = XMLNode : : char_encoding_UTF8 , char guessWideCharChars = 1 ,
char dropWhiteSpace = 1 , char removeCommentsInMiddleOfText = 1 ) ;
/**< The "setGlobalOptions" function allows you to change four global parameters that affect string & file
* parsing . First of all , you most - probably will never have to change these 3 global parameters .
*
* @ param guessWideCharChars If " guessWideCharChars " = 1 and if this library is compiled in WideChar mode , then the
* XMLNode : : parseFile and XMLNode : : openFileHelper functions will test if the file contains ASCII
* characters . If this is the case , then the file will be loaded and converted in memory to
* WideChar before being parsed . If 0 , no conversion will be performed .
*
* @ param guessWideCharChars If " guessWideCharChars " = 1 and if this library is compiled in ASCII / UTF8 / char * mode , then the
* XMLNode : : parseFile and XMLNode : : openFileHelper functions will test if the file contains WideChar
* characters . If this is the case , then the file will be loaded and converted in memory to
* ASCII / UTF8 / char * before being parsed . If 0 , no conversion will be performed .
*
* @ param characterEncoding This parameter is only meaningful when compiling in char * mode ( multibyte character mode ) .
* In wchar_t * ( wide char mode ) , this parameter is ignored . This parameter should be one of the
* three currently recognized encodings : XMLNode : : encoding_UTF8 , XMLNode : : encoding_ascii ,
* XMLNode : : encoding_ShiftJIS .
*
* @ param dropWhiteSpace In most situations , text fields containing only white spaces ( and carriage returns )
* are useless . Even more , these " empty " text fields are annoying because they increase the
* complexity of the user ' s code for parsing . So , 99 % of the time , it ' s better to drop
* the " empty " text fields . However The XML specification indicates that no white spaces
* should be lost when parsing the file . So to be perfectly XML - compliant , you should set
* dropWhiteSpace = 0. A note of caution : if you set " dropWhiteSpace=0 " , the parser will be
* slower and your code will be more complex .
*
* @ param removeCommentsInMiddleOfText To explain this parameter , let ' s consider this code :
* \ code
* XMLNode x = XMLNode : : parseString ( " <a>foo<!-- hello -->bar<!DOCTYPE world >chu</a> " , " a " ) ;
* \ endcode
* If removeCommentsInMiddleOfText = 0 , then we will have :
* \ code
* x . getText ( 0 ) - > " foo "
* x . getText ( 1 ) - > " bar "
* x . getText ( 2 ) - > " chu "
* x . getClear ( 0 ) - - > " <!-- hello --> "
* x . getClear ( 1 ) - - > " <!DOCTYPE world > "
* \ endcode
* If removeCommentsInMiddleOfText = 1 , then we will have :
* \ code
* x . getText ( 0 ) - > " foobar "
* x . getText ( 1 ) - > " chu "
* x . getClear ( 0 ) - - > " <!DOCTYPE world > "
* \ endcode
*
* \ return " 0 " when there are no errors . If you try to set an unrecognized encoding then the return value will be " 1 " to signal an error .
*
* \ note Sometime , it ' s useful to set " guessWideCharChars=0 " to disable any conversion
* because the test to detect the file - type ( ASCII / UTF8 / char * or WideChar ) may fail ( rarely ) . */
/// Guess the character encoding of the string (ascii, utf8 or shift-JIS)
static XMLCharEncoding guessCharEncoding ( void * buffer , int bufLen , char useXMLEncodingAttribute = 1 ) ;
/**< The "guessCharEncoding" function try to guess the character encoding. You most-probably will never
* have to use this function . It then returns the appropriate value of the global parameter
* " characterEncoding " described in the XMLNode : : setGlobalOptions . The guess is based on the content of a buffer of length
* " bufLen " bytes that contains the first bytes ( minimum 25 bytes ; 200 bytes is a good value ) of the
* file to be parsed . The XMLNode : : openFileHelper function is using this function to automatically compute
* the value of the " characterEncoding " global parameter . There are several heuristics used to do the
* guess . One of the heuristic is based on the " encoding " attribute . The original XML specifications
* forbids to use this attribute to do the guess but you can still use it if you set
* " useXMLEncodingAttribute " to 1 ( this is the default behavior and the behavior of most parsers ) .
* If an inconsistency in the encoding is detected , then the return value is " 0 " . */
/** @} */
2014-06-03 22:32:59 +02:00
private :
// these are functions and structures used internally by the XMLNode class (don't bother about them):
typedef struct XMLNodeDataTag { // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
XMLCSTR lpszName ; // Element name (=NULL if root)
int nChild , // Number of child nodes
nText , // Number of text fields
nClear , // Number of Clear fields (comments)
nAttribute ; // Number of attributes
char isDeclaration ; // Whether node is an XML declaration - '<?xml ?>'
struct XMLNodeDataTag * pParent ; // Pointer to parent element (=NULL if root)
XMLNode * pChild ; // Array of child nodes
XMLCSTR * pText ; // Array of text fields
XMLClear * pClear ; // Array of clear fields
XMLAttribute * pAttribute ; // Array of attributes
int * pOrder ; // order of the child_nodes,text_fields,clear_fields
int ref_count ; // for garbage collection (smart pointers)
} XMLNodeData ;
XMLNodeData * d ;
char parseClearTag ( void * px , void * pa ) ;
char maybeAddTxT ( void * pa , XMLCSTR tokenPStr ) ;
int ParseXMLElement ( void * pXML ) ;
void * addToOrder ( int memInc , int * _pos , int nc , void * p , int size , XMLElementType xtype ) ;
int indexText ( XMLCSTR lpszValue ) const ;
int indexClear ( XMLCSTR lpszValue ) const ;
XMLNode addChild_priv ( int , XMLSTR , char , int ) ;
XMLAttribute * addAttribute_priv ( int , XMLSTR , XMLSTR ) ;
XMLCSTR addText_priv ( int , XMLSTR , int ) ;
XMLClear * addClear_priv ( int , XMLSTR , XMLCSTR , XMLCSTR , int ) ;
void emptyTheNode ( char force ) ;
static inline XMLElementPosition findPosition ( XMLNodeData * d , int index , XMLElementType xtype ) ;
static int CreateXMLStringR ( XMLNodeData * pEntry , XMLSTR lpszMarker , int nFormat ) ;
static int removeOrderElement ( XMLNodeData * d , XMLElementType t , int index ) ;
static void exactMemory ( XMLNodeData * d ) ;
static int detachFromParent ( XMLNodeData * d ) ;
2014-04-01 18:44:30 +02:00
} XMLNode ;
/// This structure is given by the function XMLNode::enumContents.
2014-06-03 22:32:59 +02:00
typedef struct XMLNodeContents {
2014-04-01 18:44:30 +02:00
/// This dictates what's the content of the XMLNodeContent
enum XMLElementType etype ;
/**< should be an union to access the appropriate data. Compiler does not allow union of object with constructor... too bad. */
XMLNode child ;
XMLAttribute attrib ;
XMLCSTR text ;
XMLClear clear ;
} XMLNodeContents ;
/** @defgroup StringAlloc String Allocation/Free functions
* @ ingroup xmlModify
* @ { */
/// Duplicate (copy in a new allocated buffer) the source string.
XMLDLLENTRY XMLSTR stringDup ( XMLCSTR source , int cbData = - 1 ) ;
/**< This is
* a very handy function when used with all the " XMLNode::*_WOSD " functions ( \ link xmlWOSD \ endlink ) .
* @ param cbData If ! = 0 then cbData is the number of chars to duplicate . New strings allocated with
* this function should be free ' d using the " freeXMLString " function . */
/// to free the string allocated inside the "stringDup" function or the "createXMLString" function.
XMLDLLENTRY void freeXMLString ( XMLSTR t ) ; // {free(t);}
/** @} */
/** @defgroup atoX ato? like functions
* @ ingroup XMLParserGeneral
* The " xmlto? " functions are equivalents to the atoi , atol , atof functions .
* The only difference is : If the variable " xmlString " is NULL , than the return value
* is " defautValue " . These 6 functions are only here as " convenience " functions for the
* user ( they are not used inside the XMLparser ) . If you don ' t need them , you can
* delete them without any trouble .
*
* @ { */
2014-06-03 22:32:59 +02:00
XMLDLLENTRY char xmltob ( XMLCSTR xmlString , char defautValue = 0 ) ;
XMLDLLENTRY int xmltoi ( XMLCSTR xmlString , int defautValue = 0 ) ;
XMLDLLENTRY long xmltol ( XMLCSTR xmlString , long defautValue = 0 ) ;
XMLDLLENTRY double xmltof ( XMLCSTR xmlString , double defautValue = .0 ) ;
XMLDLLENTRY XMLCSTR xmltoa ( XMLCSTR xmlString , XMLCSTR defautValue = _CXML ( " " ) ) ;
XMLDLLENTRY XMLCHAR xmltoc ( XMLCSTR xmlString , XMLCHAR defautValue = _CXML ( ' \0 ' ) ) ;
2014-04-01 18:44:30 +02:00
/** @} */
/** @defgroup ToXMLStringTool Helper class to create XML files using "printf", "fprintf", "cout",... functions.
* @ ingroup XMLParserGeneral
* @ { */
/// Helper class to create XML files using "printf", "fprintf", "cout",... functions.
/** The ToXMLStringTool class helps you creating XML files using "printf", "fprintf", "cout",... functions.
* The " ToXMLStringTool " class is processing strings so that all the characters
* & , " ,',<,> are replaced by their XML equivalent:
* \ verbatim & amp ; , & quot ; , & apos ; , & lt ; , & gt ; \ endverbatim
* Using the " ToXMLStringTool class " and the " fprintf function " is THE most efficient
* way to produce VERY large XML documents VERY fast .
* \ note If you are creating from scratch an XML file using the provided XMLNode class
* you must not use the " ToXMLStringTool " class ( because the " XMLNode " class does the
* processing job for you during rendering ) . */
2014-06-03 22:32:59 +02:00
typedef struct XMLDLLENTRY ToXMLStringTool {
2014-04-01 18:44:30 +02:00
public :
2014-06-03 22:32:59 +02:00
ToXMLStringTool ( ) : buf ( NULL ) , buflen ( 0 ) { }
2014-04-01 18:44:30 +02:00
~ ToXMLStringTool ( ) ;
void freeBuffer ( ) ; ///<call this function when you have finished using this object to release memory used by the internal buffer.
XMLSTR toXML ( XMLCSTR source ) ; ///< returns a pointer to an internal buffer that contains a XML-encoded string based on the "source" parameter.
/** The "toXMLUnSafe" function is deprecated because there is a possibility of
* " destination-buffer-overflow " . It converts the string
* " source " to the string " dest " . */
static XMLSTR toXMLUnSafe ( XMLSTR dest , XMLCSTR source ) ; ///< deprecated: use "toXML" instead
static int lengthXMLString ( XMLCSTR source ) ; ///< deprecated: use "toXML" instead
private :
XMLSTR buf ;
int buflen ;
} ToXMLStringTool ;
/** @} */
/** @defgroup XMLParserBase64Tool Helper class to include binary data inside XML strings using "Base64 encoding".
* @ ingroup XMLParserGeneral
* @ { */
/// Helper class to include binary data inside XML strings using "Base64 encoding".
/** The "XMLParserBase64Tool" class allows you to include any binary data (images, sounds,...)
* into an XML document using " Base64 encoding " . This class is completely
* separated from the rest of the xmlParser library and can be removed without any problem .
* To include some binary data into an XML file , you must convert the binary data into
* standard text ( using " encode " ) . To retrieve the original binary data from the
* b64 - encoded text included inside the XML file , use " decode " . Alternatively , these
* functions can also be used to " encrypt/decrypt " some critical data contained inside
* the XML ( it ' s not a strong encryption at all , but sometimes it can be useful ) . */
2014-06-03 22:32:59 +02:00
typedef struct XMLDLLENTRY XMLParserBase64Tool {
2014-04-01 18:44:30 +02:00
public :
2014-06-03 22:32:59 +02:00
XMLParserBase64Tool ( ) : buf ( NULL ) , buflen ( 0 ) { }
2014-04-01 18:44:30 +02:00
~ XMLParserBase64Tool ( ) ;
void freeBuffer ( ) ; ///< Call this function when you have finished using this object to release memory used by the internal buffer.
/**
* @ param formatted If " formatted " = true , some space will be reserved for a carriage - return every 72 chars . */
static int encodeLength ( int inBufLen , char formatted = 0 ) ; ///< return the length of the base64 string that encodes a data buffer of size inBufLen bytes.
/**
* The " base64Encode " function returns a string containing the base64 encoding of " inByteLen " bytes
* from " inByteBuf " . If " formatted " parameter is true , then there will be a carriage - return every 72 chars .
* The string will be free ' d when the XMLParserBase64Tool object is deleted .
* All returned strings are sharing the same memory space . */
XMLSTR encode ( unsigned char * inByteBuf , unsigned int inByteLen , char formatted = 0 ) ; ///< returns a pointer to an internal buffer containing the base64 string containing the binary data encoded from "inByteBuf"
/// returns the number of bytes which will be decoded from "inString".
static unsigned int decodeSize ( XMLCSTR inString , XMLError * xe = NULL ) ;
/**
* The " decode " function returns a pointer to a buffer containing the binary data decoded from " inString "
* The output buffer will be free ' d when the XMLParserBase64Tool object is deleted .
* All output buffer are sharing the same memory space .
* @ param inString If " instring " is malformed , NULL will be returned */
unsigned char * decode ( XMLCSTR inString , int * outByteLen = NULL , XMLError * xe = NULL ) ; ///< returns a pointer to an internal buffer containing the binary data decoded from "inString"
/**
* decodes data from " inString " to " outByteBuf " . You need to provide the size ( in byte ) of " outByteBuf "
* in " inMaxByteOutBuflen " . If " outByteBuf " is not large enough or if data is malformed , then " FALSE "
* will be returned ; otherwise " TRUE " . */
static unsigned char decode ( XMLCSTR inString , unsigned char * outByteBuf , int inMaxByteOutBuflen , XMLError * xe = NULL ) ; ///< deprecated.
private :
void * buf ;
int buflen ;
void alloc ( int newsize ) ;
} XMLParserBase64Tool ;
/** @} */
# undef XMLDLLENTRY
# endif