Обновление значений узлов и атрибутов XML в C ++ с использованием RapidXML - PullRequest
0 голосов
/ 14 октября 2018

У меня есть XML-файл, который используется для хранения параметров камеры, который будет обновляться в ответ на изменения в пользовательском интерфейсе.С RapidXML я могу читать XML-файл, все элементы и значения их атрибутов.Однако, когда я пытаюсь обновить значение атрибута / элемента и сохранить его, файл не отражает новое значение, а показывает старое значение.Я пытался протестировать эту концепцию на небольшом XML-файле, например,

<?xml version="1.0" encoding="UTF-8"?>
<note>
    <to>Kum</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Dont forget me this weekend!</body>
</note>

Это просто простой пример файла без атрибутов> И вот мой код.

rapidxml::xml_document<> doc;
std::fstream file("TestFile.xml",std::ios::in|std::ios::out);

std::stringstream bufferStream;
bufferStream << file.rdbuf();
std::string content(bufferStream.str());
std::vector<char> buffer(content.begin(), content.end());
buffer.push_back('\0');
doc.parse<rapidxml::parse_no_data_nodes>(&content[0]);

rapidxml::xml_node<>* rootNode = doc.first_node();
std::cout <<"<"<< rootNode->name() <<">" << "\n";
rapidxml::xml_node<>* firstNode = rootNode->first_node("to");
std::cout << "<"<<firstNode->name()<<">" <<firstNode->value()<< "\n";

rapidxml::xml_node<> *real_thing = rootNode->first_node("from");

if (real_thing != nullptr)                              
{
    real_thing->value("yuck");  // now that should work
    std::cout << real_thing->name() << real_thing->value() << "\n";
}

Вот где я запутался.Как сохранить это изменение обратно в исходный файл XML.Если я это сделаю,

file << bufferStream.str();

Это не только не сохраняет новое значение, но, кажется, добавляет весь XML DOM вместо замены исходного значения элемента.Если кто-то может поделиться небольшим фрагментом о том, как решить эту задачу, я был бы признателен за это.Я провел весь день, просматривая документацию, но также не понимал флаги, которые передаются в функцию разбора.

Спасибо

1 Ответ

0 голосов
/ 16 октября 2018

RapidXML содержит внутреннее представление структуры документа, используя указатели на текстовые данные, хранящиеся в std::vector<char>, который вы передали parse.

Когда вы изменяете «значение узла, которого вы»действительно просто меняем указатель во внутренней структуре.Вам необходимо вернуться к строке, используя функции из rapidxml_print.hpp, которые включают в себя оператор записи в поток.

file << doc;

Почему он добавляется?Потому что после того, как вы прочитали данные, позиция потока находится в конце файла.Вы можете сбросить в начало, используя file.seek(0), но это не обрезает файл, если ваши новые данные короче старых.

Лучший подход - это просто записать данные в новый fstream, а не пытаться открыть их для одновременного чтения и записи.

Также см. Здесь несколько более аккуратные иболее быстрые способы анализа файла с помощью RapidXML. Как разобрать файл XML в RapidXML

...