Я недавно начал использовать RapidXML, и синтаксический анализ значений — это хорошо (я могу получить данные из элементов), но я хочу редактировать значения внутри элементов.
Для целей этой программы я хочу включить это:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<data>
This is data.
</data>
</root>
В это:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<data>
Edited!
</data>
</root>
Я где-то читал, что rapidxml::xml_node
имеет value()
функция для изменения значения внутри элемента, но это не похоже на работу. Когда я записываю в файл, я получаю то же самое, что и раньше. Вот мой код:
std::string input_xml = loadFile(filename);
std::vector<char> xml_copy(input_xml.begin(), input_xml.end());
xml_copy.push_back('\0');
rapidxml::xml_document<> doc;
doc.parse<rapidxml::parse_declaration_node | rapidxml::parse_non_destructive>(&xml_copy[0]);
// Also tried with doc.parse<0>(&xml_copy[0]) but no luck
rapidxml::xml_node<>* root_node = doc.first_node("root");
root_node->first_node("data")->value(std::string("Edited!").c_str());
std::string data = std::string(xml_copy.begin(), xml_copy.end());
std::ofstream file;
file.open(filename.c_str());
file << data;
file.close();
Есть идеи?
Редактировать:
В сочетании с принятым ответом parse()
функция должна также иметь rapidxml::parse_no_data_nodes
флаг:
std::string input_xml = TileManager::getData(filename);
std::vector<char> xml_copy(input_xml.begin(), input_xml.end());
xml_copy.push_back('\0');
rapidxml::xml_document<> doc;
doc.parse<rapidxml::parse_no_data_nodes>(&xml_copy[0]); // Notice the flag here
rapidxml::xml_node<>* root_node = doc.first_node("root");
std::string s = "test";
const char * text = doc.allocate_string(s.c_str(), strlen(s.c_str()));
root_node->first_node("data")->value(text);
std::string data;
rapidxml::print(std::back_inserter(data), doc);
std::ofstream file;
file.open(filename.c_str());
file << data;
file.close();
Тогда это будет работать.
Взгляните на это http://rapidxml.sourceforge.net/manual.html#namespacerapidxml_1lifetime_of_source_text. С RapidXML вы в основном должны гарантировать, что любые строки, которые вы записываете в документ, сохраняются в течение всего срока действия документа. В своем коде вы назначаете временный объект, который не будет существовать после этого вызова
root_node->first_node("data")->value(std::string("Edited!").c_str());
пытаться
std::string new_value = "Edited!";
root_node->first_node("data")->value(new_value.c_str());
и это должно работать для вас. Посмотрите на это также в отношении вывода результирующего XML в строку http://rapidxml.sourceforge.net/manual.html#namespacerapidxml_1printing
флаг разбора rapidxml :: parse_no_data_nodes недостаточно. Отсутствует узел объявления
< ? xml version = «1.0» encoding = «UTF-8»? >
в выходном файле.
Например, вы должны использовать похожие флаги:
doc.parse < trapidxml::parse_full | rapidxml::parse_no_data_nodes >(&xml_copy[0]);
Тогда это работает.
[CentOS7.2]