Commit b4162e34 authored by Pavel Vainerman's avatar Pavel Vainerman

(UniXML): небольшой рефакторинг

parent 1cacc5e6
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <assert.h> #include <assert.h>
#include <string> #include <string>
#include <cstddef> #include <cstddef>
#include <memory>
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/tree.h> #include <libxml/tree.h>
...@@ -45,7 +46,6 @@ class UniXML_iterator: ...@@ -45,7 +46,6 @@ class UniXML_iterator:
std::string getProp2( const std::string& name, const std::string& defval = "" ); std::string getProp2( const std::string& name, const std::string& defval = "" );
std::string getProp( const std::string& name ); std::string getProp( const std::string& name );
std::string getPropUtf8( const std::string& name );
int getIntProp( const std::string& name ); int getIntProp( const std::string& name );
/// if value if not positive ( <= 0 ), returns def /// if value if not positive ( <= 0 ), returns def
int getPIntProp( const std::string& name, int def ); int getPIntProp( const std::string& name, int def );
...@@ -66,25 +66,7 @@ class UniXML_iterator: ...@@ -66,25 +66,7 @@ class UniXML_iterator:
bool canPrev(); bool canPrev();
bool canNext(); bool canNext();
#if 0
friend inline bool operator==(const UniXML_iterator& lhs, const UniXML_iterator& rhs)
{
return ( lhs.curNode != 0 && rhs.curNode != 0 && lhs.curNode == rhs.curNode );
}
friend inline bool operator!=(const UniXML_iterator& lhs, const UniXML_iterator& rhs)
{
return !(lhs == rhs);
}
inline bool operator==(int a)
{
if( a == 0 )
return (curNode == NULL);
return false;
}
#endif
// Перейти к следующему узлу // Перейти к следующему узлу
UniXML_iterator& operator+(int); UniXML_iterator& operator+(int);
UniXML_iterator& operator++(int); UniXML_iterator& operator++(int);
...@@ -108,50 +90,19 @@ class UniXML_iterator: ...@@ -108,50 +90,19 @@ class UniXML_iterator:
bool goChildren(); bool goChildren();
// Получить текущий узел // Получить текущий узел
xmlNode* getCurrent() xmlNode* getCurrent();
{
return curNode;
}
// Получить название текущего узла // Получить название текущего узла
inline const std::string getName() const const std::string getName() const;
{ const std::string getContent() const;
if( curNode )
{
if( !curNode->name )
return "";
return (char*) curNode->name;
}
return ""; operator xmlNode* () const;
}
const std::string getContent() const; void goBegin();
void goEnd();
inline operator xmlNode* () const private:
{
//ulog.< "current\n";
return curNode;
}
inline void goBegin()
{
while(canPrev())
{
goPrev();
}
}
inline void goEnd()
{
while(canNext())
{
goNext();
}
}
protected:
xmlNode* curNode; xmlNode* curNode;
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -161,57 +112,34 @@ class UniXML ...@@ -161,57 +112,34 @@ class UniXML
typedef UniXML_iterator iterator; typedef UniXML_iterator iterator;
inline xmlNode* getFirstNode() UniXML( const std::string& filename );
{ UniXML();
return xmlDocGetRootElement(doc); ~UniXML();
}
inline xmlNode* getFirstNode() const
{
return xmlDocGetRootElement(doc);
}
xmlNode* getFirstNode();
xmlNode* getFirstNode() const;
/*! возвращает итератор на самый первый узел документа */ /*! возвращает итератор на самый первый узел документа */
inline iterator begin() iterator begin();
{ iterator end();
return iterator(getFirstNode());
}
inline iterator end()
{
return iterator(NULL);
}
// Загружает указанный файл // Загружает указанный файл
void open(const std::string& filename); void open( const std::string& filename );
void close(); void close();
inline bool isOpen() const bool isOpen() const;
{
return doc != 0;
}
UniXML( const std::string& filename );
UniXML();
~UniXML();
xmlDoc* doc; std::string getFileName() const;
inline std::string getFileName() const
{
return filename;
}
// Создать новый XML-документ // Создать новый XML-документ
void newDoc(const std::string& root_node, std::string xml_ver = "1.0"); void newDoc( const std::string& root_node, const std::string& xml_ver = "1.0");
// Получить свойство name указанного узла node // Получить свойство name указанного узла node
static std::string getProp(const xmlNode* node, const std::string& name); static std::string getProp(const xmlNode* node, const std::string& name);
static std::string getProp2(const xmlNode* node, const std::string& name, const std::string& defval = "" ); static std::string getProp2(const xmlNode* node, const std::string& name, const std::string& defval = "" );
static std::string getPropUtf8(const xmlNode* node, const std::string& name);
static int getIntProp(const xmlNode* node, const std::string& name); static int getIntProp(const xmlNode* node, const std::string& name);
/// if value if not positive ( <= 0 ), returns def /// if value if not positive ( <= 0 ), returns def
static int getPIntProp(const xmlNode* node, const std::string& name, int def); static int getPIntProp(const xmlNode* node, const std::string& name, int def);
...@@ -240,27 +168,15 @@ class UniXML ...@@ -240,27 +168,15 @@ class UniXML
// После проверки исправить рекурсивный алгоритм на обычный, // После проверки исправить рекурсивный алгоритм на обычный,
// используя ->parent // используя ->parent
xmlNode* findNode( xmlNode* node, const std::string& searchnode, const std::string& name = "") const; xmlNode* findNode( xmlNode* node, const std::string& searchnode, const std::string& name = "") const;
xmlNode* findNodeUtf8( xmlNode* node, const std::string& searchnode, const std::string& name = "") const;
// ?? // ??
//width means number of nodes of the same level as node in 1-st parameter (width number includes first node) //width means number of nodes of the same level as node in 1-st parameter (width number includes first node)
//depth means number of times we can go to the children, if 0 we can't go only to elements of the same level //depth means number of times we can go to the children, if 0 we can't go only to elements of the same level
xmlNode* extFindNode( xmlNode* node, int depth, int width, const std::string& searchnode, const std::string& name = "", bool top = true ) const; xmlNode* extFindNode( xmlNode* node, int depth, int width, const std::string& searchnode, const std::string& name = "", bool top = true ) const;
xmlNode* extFindNodeUtf8( xmlNode* node, int depth, int width, const std::string& searchnode, const std::string& name = "", bool top = true ) const;
protected: protected:
std::string filename; std::string filename;
std::shared_ptr<xmlDoc> doc = { nullptr };
// Преобразование текстовой строки из XML в строку нашего внутреннего представления
static std::string xml2local( const std::string& text );
// Преобразование текстовой строки из нашего внутреннего представления в строку для XML
// Возвращает указатель на временный буфер, который один на все вызовы функции.
static const xmlChar* local2xml( const std::string& text );
static std::string local2utf8( const std::string& text );
static size_t recur;
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#endif #endif
...@@ -30,89 +30,121 @@ ...@@ -30,89 +30,121 @@
#include "UniXML.h" #include "UniXML.h"
#include "Exceptions.h" #include "Exceptions.h"
#include <libxml/xinclude.h> #include <libxml/xinclude.h>
// -----------------------------------------------------------------------------
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace std; using namespace std;
// -----------------------------------------------------------------------------
/* FIXME: /* FIXME:
Возможно стоит использовать в качестве основы libxmlmm. Возможно стоит использовать в качестве основы libxmlmm.
Перед переделкой нужно написать полный тест на все функции UniXML. Перед переделкой нужно написать полный тест на все функции UniXML.
Особенно проверить распознавание кодировки XML-файла Особенно проверить распознавание кодировки XML-файла
----
Либо переходить на Poco::XML - но это несовместимость со всеми проектам, т.к.
не станет xmlNode*.
Либо возможно typedef Poco::XML::Node xmlNode;
*/ */
// -----------------------------------------------------------------------------
// Временная переменная для подсчёта рекурсии UniXML::UniXML(const string& fname):
size_t UniXML::recur = 0; filename(fname)
UniXML::UniXML(const string& filename):
doc(0),
filename(filename)
{ {
open(filename); open(filename);
} }
UniXML::UniXML(): UniXML::UniXML()
doc(0)
{ {
} }
// -----------------------------------------------------------------------------
UniXML::~UniXML() UniXML::~UniXML()
{ {
close(); close();
} }
// -----------------------------------------------------------------------------
void UniXML::newDoc(const string& root_node, string xml_ver) string UniXML::getFileName() const
{
return filename;
}
// -----------------------------------------------------------------------------
struct UniXMLDocDeleter
{
void operator()(xmlDoc* doc) const
{
try
{
if( doc )
xmlFreeDoc(doc);
}
catch(...) {}
}
};
// -----------------------------------------------------------------------------
void UniXML::newDoc(const string& root_node, const string& xml_ver)
{ {
assert(doc == 0); // предыдущий doc не удален из памяти assert(doc == nullptr); // предыдущий doc не удален из памяти
xmlKeepBlanksDefault(0); xmlKeepBlanksDefault(0);
xmlNode* rootnode; xmlDoc* d = xmlNewDoc((const xmlChar*)xml_ver.c_str());
doc = xmlNewDoc((const xmlChar*)xml_ver.c_str()); if( d == NULL )
// xmlEncodeEntitiesReentrant(doc, (const xmlChar*)ExternalEncoding.c_str());
rootnode = xmlNewDocNode(doc, NULL, (const xmlChar*)root_node.c_str(), NULL);
xmlDocSetRootElement(doc, rootnode);
//assert(doc != NULL);
if(doc == NULL)
throw NameNotFound("UniXML(open): не смогли создать doc=" + root_node); throw NameNotFound("UniXML(open): не смогли создать doc=" + root_node);
}
void UniXML::open(const string& _filename) doc = std::shared_ptr<xmlDoc>(d, UniXMLDocDeleter());
// xmlEncodeEntitiesReentrant(doc, (const xmlChar*)ExternalEncoding.c_str());
xmlNode* rootnode = xmlNewDocNode(d, NULL, (const xmlChar*)root_node.c_str(), NULL);
xmlDocSetRootElement(d, rootnode);
}
// -----------------------------------------------------------------------------
xmlNode* UniXML::getFirstNode()
{
return xmlDocGetRootElement(doc.get());
}
// -----------------------------------------------------------------------------
xmlNode* UniXML::getFirstNode() const
{
return xmlDocGetRootElement(doc.get());
}
// -----------------------------------------------------------------------------
UniXML::iterator UniXML::begin()
{
return iterator(getFirstNode());
}
// -----------------------------------------------------------------------------
UniXML::iterator UniXML::end()
{ {
// if(doc) return iterator(NULL);
// close(); }
assert(doc == 0); // предыдущий doc не удален из памяти // -----------------------------------------------------------------------------
void UniXML::open( const string& _filename )
{
assert( doc == nullptr ); // предыдущий doc не удален из памяти
xmlKeepBlanksDefault(0); xmlKeepBlanksDefault(0);
// Can read files in any encoding, recode to UTF-8 internally // Can read files in any encoding, recode to UTF-8 internally
doc = xmlParseFile(_filename.c_str()); xmlDoc* d = xmlParseFile(_filename.c_str());
if(doc == NULL) if( d == NULL )
throw NameNotFound("UniXML(open): NotFound file=" + _filename); throw NameNotFound("UniXML(open): NotFound file=" + _filename);
doc = std::shared_ptr<xmlDoc>(d,UniXMLDocDeleter());
// Support for XInclude (see eterbug #6304) // Support for XInclude (see eterbug #6304)
// main tag must to have follow property: xmlns:xi="http://www.w3.org/2001/XInclude" // main tag must to have follow property: xmlns:xi="http://www.w3.org/2001/XInclude"
//For include: <xi:include href="test2.xml"/> //For include: <xi:include href="test2.xml"/>
xmlXIncludeProcess(doc); xmlXIncludeProcess(doc.get());
filename = _filename; filename = _filename;
} }
// -----------------------------------------------------------------------------
void UniXML::close() void UniXML::close()
{ {
if(doc) doc = nullptr;
{
xmlFreeDoc(doc);
doc = 0;
}
filename = ""; filename = "";
} }
// -----------------------------------------------------------------------------
/* FIXME: compatibility, remove later */ bool UniXML::isOpen() const
string UniXML::getPropUtf8(const xmlNode* node, const string& name)
{ {
return getProp(node, name); return (doc != nullptr);
} }
// -----------------------------------------------------------------------------
string UniXML::getProp2(const xmlNode* node, const string& name, const string& defval) string UniXML::getProp2(const xmlNode* node, const string& name, const string& defval)
{ {
string s(getProp(node, name)); string s(getProp(node, name));
...@@ -122,7 +154,7 @@ string UniXML::getProp2(const xmlNode* node, const string& name, const string& d ...@@ -122,7 +154,7 @@ string UniXML::getProp2(const xmlNode* node, const string& name, const string& d
return defval; return defval;
} }
// -----------------------------------------------------------------------------
string UniXML::getProp(const xmlNode* node, const string& name) string UniXML::getProp(const xmlNode* node, const string& name)
{ {
xmlChar* text = ::xmlGetProp((xmlNode*)node, (const xmlChar*)name.c_str()); xmlChar* text = ::xmlGetProp((xmlNode*)node, (const xmlChar*)name.c_str());
...@@ -137,12 +169,12 @@ string UniXML::getProp(const xmlNode* node, const string& name) ...@@ -137,12 +169,12 @@ string UniXML::getProp(const xmlNode* node, const string& name)
xmlFree( (xmlChar*) text ); xmlFree( (xmlChar*) text );
return std::move(t); return std::move(t);
} }
// -----------------------------------------------------------------------------
int UniXML::getIntProp(const xmlNode* node, const string& name ) int UniXML::getIntProp(const xmlNode* node, const string& name )
{ {
return UniSetTypes::uni_atoi(getProp(node, name)); return UniSetTypes::uni_atoi(getProp(node, name));
} }
// -----------------------------------------------------------------------------
int UniXML::getPIntProp(const xmlNode* node, const string& name, int def ) int UniXML::getPIntProp(const xmlNode* node, const string& name, int def )
{ {
string param( getProp(node, name) ); string param( getProp(node, name) );
...@@ -152,17 +184,17 @@ int UniXML::getPIntProp(const xmlNode* node, const string& name, int def ) ...@@ -152,17 +184,17 @@ int UniXML::getPIntProp(const xmlNode* node, const string& name, int def )
return UniSetTypes::uni_atoi(param); return UniSetTypes::uni_atoi(param);
} }
// -----------------------------------------------------------------------------
void UniXML::setProp(xmlNode* node, const string& name, const string& text ) void UniXML::setProp(xmlNode* node, const string& name, const string& text )
{ {
::xmlSetProp(node, (const xmlChar*)name.c_str(), (const xmlChar*)text.c_str()); ::xmlSetProp(node, (const xmlChar*)name.c_str(), (const xmlChar*)text.c_str());
} }
// -----------------------------------------------------------------------------
xmlNode* UniXML::createChild(xmlNode* node, const string& title, const string& text) xmlNode* UniXML::createChild(xmlNode* node, const string& title, const string& text)
{ {
return ::xmlNewChild(node, NULL, (const xmlChar*)title.c_str(), (const xmlChar*)text.c_str()); return ::xmlNewChild(node, NULL, (const xmlChar*)title.c_str(), (const xmlChar*)text.c_str());
} }
// -----------------------------------------------------------------------------
xmlNode* UniXML::createNext(xmlNode* node, const string& title, const string& text) xmlNode* UniXML::createNext(xmlNode* node, const string& title, const string& text)
{ {
if( node->parent ) if( node->parent )
...@@ -170,14 +202,14 @@ xmlNode* UniXML::createNext(xmlNode* node, const string& title, const string& te ...@@ -170,14 +202,14 @@ xmlNode* UniXML::createNext(xmlNode* node, const string& title, const string& te
return 0; return 0;
} }
// -----------------------------------------------------------------------------
/// Удаление указанного узла со всеми вложенными /// Удаление указанного узла со всеми вложенными
void UniXML::removeNode(xmlNode* node) void UniXML::removeNode(xmlNode* node)
{ {
::xmlUnlinkNode(node); ::xmlUnlinkNode(node);
::xmlFreeNode(node); ::xmlFreeNode(node);
} }
// -----------------------------------------------------------------------------
xmlNode* UniXML::copyNode(xmlNode* node, int recursive) xmlNode* UniXML::copyNode(xmlNode* node, int recursive)
{ {
// return ::xmlCopyNode(node,recursive); // return ::xmlCopyNode(node,recursive);
...@@ -209,8 +241,7 @@ xmlNode* UniXML::copyNode(xmlNode* node, int recursive) ...@@ -209,8 +241,7 @@ xmlNode* UniXML::copyNode(xmlNode* node, int recursive)
return 0; return 0;
} }
// -----------------------------------------------------------------------------
bool UniXML::save(const string& filename, int level) bool UniXML::save(const string& filename, int level)
{ {
string fn(filename); string fn(filename);
...@@ -223,11 +254,11 @@ bool UniXML::save(const string& filename, int level) ...@@ -223,11 +254,11 @@ bool UniXML::save(const string& filename, int level)
(void)rename(fn.c_str(), bakfilename.c_str()); (void)rename(fn.c_str(), bakfilename.c_str());
// int res = ::xmlSaveFormatFileEnc(fn.c_str(), doc, ExternalEncoding.c_str(), level); // int res = ::xmlSaveFormatFileEnc(fn.c_str(), doc, ExternalEncoding.c_str(), level);
// Write in UTF-8 without XML encoding in the header */ // Write in UTF-8 without XML encoding in the header */
int res = ::xmlSaveFormatFile(fn.c_str(), doc, level); int res = ::xmlSaveFormatFile(fn.c_str(), doc.get(), level);
// int res = ::xmlSaveFile(fn.c_str(), doc); // int res = ::xmlSaveFile(fn.c_str(), doc);
return res > 0; return res > 0;
} }
// -----------------------------------------------------------------------------
// Переместить указатель к следующему узлу, обходит по всему дереву // Переместить указатель к следующему узлу, обходит по всему дереву
xmlNode* UniXML::nextNode(xmlNode* n) xmlNode* UniXML::nextNode(xmlNode* n)
{ {
...@@ -251,7 +282,7 @@ xmlNode* UniXML::nextNode(xmlNode* n) ...@@ -251,7 +282,7 @@ xmlNode* UniXML::nextNode(xmlNode* n)
return n; return n;
} }
// -----------------------------------------------------------------------------
xmlNode* UniXML::findNode( xmlNode* node, const string& searchnode, const string& name ) const xmlNode* UniXML::findNode( xmlNode* node, const string& searchnode, const string& name ) const
{ {
xmlNode* fnode = node; xmlNode* fnode = node;
...@@ -280,12 +311,6 @@ xmlNode* UniXML::findNode( xmlNode* node, const string& searchnode, const string ...@@ -280,12 +311,6 @@ xmlNode* UniXML::findNode( xmlNode* node, const string& searchnode, const string
return NULL; return NULL;
} }
xmlNode* UniXML::findNodeUtf8( xmlNode* node, const string& searchnode, const string& name ) const
{
return findNode(node, searchnode, name);
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -324,13 +349,7 @@ xmlNode* UniXML::extFindNode( xmlNode* node, int depth, int width, const string& ...@@ -324,13 +349,7 @@ xmlNode* UniXML::extFindNode( xmlNode* node, int depth, int width, const string&
return NULL; return NULL;
} }
// -----------------------------------------------------------------------------
xmlNode* UniXML::extFindNodeUtf8( xmlNode* node, int depth, int width, const string& searchnode, const string& name, bool top ) const
{
return extFindNode(node, depth, width, searchnode, name, top );
}
bool UniXML_iterator::goNext() bool UniXML_iterator::goNext()
{ {
if( !curNode ) // || !curNode->next ) if( !curNode ) // || !curNode->next )
...@@ -432,6 +451,24 @@ bool UniXML_iterator::goChildren() ...@@ -432,6 +451,24 @@ bool UniXML_iterator::goChildren()
return true; return true;
} }
// -------------------------------------------------------------------------
xmlNode*UniXML_iterator::getCurrent()
{
return curNode;
}
// -------------------------------------------------------------------------
const string UniXML_iterator::getName() const
{
if( curNode )
{
if( !curNode->name )
return "";
return (char*) curNode->name;
}
return "";
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
string UniXML_iterator::getProp2( const string& name, const string& defval ) string UniXML_iterator::getProp2( const string& name, const string& defval )
...@@ -452,13 +489,28 @@ const string UniXML_iterator::getContent() const ...@@ -452,13 +489,28 @@ const string UniXML_iterator::getContent() const
return (const char*)::xmlNodeGetContent(curNode); return (const char*)::xmlNodeGetContent(curNode);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
string UniXML_iterator::getPropUtf8( const string& name ) void UniXML_iterator::goBegin()
{ {
return UniXML::getProp(curNode, name); while(canPrev())
{
goPrev();
}
}
// -------------------------------------------------------------------------
void UniXML_iterator::goEnd()
{
while(canNext())
{
goNext();
}
}
// -------------------------------------------------------------------------
UniXML_iterator::operator xmlNode*() const
{
//ulog.< "current\n";
return curNode;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
int UniXML_iterator::getIntProp( const string& name ) int UniXML_iterator::getIntProp( const string& name )
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment