Rapidxml: adding subtree directly as value
Pergunta
I'm trying to append a very big subtree using rapidxml in a dirty way, exploiting the value
method
rapidxml::xml_node<>* node = allocate_node(rapidxml::node_element, "tree");
node->value("<very><long><subtree></subtree></long></very>");
but it but the angle brackets are expanded into <
and >
when I print the document. The clean way would be to manually declare and append every single node and attribute of the subtree, which is pretty boring.
Is there a way to prevent brackets expansion, or can you suggest any other practical way to quickly add a big branch?
Solução 2
Ok, I came out with this workaround, automatically creating the structure and appending it:
char txt[] = "<very><long><xml with="attributes"></xml></long></very>"; // or extract from file
rapidxml::xml_document<char> tmp;
tmp.parse<0>(txt);
rapidxml::xml_node<char> *subt = tmp.first_node();
tmp.remove_all_nodes(); // detach, since you can't have more than one parent
appendHere.append_node(subt);
any idea to improve it, maybe to avoid the extra overhead to parse the subtree?
Outras dicas
Imho easiest way would be to parse it with new document and then just clone it, something like
void appendLongTree(rapidxml::xml_document<>* document,
rapidxml::xml_node<>* parent,
char* value) {
rapidxml::xml_document<>* new_document = new rapidxml::xml_document<>();
// if we don't wanna bother about lifetime of the string,
// save a string in target's document
new_document.parse<0>(document->allocate_string(value));
parent->append_node(document->clone_node(new_document->first_node()));
delete new_document;
}
I don't think it's a big overhead in parsing...
Write a helper function or class, e.g.
#include <iostream>
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
class Node_Adder
{
public:
Node_Adder(rapidxml::xml_document<> & doc) : m_doc(doc) { }
rapidxml::xml_node<> * operator()(rapidxml::xml_node<> * parent,
char const * node_name)
{
char * name = m_doc.allocate_string(node_name);
rapidxml::xml_node<> * child = m_doc.allocate_node(rapidxml::node_element, name);
parent->append_node(child);
return child;
}
protected:
private:
rapidxml::xml_document<> & m_doc;
};
void stackoverflow()
{
rapidxml::xml_document<> doc;
rapidxml::xml_node<char> * decl = doc.allocate_node(rapidxml::node_declaration);
decl->append_attribute(doc.allocate_attribute("version", "1.0"));
decl->append_attribute(doc.allocate_attribute("encoding", "UTF-8"));
doc.append_node(decl);
rapidxml::xml_node<> * root = doc.allocate_node(rapidxml::node_element, "root");
doc.append_node(root);
Node_Adder add(doc);
add(add(add(root, "very"), "long"), "subtree");
rapidxml::print(std::ostreambuf_iterator<char>(std::cout), doc);
}
which prints
<?xml version="1.0" encoding="UTF-8"?>
<root>
<very>
<long>
<subtree/>
</long>
</very>
</root>