c++c++11rapidxml

Trying to append unique XML attributes to nodes using RapidXML


I want to append attributes to each node found in a root tag in an iterator, and I want the attribute to be id with indices assigned to them. Here is the block of code used for iterating over the child nodes, allocating and appending each attribute to each node:

for (xml_node<>* node = root->first_node("lang")->first_node("strings")->first_node();
     node; node = node->next_sibling()) 
{
    node->append_attribute(
        document.allocate_attribute(
            "id", (std::to_string(index)).c_str()
            )
        );
    index += 1;
}

After inspection, it seems that document.allocate_attribute isn't creating a new pointer as I expected it to, since the most of the id attributes in the XML output produced by my function print_document, show mostly duplicate values, i.e.:

<translations>
    <lang>
        <strings>
        ...
        <s id="895">string1</s>
        <s id="895">string2</s>
        <s id="895">string3</s>
        ...
        </strings>
    </lang>
</translations>

print_document is simply:

void print_document(xml_document<> &document)
{
    rapidxml::print(std::cout, document, 0);
}

Given that I'm not overly concerned with memory usage, how can I ensure that each appended attribute value is unique?


Solution

  • This is a classic stumble due to RapidXML's string ownership design.

    When you add an attribute, RapidXML doesn't make a copy of the attribute string - it just stores the pointer, which then goes out of scope and frequently gets reused for the next attribute...

    Use allocate_string to help you.

    Try this:-

    document.allocate_attribute("id", allocate_string(std::to_string(index).c_str()))