You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1374 lines
64 KiB
1374 lines
64 KiB
diff --git a/CMakeLists.txt b/CMakeLists.txt |
|
index 16870b4..a1f5a65 100644 |
|
--- a/CMakeLists.txt |
|
+++ b/CMakeLists.txt |
|
@@ -20,6 +20,7 @@ SET(musicbrainz5_SOVERSION ${musicbrainz5_SOVERSION_MAJOR}) |
|
|
|
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) |
|
FIND_PACKAGE(Neon REQUIRED) |
|
+FIND_PACKAGE(LibXml2 REQUIRED) |
|
|
|
SET(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)") |
|
SET(EXEC_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "Installation prefix for executables and object code libraries" FORCE) |
|
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt |
|
index 3e11469..440d4f2 100644 |
|
--- a/examples/CMakeLists.txt |
|
+++ b/examples/CMakeLists.txt |
|
@@ -1,5 +1,5 @@ |
|
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include) |
|
-LINK_LIBRARIES(musicbrainz5 ${NEON_LIBRARIES}) |
|
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include ${LIBXML2_INCLUDE_DIR}) |
|
+LINK_LIBRARIES(musicbrainz5 ${NEON_LIBRARIES} ${LIBXML2_LIBRARIES}) |
|
|
|
ADD_EXECUTABLE(cdlookup cdlookup.cc) |
|
ADD_EXECUTABLE(cdlookup_c cdlookup_c.c) |
|
diff --git a/include/musicbrainz5/xmlParser.h b/include/musicbrainz5/xmlParser.h |
|
index 56b29d7..45db5fc 100644 |
|
--- a/include/musicbrainz5/xmlParser.h |
|
+++ b/include/musicbrainz5/xmlParser.h |
|
@@ -1,733 +1,111 @@ |
|
-/****************************************************************************/ |
|
-/*! \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.43 |
|
- * @author Frank Vanden Berghen |
|
- * |
|
- * Copyright (c) 2002, Business-Insight |
|
- * <a href="http://www.Business-Insight.com">Business-Insight</a> |
|
- * All rights reserved. |
|
- * See the file <a href="../../AFPL-license.txt">AFPL-license.txt</a> about the licensing terms |
|
- * |
|
- * \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__ |
|
+ libmusicbrainz5 - Client library to access MusicBrainz |
|
|
|
-#include <stdlib.h> |
|
+ Copyright (C) 2012 Christophe Fergeau |
|
|
|
-#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 |
|
+ This file is part of libmusicbrainz5. |
|
|
|
-// 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 |
|
+ This library is free software; you can redistribute it and/or |
|
+ modify it under the terms of v2 of the GNU Lesser General Public |
|
+ License as published by the Free Software Foundation. |
|
|
|
-#ifdef XML_NO_WIDE_CHAR |
|
-#undef _XMLWINDOWS |
|
-#undef _XMLWIDECHAR |
|
-#endif |
|
+ libmusicbrainz5 is distributed in the hope that it will be useful, |
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
+ Lesser General Public License for more details. |
|
|
|
-#ifdef _XMLWINDOWS |
|
-#include <tchar.h> |
|
-#else |
|
-#define XMLDLLENTRY |
|
-#ifndef XML_NO_WIDE_CHAR |
|
-#include <wchar.h> // to have 'wcsrtombs' for ANSI version |
|
- // to have 'mbsrtowcs' for WIDECHAR version |
|
-#endif |
|
-#endif |
|
+ You should have received a copy of the GNU General Public License |
|
+ along with this library. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
-// Some common types for char set portable code |
|
-#ifdef _XMLWIDECHAR |
|
- #define _CXML(c) L ## c |
|
- #define XMLCSTR const wchar_t * |
|
- #define XMLSTR wchar_t * |
|
- #define XMLCHAR wchar_t |
|
-#else |
|
- #define _CXML(c) c |
|
- #define XMLCSTR const char * |
|
- #define XMLSTR char * |
|
- #define XMLCHAR char |
|
-#endif |
|
-#ifndef FALSE |
|
- #define FALSE 0 |
|
-#endif /* FALSE */ |
|
-#ifndef TRUE |
|
- #define TRUE 1 |
|
-#endif /* TRUE */ |
|
+ $Id$ |
|
|
|
+----------------------------------------------------------------------------*/ |
|
+#ifndef _MUSICBRAINZ5_XMLPARSER_H |
|
+#define _MUSICBRAINZ5_XMLPARSER_H |
|
|
|
-/// Enumeration for XML parse errors. |
|
-typedef enum XMLError |
|
-{ |
|
- eXMLErrorNone = 0, |
|
- eXMLErrorMissingEndTag, |
|
- eXMLErrorNoXMLTagFound, |
|
- eXMLErrorEmpty, |
|
- eXMLErrorMissingTagName, |
|
- eXMLErrorMissingEndTagName, |
|
- eXMLErrorUnmatchedEndTag, |
|
- eXMLErrorUnmatchedEndClearTag, |
|
- eXMLErrorUnexpectedToken, |
|
- eXMLErrorNoElements, |
|
- eXMLErrorFileNotFound, |
|
- eXMLErrorFirstTagNotFound, |
|
- eXMLErrorUnknownCharacterEntity, |
|
- eXMLErrorCharacterCodeAbove255, |
|
- eXMLErrorCharConversionError, |
|
- eXMLErrorCannotOpenWriteFile, |
|
- eXMLErrorCannotWriteFile, |
|
- |
|
- eXMLErrorBase64DataSizeIsNotMultipleOf4, |
|
- eXMLErrorBase64DecodeIllegalCharacter, |
|
- eXMLErrorBase64DecodeTruncatedData, |
|
- eXMLErrorBase64DecodeBufferTooSmall |
|
-} XMLError; |
|
+#include <string> |
|
+#include <libxml/tree.h> |
|
|
|
+typedef xmlError XMLResults; |
|
|
|
-/// Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents |
|
-typedef enum XMLElementType |
|
-{ |
|
- eNodeChild=0, |
|
- eNodeAttribute=1, |
|
- eNodeText=2, |
|
- eNodeClear=3, |
|
- eNodeNULL=4 |
|
-} XMLElementType; |
|
+const int eXMLErrorNone = 0; |
|
|
|
-/// Structure used to obtain error details if the parse fails. |
|
-typedef struct XMLResults |
|
+class XMLAttribute; |
|
+class XMLNode |
|
{ |
|
- enum XMLError error; |
|
- int nLine,nColumn; |
|
-} XMLResults; |
|
- |
|
-/// Structure for XML clear (unformatted) node (usually comments) |
|
-typedef struct XMLClear { |
|
- XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag; |
|
-} XMLClear; |
|
- |
|
-/// Structure for XML attribute. |
|
-typedef struct XMLAttribute { |
|
- XMLCSTR lpszName; XMLCSTR lpszValue; |
|
-} 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> */ |
|
-typedef struct XMLDLLENTRY XMLNode |
|
-{ |
|
- private: |
|
- |
|
- 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); |
|
- |
|
- public: |
|
- 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. |
|
- static XMLNode parseString (XMLCSTR lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL); |
|
- /**< 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. |
|
- static XMLNode parseFile (XMLCSTR filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL); |
|
- /**< 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. |
|
- */ |
|
+ public: |
|
+ static XMLNode emptyNode(); |
|
+ bool isEmpty() const; |
|
|
|
- /// 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. |
|
- static XMLNode openFileHelper(XMLCSTR filename, XMLCSTR tag=NULL); |
|
- /**< 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 (<? ... ?>). |
|
- */ |
|
+ virtual ~XMLNode() {}; |
|
|
|
- static XMLCSTR getError(XMLError error); ///< this gives you a user-friendly explanation of the parsing error |
|
+ const XMLAttribute getAttribute(const char *name = NULL) const; |
|
+ bool isAttributeSet(const char *name) const; |
|
|
|
- /// Create an XML string starting from the current XMLNode. |
|
- XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const; |
|
- /**< 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. */ |
|
+ XMLNode getChildNode(const char *name = NULL) const; |
|
+ XMLNode next() const; |
|
+ const char *getName() const; |
|
+ const char *getText() const; |
|
|
|
- /// Save the content of an xmlNode inside a file |
|
- XMLError writeToFile(XMLCSTR filename, |
|
- const char *encoding=NULL, |
|
- char nFormat=1) const; |
|
- /**< 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. */ |
|
- /** @} */ |
|
+ friend bool operator== (const XMLNode &lhs, const XMLNode &rhs); |
|
|
|
- /** @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) |
|
- 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='/'); |
|
- ///< return the first child node with specific path |
|
- XMLNode getChildNodeByPathNonConst(XMLSTR path, char createNodeIfMissing=0, XMLCHAR sep='/'); |
|
- ///< return the first child node with specific path. |
|
+ protected: |
|
+ XMLNode(xmlNodePtr node): mNode(node) {}; |
|
|
|
- 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; |
|
- /** @} */ |
|
+ xmlNodePtr mNode; |
|
|
|
- ~XMLNode(); |
|
- XMLNode(const XMLNode &A); ///< to allow shallow/fast copy: |
|
- XMLNode& operator=( const XMLNode& A ); ///< to allow shallow/fast copy: |
|
+ private: |
|
+ xmlAttrPtr getAttributeRaw(const char *name) const; |
|
+}; |
|
|
|
- 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 |
|
- 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 |
|
- 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 |
|
- XMLClear *updateClear(XMLClear *newP,XMLClear *oldP); ///< if the clearTag to update is missing, a new one will be added |
|
- 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 |
|
- 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 |
|
- 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 |
|
- XMLClear *updateClear_WOSD(XMLClear *newP,XMLClear *oldP); ///< if the clearTag to update is missing, a new one will be added |
|
- 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. |
|
- 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 |
|
- } 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". */ |
|
- /** @} */ |
|
- |
|
- 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); |
|
-} XMLNode; |
|
- |
|
-/// This structure is given by the function XMLNode::enumContents. |
|
-typedef struct XMLNodeContents |
|
+inline bool operator== (const XMLNode &lhs, const XMLNode &rhs) |
|
{ |
|
- /// 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. */ |
|
+ return (lhs.mNode == rhs.mNode); |
|
+} |
|
|
|
-/// 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. |
|
- * |
|
- * @{ */ |
|
-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,const XMLCHAR defautValue=_CXML('\0')); |
|
-/** @} */ |
|
- |
|
-/** @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 &, ", ', <, > \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).*/ |
|
-typedef struct XMLDLLENTRY ToXMLStringTool |
|
+inline bool operator!= (const XMLNode &lhs, const XMLNode &rhs) |
|
{ |
|
-public: |
|
- ToXMLStringTool(): buf(NULL),buflen(0){} |
|
- ~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. |
|
+ return !(lhs == rhs); |
|
+} |
|
|
|
- /** 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). */ |
|
-typedef struct XMLDLLENTRY XMLParserBase64Tool |
|
+class XMLRootNode: public XMLNode |
|
{ |
|
-public: |
|
- XMLParserBase64Tool(): buf(NULL),buflen(0){} |
|
- ~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. |
|
+ public: |
|
+ static XMLNode* parseString(std::string &xml, XMLResults *results); |
|
+ static XMLNode* parseFile(const std::string &filename, XMLResults *results); |
|
|
|
- /** |
|
- * 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" |
|
+ virtual ~XMLRootNode() { if (mDoc != NULL) xmlFreeDoc(mDoc); }; |
|
|
|
- /// returns the number of bytes which will be decoded from "inString". |
|
- static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL); |
|
+ private: |
|
+ XMLRootNode(xmlDocPtr doc); |
|
|
|
- /** |
|
- * 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" |
|
+ mutable xmlDocPtr mDoc; |
|
+}; |
|
|
|
- /** |
|
- * 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 |
|
+class XMLAttribute |
|
+{ |
|
+ public: |
|
+ bool isEmpty() const { |
|
+ return (mAttr == NULL); |
|
+ } |
|
+ |
|
+ std::string name() const { |
|
+ return std::string((const char *)mAttr->name); |
|
+ } |
|
+ |
|
+ std::string value() const { |
|
+ return std::string((const char *)mAttr->children->content); |
|
+ } |
|
+ const XMLAttribute next() const { |
|
+ return XMLAttribute(mAttr->next); |
|
+ } |
|
+ |
|
+ friend const XMLAttribute XMLNode::getAttribute(const char *name) const; |
|
+ |
|
+ private: |
|
+ XMLAttribute(xmlAttrPtr attr): mAttr(attr) {}; |
|
+ xmlAttrPtr mAttr; |
|
+}; |
|
|
|
#endif |
|
diff --git a/libmusicbrainz5.pc.cmake b/libmusicbrainz5.pc.cmake |
|
index c2f45c9..fca0de1 100644 |
|
--- a/libmusicbrainz5.pc.cmake |
|
+++ b/libmusicbrainz5.pc.cmake |
|
@@ -8,6 +8,7 @@ Description: The Musicbrainz Client Library. |
|
URL: http://musicbrainz.org/doc/libmusicbrainz |
|
Version: ${PROJECT_VERSION} |
|
Requires.private: neon >= 0.25 |
|
+Requires: libxml-2.0 |
|
Libs: -L${LIB_INSTALL_DIR} -lmusicbrainz5 |
|
Cflags: -I${INCLUDE_INSTALL_DIR} |
|
|
|
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt |
|
index 2ee102f..368dd93 100644 |
|
--- a/src/CMakeLists.txt |
|
+++ b/src/CMakeLists.txt |
|
@@ -1,14 +1,15 @@ |
|
SET(CMAKE_INCLUDE_CURRENT_DIR ON) |
|
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../include ${NEON_INCLUDE_DIR}) |
|
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../include ${NEON_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) |
|
|
|
SET(_sources Alias.cc Annotation.cc Artist.cc ArtistCredit.cc Attribute.cc CDStub.cc Collection.cc |
|
Disc.cc Entity.cc FreeDBDisc.cc HTTPFetch.cc ISRC.cc Label.cc LabelInfo.cc Lifespan.cc List.cc |
|
mb5_c.cc Medium.cc MediumList.cc Message.cc Metadata.cc NameCredit.cc NonMBTrack.cc PUID.cc |
|
Query.cc Rating.cc Recording.cc Relation.cc RelationList.cc Release.cc ReleaseGroup.cc Tag.cc |
|
- TextRepresentation.cc Track.cc UserRating.cc UserTag.cc Work.cc xmlParser.cpp |
|
+ TextRepresentation.cc Track.cc UserRating.cc UserTag.cc Work.cc xmlParser.cc |
|
RelationListList.cc ISWCList.cc ISWC.cc SecondaryType.cc SecondaryTypeList.cc IPI.cc) |
|
|
|
-ADD_EXECUTABLE(make-c-interface make-c-interface.cc xmlParser.cpp) |
|
+ADD_EXECUTABLE(make-c-interface make-c-interface.cc xmlParser.cc) |
|
+TARGET_LINK_LIBRARIES(make-c-interface ${LIBXML2_LIBRARIES}) |
|
|
|
ADD_CUSTOM_COMMAND( |
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mb5_c.cc ${CMAKE_CURRENT_BINARY_DIR}/mb5_c.h ${CMAKE_CURRENT_BINARY_DIR}/../include/musicbrainz5/mb5_c.h |
|
@@ -36,7 +37,7 @@ if(CMAKE_BUILD_TYPE STREQUAL Debug) |
|
ENDIF(CMAKE_COMPILER_IS_GNUCXX) |
|
endif(CMAKE_BUILD_TYPE STREQUAL Debug) |
|
|
|
-TARGET_LINK_LIBRARIES(musicbrainz5 ${NEON_LIBRARIES}) |
|
+TARGET_LINK_LIBRARIES(musicbrainz5 ${NEON_LIBRARIES} ${LIBXML2_LIBRARIES}) |
|
|
|
IF(WIN32) |
|
TARGET_LINK_LIBRARIES(musicbrainz5 wsock32 winmm ws2_32) |
|
@@ -47,7 +48,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX) |
|
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../.git) |
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") |
|
ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../.git) |
|
- set_source_files_properties(mb5_c.cc PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations") |
|
+ #set_source_files_properties(mb5_c.cc PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations") |
|
ENDIF(CMAKE_COMPILER_IS_GNUCXX) |
|
|
|
INSTALL(TARGETS musicbrainz5 DESTINATION ${LIB_INSTALL_DIR}) |
|
diff --git a/src/Entity.cc b/src/Entity.cc |
|
index 0644377..a1bb1ca 100644 |
|
--- a/src/Entity.cc |
|
+++ b/src/Entity.cc |
|
@@ -80,10 +80,12 @@ void MusicBrainz5::CEntity::Parse(const XMLNode& Node) |
|
{ |
|
if (!Node.isEmpty()) |
|
{ |
|
- for (int count=0;count<Node.nAttribute();count++) |
|
+ for (XMLAttribute Attr = Node.getAttribute(); |
|
+ !Attr.isEmpty(); |
|
+ Attr = Attr.next()) |
|
{ |
|
- std::string Name=Node.getAttributeName(count); |
|
- std::string Value=Node.getAttributeValue(count); |
|
+ std::string Name=Attr.name(); |
|
+ std::string Value=Attr.value(); |
|
|
|
if ("ext:"==Name.substr(0,4)) |
|
m_d->m_ExtAttributes[Name.substr(4)]=Value; |
|
@@ -93,10 +95,10 @@ void MusicBrainz5::CEntity::Parse(const XMLNode& Node) |
|
|
|
//std::cout << "Node: " << std::endl << Node.createXMLString(true) << std::endl; |
|
|
|
- for (int count=0;count<Node.nChildNode();count++) |
|
+ for (XMLNode ChildNode = Node.getChildNode(); |
|
+ !ChildNode.isEmpty(); |
|
+ ChildNode = ChildNode.next()) |
|
{ |
|
- XMLNode ChildNode=Node.getChildNode(count); |
|
- |
|
std::string Name=ChildNode.getName(); |
|
std::string Value; |
|
if (ChildNode.getText()) |
|
diff --git a/src/Query.cc b/src/Query.cc |
|
index d132ae7..a835c84 100644 |
|
--- a/src/Query.cc |
|
+++ b/src/Query.cc |
|
@@ -158,15 +158,17 @@ MusicBrainz5::CMetadata MusicBrainz5::CQuery::PerformQuery(const std::string& Qu |
|
#endif |
|
|
|
XMLResults Results; |
|
- XMLNode TopNode=XMLNode::parseString(strData.c_str(), 0, &Results); |
|
- if (Results.error==eXMLErrorNone) |
|
+ memset(&Results, 0, sizeof(Results)); |
|
+ XMLNode *TopNode = XMLRootNode::parseString(strData, &Results); |
|
+ if (Results.code==eXMLErrorNone) |
|
{ |
|
- XMLNode MetadataNode=TopNode.getChildNode("metadata"); |
|
+ XMLNode MetadataNode=*TopNode; |
|
if (!MetadataNode.isEmpty()) |
|
{ |
|
Metadata=CMetadata(MetadataNode); |
|
} |
|
} |
|
+ delete TopNode; |
|
} |
|
} |
|
|
|
@@ -393,10 +395,11 @@ bool MusicBrainz5::CQuery::EditCollection(const std::string& CollectionID, const |
|
#endif |
|
|
|
XMLResults Results; |
|
- XMLNode TopNode=XMLNode::parseString(strData.c_str(), 0, &Results); |
|
- if (Results.error==eXMLErrorNone) |
|
+ memset(&Results, 0, sizeof(Results)); |
|
+ XMLNode *TopNode = XMLRootNode::parseString(strData, &Results); |
|
+ if (Results.code==eXMLErrorNone) |
|
{ |
|
- XMLNode MetadataNode=TopNode.getChildNode("metadata"); |
|
+ XMLNode MetadataNode=*TopNode; |
|
if (!MetadataNode.isEmpty()) |
|
{ |
|
CMetadata Metadata(MetadataNode); |
|
@@ -405,6 +408,7 @@ bool MusicBrainz5::CQuery::EditCollection(const std::string& CollectionID, const |
|
RetVal=RetVal && true; |
|
} |
|
} |
|
+ delete TopNode; |
|
} |
|
} |
|
|
|
diff --git a/src/cinterface.xml b/src/cinterface.xml |
|
index ae5cf92..f492fd1 100644 |
|
--- a/src/cinterface.xml |
|
+++ b/src/cinterface.xml |
|
@@ -1,5 +1,4 @@ |
|
<!-- |
|
- -------------------------------------------------------------------------- |
|
|
|
libmusicbrainz5 - Client library to access MusicBrainz |
|
|
|
@@ -21,7 +20,6 @@ |
|
|
|
$Id$ |
|
|
|
----------------------------------------------------------------------------- |
|
--> |
|
|
|
<cinterface> |
|
@@ -218,7 +216,7 @@ extern "C" |
|
<property name="artist" type="string"/> |
|
<property name="length" type="integer"/> |
|
</class> |
|
- <class name="puid" uppername="PUID" uppername="PUID"> |
|
+ <class name="puid" uppername="PUID"> |
|
<property name="id" uppername="ID" type="string"/> |
|
<property name="recordinglist" uppername="RecordingList" type="object"/> |
|
</class> |
|
diff --git a/src/make-c-interface.cc b/src/make-c-interface.cc |
|
index 652a65b..97af3d9 100644 |
|
--- a/src/make-c-interface.cc |
|
+++ b/src/make-c-interface.cc |
|
@@ -28,6 +28,8 @@ |
|
#include <iostream> |
|
#include <fstream> |
|
#include <sstream> |
|
+#include <cstring> |
|
+#include <unistd.h> |
|
#include <vector> |
|
#include <string> |
|
|
|
@@ -51,8 +53,9 @@ int main(int argc, const char *argv[]) |
|
{ |
|
std::string XMLFile=std::string(argv[1])+"/"+argv[2]; |
|
XMLResults Results; |
|
- XMLNode TopNode=XMLNode::parseFile(XMLFile.c_str(),"cinterface",&Results); |
|
- if (!TopNode.isEmpty()) |
|
+ XMLNode *TopNode=XMLRootNode::parseFile(XMLFile.c_str(),&Results); |
|
+ memset(&Results, 0, sizeof(Results)); |
|
+ if (!TopNode->isEmpty()) |
|
{ |
|
std::cout << "Generating '" << argv[3] << "/" << argv[4] << "' and '" << argv[3] << "/" << argv[5] << "'" << std::endl; |
|
|
|
@@ -74,9 +77,10 @@ int main(int argc, const char *argv[]) |
|
return 1; |
|
} |
|
|
|
- for (int count=0;count<TopNode.nChildNode();count++) |
|
+ for (XMLNode Node = TopNode->getChildNode(); |
|
+ !Node.isEmpty(); |
|
+ Node = Node.next()) |
|
{ |
|
- XMLNode Node=TopNode.getChildNode(count); |
|
std::string Name=Node.getName(); |
|
|
|
if ("boilerplate"==Name) |
|
@@ -84,7 +88,7 @@ int main(int argc, const char *argv[]) |
|
else if ("header"==Name) |
|
ProcessHeader(Node,Source,Include); |
|
else if ("declare"==Name) |
|
- ProcessDeclare(TopNode,Source,Include); |
|
+ ProcessDeclare(*TopNode,Source,Include); |
|
else if ("entity"==Name) |
|
ProcessEntity(Node,Source,Include); |
|
else if ("class"==Name) |
|
@@ -100,9 +104,11 @@ int main(int argc, const char *argv[]) |
|
} |
|
else |
|
{ |
|
- std::cerr << "Error reading XML: " << XMLNode::getError(Results.error) << " at line " << Results.nLine << std::endl; |
|
+ std::cerr << "Error reading XML: " << Results.message << " at line " << Results.line << std::endl; |
|
return 1; |
|
} |
|
+ if (TopNode != NULL) |
|
+ delete TopNode; |
|
} |
|
|
|
return 0; |
|
@@ -114,7 +120,7 @@ std::ofstream *GetFile(const XMLNode& Node, std::ofstream& Source, std::ofstream |
|
|
|
if (Node.isAttributeSet("target")) |
|
{ |
|
- std::string Target=Node.getAttribute("target"); |
|
+ std::string Target=Node.getAttribute("target").value(); |
|
if ("source"==Target) |
|
File=&Source; |
|
else if ("include"==Target) |
|
@@ -162,7 +168,7 @@ void ProcessBoilerplate(const XMLNode& Node, std::ofstream& Source, std::ofstrea |
|
|
|
if (Node.isAttributeSet("file")) |
|
{ |
|
- std::string FileName=Node.getAttribute("file"); |
|
+ std::string FileName=Node.getAttribute("file").value(); |
|
std::ifstream InFile(FileName.c_str()); |
|
if (InFile.is_open()) |
|
*File << InFile.rdbuf() << std::endl; |
|
@@ -263,11 +269,11 @@ void ProcessClass(const XMLNode& Node, std::ofstream& Source, std::ofstream& Inc |
|
{ |
|
if (Node.isAttributeSet("name")) |
|
{ |
|
- std::string LowerName=Node.getAttribute("name"); |
|
+ std::string LowerName=Node.getAttribute("name").value(); |
|
|
|
std::string UpperName=LowerName; |
|
if (Node.isAttributeSet("uppername")) |
|
- UpperName=Node.getAttribute("uppername"); |
|
+ UpperName=Node.getAttribute("uppername").value(); |
|
else |
|
UpperName[0]=toupper(UpperName[0]); |
|
|
|
@@ -294,24 +300,25 @@ void ProcessClass(const XMLNode& Node, std::ofstream& Source, std::ofstream& Inc |
|
|
|
Source << " MB5_C_CLONE(" << UpperName << "," << LowerName << ")" << std::endl; |
|
|
|
- for (int count=0;count<Node.nChildNode();count++) |
|
+ for (XMLNode ChildNode = Node.getChildNode(); |
|
+ !ChildNode.isEmpty(); |
|
+ ChildNode = ChildNode.next()) |
|
{ |
|
- XMLNode ChildNode=Node.getChildNode(count); |
|
std::string Name=ChildNode.getName(); |
|
|
|
if ("property"==Name) |
|
{ |
|
if (ChildNode.isAttributeSet("name") && ChildNode.isAttributeSet("type")) |
|
{ |
|
- std::string PropertyLowerName=ChildNode.getAttribute("name"); |
|
+ std::string PropertyLowerName=ChildNode.getAttribute("name").value(); |
|
|
|
std::string PropertyUpperName=PropertyLowerName; |
|
if (ChildNode.isAttributeSet("uppername")) |
|
- PropertyUpperName=ChildNode.getAttribute("uppername"); |
|
+ PropertyUpperName=ChildNode.getAttribute("uppername").value(); |
|
else |
|
PropertyUpperName[0]=toupper(PropertyUpperName[0]); |
|
|
|
- std::string PropertyType=ChildNode.getAttribute("type"); |
|
+ std::string PropertyType=ChildNode.getAttribute("type").value(); |
|
|
|
if ("string"==PropertyType) |
|
{ |
|
@@ -320,13 +327,13 @@ void ProcessClass(const XMLNode& Node, std::ofstream& Source, std::ofstream& Inc |
|
|
|
if (ChildNode.isAttributeSet("deprecated")) |
|
{ |
|
- std::string StrDeprecated=ChildNode.getAttribute("deprecated"); |
|
+ std::string StrDeprecated=ChildNode.getAttribute("deprecated").value(); |
|
|
|
if (StrDeprecated=="true") |
|
Deprecated=true; |
|
|
|
if (ChildNode.isAttributeSet("replacement")) |
|
- Replacement=ChildNode.getAttribute("replacement"); |
|
+ Replacement=ChildNode.getAttribute("replacement").value(); |
|
} |
|
|
|
Include << "/**" << std::endl; |
|
@@ -470,11 +477,11 @@ void ProcessList(const XMLNode& Node, std::ofstream& Source, std::ofstream& Incl |
|
{ |
|
if (Node.isAttributeSet("name")) |
|
{ |
|
- std::string LowerName=Node.getAttribute("name"); |
|
+ std::string LowerName=Node.getAttribute("name").value(); |
|
|
|
std::string UpperName=LowerName; |
|
if (Node.isAttributeSet("uppername")) |
|
- UpperName=Node.getAttribute("uppername"); |
|
+ UpperName=Node.getAttribute("uppername").value(); |
|
else |
|
UpperName[0]=toupper(UpperName[0]); |
|
|
|
@@ -532,24 +539,25 @@ void ProcessList(const XMLNode& Node, std::ofstream& Source, std::ofstream& Incl |
|
|
|
Source << " MB5_C_CLONE(" << UpperName << "List," << LowerName << "_list)" << std::endl; |
|
|
|
- for (int count=0;count<Node.nChildNode();count++) |
|
+ for (XMLNode ChildNode = Node.getChildNode(); |
|
+ !ChildNode.isEmpty(); |
|
+ ChildNode = ChildNode.next()) |
|
{ |
|
- XMLNode ChildNode=Node.getChildNode(count); |
|
std::string Name=ChildNode.getName(); |
|
|
|
if ("property"==Name) |
|
{ |
|
if (ChildNode.isAttributeSet("name") && ChildNode.isAttributeSet("type")) |
|
{ |
|
- std::string PropertyLowerName=ChildNode.getAttribute("name"); |
|
+ std::string PropertyLowerName=ChildNode.getAttribute("name").value(); |
|
|
|
std::string PropertyUpperName=PropertyLowerName; |
|
if (ChildNode.isAttributeSet("uppername")) |
|
- PropertyUpperName=ChildNode.getAttribute("uppername"); |
|
+ PropertyUpperName=ChildNode.getAttribute("uppername").value(); |
|
else |
|
PropertyUpperName[0]=toupper(PropertyUpperName[0]); |
|
|
|
- std::string PropertyType=ChildNode.getAttribute("type"); |
|
+ std::string PropertyType=ChildNode.getAttribute("type").value(); |
|
|
|
if ("string"==PropertyType) |
|
{ |
|
@@ -637,18 +645,19 @@ void ProcessDeclare(const XMLNode& Node, std::ofstream& /*Source*/, std::ofstrea |
|
std::vector<std::string> Classes; |
|
Classes.push_back("Entity"); |
|
|
|
- for (int count=0;count<Node.nChildNode();count++) |
|
+ for (XMLNode ChildNode = Node.getChildNode(); |
|
+ !ChildNode.isEmpty(); |
|
+ ChildNode = ChildNode.next()) |
|
{ |
|
- XMLNode ChildNode=Node.getChildNode(count); |
|
std::string Name=ChildNode.getName(); |
|
|
|
if ("class"==Name || "list"==Name) |
|
{ |
|
if (ChildNode.isAttributeSet("name")) |
|
{ |
|
- std::string UpperName=ChildNode.getAttribute("name"); |
|
+ std::string UpperName=ChildNode.getAttribute("name").value(); |
|
if (ChildNode.isAttributeSet("uppername")) |
|
- UpperName=ChildNode.getAttribute("uppername"); |
|
+ UpperName=ChildNode.getAttribute("uppername").value(); |
|
else |
|
UpperName[0]=toupper(UpperName[0]); |
|
|
|
diff --git a/src/xmlParser.cc b/src/xmlParser.cc |
|
new file mode 100644 |
|
index 0000000..41af44b |
|
--- /dev/null |
|
+++ b/src/xmlParser.cc |
|
@@ -0,0 +1,145 @@ |
|
+/* -------------------------------------------------------------------------- |
|
+ |
|
+ libmusicbrainz5 - Client library to access MusicBrainz |
|
+ |
|
+ Copyright (C) 2012 Christophe Fergeau |
|
+ |
|
+ This file is part of libmusicbrainz5. |
|
+ |
|
+ This library is free software; you can redistribute it and/or |
|
+ modify it under the terms of v2 of the GNU Lesser General Public |
|
+ License as published by the Free Software Foundation. |
|
+ |
|
+ libmusicbrainz5 is distributed in the hope that it will be useful, |
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
+ Lesser General Public License for more details. |
|
+ |
|
+ You should have received a copy of the GNU General Public License |
|
+ along with this library. If not, see <http://www.gnu.org/licenses/>. |
|
+ |
|
+ $Id$ |
|
+ |
|
+----------------------------------------------------------------------------*/ |
|
+ |
|
+#include "config.h" |
|
+#include "musicbrainz5/defines.h" |
|
+ |
|
+#include "musicbrainz5/xmlParser.h" |
|
+ |
|
+#include <cstring> |
|
+ |
|
+XMLNode XMLNode::emptyNode() |
|
+{ |
|
+ return XMLNode(NULL); |
|
+} |
|
+ |
|
+XMLNode *XMLRootNode::parseFile(const std::string &filename, xmlErrorPtr results) |
|
+{ |
|
+ xmlDocPtr doc; |
|
+ |
|
+ doc = xmlParseFile(filename.c_str()); |
|
+ if ((doc == NULL) && (results != NULL)) { |
|
+ xmlCopyError(xmlGetLastError(), results); |
|
+ } |
|
+ |
|
+ return new XMLRootNode(doc); |
|
+} |
|
+ |
|
+XMLNode *XMLRootNode::parseString(std::string &xml, xmlErrorPtr results) |
|
+{ |
|
+ xmlDocPtr doc; |
|
+ |
|
+ doc = xmlParseMemory(xml.c_str(), xml.length()); |
|
+ if ((doc == NULL) && (results != NULL)) { |
|
+ xmlCopyError(xmlGetLastError(), results); |
|
+ } |
|
+ |
|
+ return new XMLRootNode(doc); |
|
+} |
|
+ |
|
+const char *XMLNode::getName() const |
|
+{ |
|
+ return (char *)mNode->name; |
|
+} |
|
+ |
|
+const char *XMLNode::getText() const |
|
+{ |
|
+ if (mNode->children == NULL) |
|
+ return NULL; |
|
+ if (!xmlNodeIsText(mNode->children)) |
|
+ return NULL; |
|
+ |
|
+ return (char*)mNode->children->content; |
|
+} |
|
+ |
|
+xmlAttrPtr XMLNode::getAttributeRaw(const char *name) const |
|
+{ |
|
+ xmlAttrPtr attr; |
|
+ |
|
+ for (attr = mNode->properties; attr != NULL; attr = attr->next) |
|
+ if (strcmp(name, (char *)attr->name) == 0) |
|
+ return attr; |
|
+ |
|
+ return NULL; |
|
+} |
|
+ |
|
+const XMLAttribute XMLNode::getAttribute(const char *name) const |
|
+{ |
|
+ xmlAttrPtr attr; |
|
+ |
|
+ if (name == NULL) |
|
+ return XMLAttribute(mNode->properties); |
|
+ |
|
+ attr = this->getAttributeRaw(name); |
|
+ if (attr != NULL) |
|
+ return XMLAttribute(attr); |
|
+ |
|
+ return XMLAttribute(NULL); |
|
+} |
|
+ |
|
+bool XMLNode::isAttributeSet(const char *name) const |
|
+{ |
|
+ return (this->getAttributeRaw(name) != NULL); |
|
+} |
|
+ |
|
+XMLRootNode::XMLRootNode(xmlDocPtr doc): XMLNode(xmlDocGetRootElement(doc)), |
|
+ mDoc(doc) |
|
+{ |
|
+} |
|
+ |
|
+static xmlNodePtr skipTextNodes(xmlNodePtr node) |
|
+{ |
|
+ xmlNodePtr it = node; |
|
+ |
|
+ while ((it != NULL) && xmlNodeIsText(it)) |
|
+ it = it->next; |
|
+ |
|
+ return it; |
|
+} |
|
+ |
|
+XMLNode XMLNode::next() const |
|
+{ |
|
+ return XMLNode(skipTextNodes(mNode->next)); |
|
+} |
|
+ |
|
+XMLNode XMLNode::getChildNode(const char *name) const |
|
+{ |
|
+ xmlNodePtr it; |
|
+ if (name == NULL) |
|
+ return XMLNode(skipTextNodes(mNode->children)); |
|
+ |
|
+ for (it = mNode->children; it != NULL; it = it->next) { |
|
+ if (xmlNodeIsText(it)) |
|
+ continue; |
|
+ if (strcmp(name, (char *)it->name) == 0) |
|
+ return XMLNode(it); |
|
+ } |
|
+ |
|
+ return emptyNode(); |
|
+} |
|
+ |
|
+bool XMLNode::isEmpty() const |
|
+{ |
|
+ return mNode == NULL; |
|
+} |
|
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt |
|
index 645f8ae..8dd569c 100644 |
|
--- a/tests/CMakeLists.txt |
|
+++ b/tests/CMakeLists.txt |
|
@@ -1,5 +1,5 @@ |
|
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include) |
|
-LINK_LIBRARIES(musicbrainz5 ${NEON_LIBRARIES}) |
|
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include ${LIBXML2_INCLUDE_DIR}) |
|
+LINK_LIBRARIES(musicbrainz5 ${NEON_LIBRARIES} ${LIBXML2_LIBRARIES}) |
|
ADD_EXECUTABLE(mbtest mbtest.cc) |
|
ADD_EXECUTABLE(ctest ctest.c) |
|
|
|
|