Files
libsst/ZUtil/ZXMLReader.cpp
2026-04-03 00:22:39 -05:00

110 lines
2.8 KiB
C++

#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;
}