C++: How to extract a string from RapidXml
Asked Answered
Y

8

15

In my C++ program I want to parse a small piece of XML, insert some nodes, then extract the new XML (preferably as a std::string).
RapidXml has been recommended to me, but I can't see how to retrieve the XML back as a text string.
(I could iterate over the nodes and attributes and build it myself, but surely there's a build in function that I am missing.)
Thank you.

Yap answered 1/9, 2008 at 15:10 Comment(0)
C
11

Althoug the documentation is poor on this topic, I managed to get some working code by looking at the source. Although it is missing the xml header which normally contains important information. Here is a small example program that does what you are looking for using rapidxml:

#include <iostream>
#include <sstream>
#include "rapidxml/rapidxml.hpp"
#include "rapidxml/rapidxml_print.hpp"

int main(int argc, char* argv[]) {
    char xml[] = "<?xml version=\"1.0\" encoding=\"latin-1\"?>"
                 "<book>"
                 "</book>";

    //Parse the original document
    rapidxml::xml_document<> doc;
    doc.parse<0>(xml);
    std::cout << "Name of my first node is: " << doc.first_node()->name() << "\n";

    //Insert something
    rapidxml::xml_node<> *node = doc.allocate_node(rapidxml::node_element, "author", "John Doe");
    doc.first_node()->append_node(node);

    std::stringstream ss;
    ss <<*doc.first_node();
    std::string result_xml = ss.str();
    std::cout <<result_xml<<std::endl;
    return 0;
}
Cryptogenic answered 1/9, 2008 at 20:52 Comment(0)
P
6

Use print function (found in rapidxml_print.hpp utility header) to print the XML node contents to a stringstream.

Pepper answered 2/10, 2008 at 12:5 Comment(2)
Excellent, that allows me to suppress node indentationYap
Can you provide an example?Handshake
G
4

rapidxml::print reuqires an output iterator to generate the output, so a character string works with it. But this is risky because I can not know whether an array with fixed length (like 2048 bytes) is long enough to hold all the content of the XML.

The right way to do this is to pass in an output iterator of a string stream so allow the buffer to be expanded when the XML is being dumped into it.

My code is like below:

std::stringstream stream;
std::ostream_iterator<char> iter(stream);

rapidxml::print(iter, doc, rapidxml::print_no_indenting);

printf("%s\n", stream.str().c_str());
printf("len = %d\n", stream.str().size());
Glenine answered 9/12, 2011 at 6:59 Comment(0)
S
2

If you do build XML yourself, don't forget to escape the special characters. This tends to be overlooked, but can cause some serious headaches if it is not implemented:

  • <        &lt;
  • >        &gt;
  • &        &amp;
  • "        &quot;
  • '        &apos;
Sisyphus answered 1/9, 2008 at 16:34 Comment(0)
N
2

Here's how to print a node to a string straight from the RapidXML Manual:

xml_document<> doc;    // character type defaults to char
// ... some code to fill the document

// Print to stream using operator <<
std::cout << doc;   

// Print to stream using print function, specifying printing flags
print(std::cout, doc, 0);   // 0 means default printing flags

// Print to string using output iterator
std::string s;
print(std::back_inserter(s), doc, 0);

// Print to memory buffer using output iterator
char buffer[4096];                      // You are responsible for making the buffer large enough!
char *end = print(buffer, doc, 0);      // end contains pointer to character after last printed character
*end = 0;                               // Add string terminator after XML
Nationalize answered 14/8, 2010 at 16:44 Comment(0)
S
0

If you aren't yet committed to Rapid XML, I can recommend some alternative libraries:

Sisyphus answered 1/9, 2008 at 16:29 Comment(1)
Just don't forget the few hundred percent speed penalty for these libraries -- though they both have a lot more features than RapidXML.Kipton
T
0

Use static_cast<>

Ex:

rapidxml::xml_document<> doc;
rapidxml::xml_node <> * root_node = doc.first_node();
std::string strBuff;

doc.parse<0>(xml);

.
.
.
strBuff = static_cast<std::string>(root_node->first_attribute("attribute_name")->value());
Thunderstorm answered 22/2, 2013 at 11:50 Comment(0)
D
0

Following is very easy,

std::string s;
print(back_inserter(s), doc, 0);
cout << s;

You only need to include "rapidxml_print.hpp" header in your source code.

Decolonize answered 26/2, 2013 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.