Initial commit
This commit is contained in:
109
ZUtil/ZXMLReader.cpp
Normal file
109
ZUtil/ZXMLReader.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <ZUtil/ZXMLReader.hpp>
|
||||
|
||||
//We don't want rapidxml throwing exceptions at us, let the parse handler do it
|
||||
#ifndef RAPIDXML_NO_EXCEPTIONS
|
||||
#define RAPIDXML_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#include <rapidxml/rapidxml.hpp>
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
void parse_error_handler(const char *what, void *where, void *arg)
|
||||
{
|
||||
URFP(where); //For now
|
||||
|
||||
ZString& errorMsg = *((ZString*)arg);
|
||||
|
||||
errorMsg = "ZXMLReader (rapidxml): ";
|
||||
ZStringAlgo::Append(errorMsg, what);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZXMLReader::Read(const char* data, size_t length)
|
||||
{
|
||||
Tree.Clear();
|
||||
|
||||
ZString name; // current node name
|
||||
ZString value; // current node value
|
||||
|
||||
// make a copy of xml data so we can use rapidxml in destructive mode
|
||||
ZString xmlData(data, length);
|
||||
rapidxml::xml_document<> doc(&ErrorMessage); // character type is 'char'
|
||||
|
||||
// 0 is default flags (error message will be set by handler)
|
||||
if (!doc.parse<rapidxml::parse_no_data_nodes>(xmlData.Data())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterate the nodes and set data in the tree
|
||||
rapidxml::xml_node<> *node = doc.first_node();
|
||||
ZKVTree::Iterator itr = Tree.Begin();
|
||||
|
||||
while (node != NULL) {
|
||||
name = node->name();
|
||||
value = node->value();
|
||||
|
||||
// xml often contains a lot of control characters within the 'body'
|
||||
ZStringAlgo::Trim(value);
|
||||
|
||||
// add this node under the root node
|
||||
ZKVTree::Iterator node_itr = Tree.Add(itr, name, value);
|
||||
|
||||
// iterate the attributes and set data in the kvtree
|
||||
for (rapidxml::xml_attribute<> *attr = node->first_attribute(); attr != NULL; attr = attr->next_attribute()) {
|
||||
ZString attr_name = attr->name();
|
||||
ZString attr_value = attr->value();
|
||||
|
||||
// add this node under the newly created node
|
||||
Tree.Add(node_itr, attr_name, attr_value);
|
||||
}
|
||||
|
||||
// iterate to next node (check child first, then sibling, then go up to parent)
|
||||
if (node->first_node() != NULL) {
|
||||
node = node->first_node();
|
||||
itr = node_itr;
|
||||
} else if (node->next_sibling() != NULL) {
|
||||
node = node->next_sibling();
|
||||
} else {
|
||||
|
||||
// go to next element (up and out)
|
||||
while (node->parent() != NULL) {
|
||||
node = node->parent();
|
||||
|
||||
if (node->type() != rapidxml::node_document) {
|
||||
itr = itr.Parent();
|
||||
} else break;
|
||||
|
||||
if (node->next_sibling() != NULL) {
|
||||
node = node->next_sibling();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if we end up NULL or back at the 'document' node by going to parent, then we are done.
|
||||
if (node == NULL || node->parent() == NULL || node->type() == rapidxml::node_document) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZString& ZXMLReader::GetErrorString()
|
||||
{
|
||||
return ErrorMessage;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZXMLReader::GetKVTree(ZKVTree& _kvtree)
|
||||
{
|
||||
_kvtree = Tree;
|
||||
}
|
||||
Reference in New Issue
Block a user