В моей программе на С++ я хочу разобрать небольшой фрагмент XML, вставить некоторые узлы, а затем извлечь новый XML (желательно как std::string
).
RapidXml мне рекомендовали, но я не вижу, как вернуть XML в текстовую строку.
(Я мог бы перебирать узлы и атрибуты и сам создавать их, но, конечно же, есть функция сборки, которую мне не хватает.)
Спасибо.
С++: как извлечь строку из RapidXml
Ответ 1
Althoug документация плохая по этой теме, мне удалось получить некоторый рабочий код, посмотрев на источник. Хотя в нем отсутствует заголовок xml, который обычно содержит важную информацию. Вот небольшая примерная программа, которая делает то, что вы ищете, используя quickxml:
#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;
}
Ответ 2
Используйте print
функцию (найти в rapidxml_print.hpp
заголовок утилиты), чтобы напечатать содержимое XML node до stringstream
.
Ответ 3
Если вы сами создаете XML, не забывайте избегать специальных символов. Это, как правило, игнорируется, но может вызвать серьезные головные боли, если он не реализован:
- < & л;
- > & GT;
- & & амп;
- " "
- & APOS; & APOS;
Ответ 4
Здесь, как напечатать node строку прямо из Руководство RapidXML:
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
Ответ 5
rapidxml:: print reuqires выходной итератор для генерации вывода, поэтому с ним работает символьная строка. Но это опасно, потому что я не могу знать, достаточно ли массива с фиксированной длиной (например, 2048 байтов) для хранения всего содержимого XML.
Правильный способ сделать это - передать в выходной итератор потока строк, чтобы позволить расширять буфер при сбрасывании XML в него.
Мой код выглядит следующим образом:
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());
Ответ 6
Если вы еще не настроены на Rapid XML, я могу порекомендовать некоторые альтернативные библиотеки:
-
Xerces - это, вероятно, реализация defacto С++.
-
XMLite - мне повезло с этой минимальной реализацией XML. См. Статью в http://www.codeproject.com/KB/recipes/xmlite.aspx
Ответ 7
Используйте static_cast < >
Пример:
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());
Ответ 8
Следующее очень просто,
std::string s;
print(back_inserter(s), doc, 0);
cout << s;
Вам нужно включить заголовок "rapidxml_print.hpp" в исходный код.