0

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 &lt and &gt 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?

Cavaz
  • 2,682
  • 19
  • 33

3 Answers3

2

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...

1

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?

Cavaz
  • 2,682
  • 19
  • 33
0

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>
MadScientist
  • 3,140
  • 12
  • 19
  • well, this was a simple example. The real subtree has multiple branches and attributes... My point was to find a way to brutally cut&paste the text without manually managing the whole structure. – Cavaz Oct 15 '12 at 09:03