Created
October 17, 2015 23:47
-
-
Save goldsborough/07ecacbf35ace741a539 to your computer and use it in GitHub Desktop.
Compresses XML to a more compact representation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename Node> | |
class XMLCompressor | |
{ | |
public: | |
using map_t = std::map<std::string, std::string>; | |
static map_t global_keywords; | |
std::string operator()(Node* node, map_t& keywords = global_keywords) | |
{ | |
std::string string; | |
_compress(node, string, keywords); | |
string.pop_back(); | |
return string; | |
} | |
private: | |
void _compress(Node* node, std::string& string, map_t& keywords) | |
{ | |
if (! node) return; | |
string += keywords.at(node->tag) + " "; | |
for (const auto& attribute : node->attributes) | |
{ | |
string += keywords.at(attribute.first) + " "; | |
string += attribute.second + " "; | |
} | |
string += "0 "; | |
if (! node->data.empty()) | |
{ | |
string += node->data + " "; | |
} | |
for (const auto& child : node->children) | |
{ | |
_compress(child, string, keywords); | |
} | |
string += "0 "; | |
} | |
}; | |
template<typename Node> | |
typename XMLCompressor<Node>::map_t XMLCompressor<Node>::global_keywords = { | |
{"family", "1"}, | |
{"person", "2"}, | |
{"first_name", "3"}, | |
{"last_name", "4"}, | |
{"state", "5"} | |
}; | |
template<typename Node> | |
std::string compress(Node* root) | |
{ | |
XMLCompressor<Node> compress; | |
return compress(root); | |
} | |
struct XMLNode | |
{ | |
using attributes_t = std::map<std::string, std::string>; | |
using children_t = std::vector<XMLNode*>; | |
XMLNode(const std::string& tag_, | |
const std::string& data_, | |
const attributes_t& attributes_ = attributes_t(), | |
const children_t& children_ = children_t()) | |
: tag(tag_) | |
, data(data_) | |
, attributes(attributes_) | |
, children(children_) | |
{ } | |
std::string tag; | |
std::string data; | |
attributes_t attributes; | |
std::vector<XMLNode*> children; | |
}; | |
template<typename Node> | |
void delete_xml_tree(Node* node) | |
{ | |
for (auto& child : node->children) | |
{ | |
delete_xml_tree(child); | |
} | |
delete node; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
XMLNode* root = new XMLNode("family", | |
"", | |
{ | |
{"last_name", "McDowell"}, | |
{"state", "CA"} | |
}, | |
{ | |
new XMLNode("person", | |
"Some Message", | |
{{"first_name", "Gayle"}}) | |
}); | |
print::ln(compress(root)); | |
delete_xml_tree(root); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment