Ошибки значения атрибута RapidXML

Раньше я использовал RapidXML с несколько проблемами, но эта поставила меня в тупик.

Я создаю журнал временных меток событий приложения, которые внешняя программа может прочитать в воспроизведении любого звука, который произошел в исходном приложении в нужное время.

При инициализации приложения правильно генерируется следующий XML:

<?xml version="1.0" encoding="utf-8"?>
<playbacklog>
    <logitem type="general" event="start" timestamp="85639323"/>
</playbacklog>

После добавления следующего элемента документы становятся такими:

<?xml version="1.0" encoding="utf-8"?>
<playbacklog>
    <logitem type="general" event="start" timestamp="NUL NUL NUL NUL"/>
    <logitem type="audio" event="start" timestamp="86473833">
</playbacklog>

а потом:

<?xml version="1.0" encoding="utf-8"?>
<playbacklog>
    <logitem type="general" event="start" timestamp="@NUL NUL' NUL NUL"/>
    <logitem type="audio" event="start" timestamp="NUL NUL NUL NUL">
    <logitem type="audio" event="stop" timestamp="8654533">
</playbacklog>

С добавлением каждой новой пары start и stop также наблюдается окончательное следующее поведение, при этом значение метки времени изменяется для всех узлов с одинаковым значением атрибута события. :

<?xml version="1.0" encoding="utf-8"?>
<playbacklog>
    <logitem type="general" event="start" timestamp="@NUL NUL' NUL NUL"/>
    <logitem type="audio" event="start" timestamp="NUL NUL NUL NUL">
    <logitem type="audio" event="stop" timestamp="8674519">
    <logitem type="audio" event="start" timestamp="NUL NUL NUL NUL">
    <logitem type="audio" event="stop" timestamp="8674519">
    <logitem type="audio" event="start" timestamp="NUL NUL NUL NUL">
    <logitem type="audio" event="stop" timestamp="8674519">
</playbacklog>

Я объявляю документ как таковой в заголовочном файле С++:

private:
    rapidxml::xml_document<> outputDocument;

Чтобы создать каждый узел, я использую следующий код:

// tStamp is a typedef'd std::pair containing two std::string values, one for the
// time at which the evet occurred and the other containing the event type.
void AudioLogger::LogEvent( Timestamp* tStamp )
{
    rapidxml::xml_node<>* nodeToAdd = outputDocument.allocate_node(rapidxml::node_element, "logitem");
    ...
    nodeToAdd->append_attirbute(outputDocument.allocate_attribute("timestamp", ts->first.c_str()));
    ...

    outputDocument.first_node()->next_sibling()->append_node(nodeToAdd);
}

Значения TimeStamp*, переданные этой функции, хранятся в std::vector, и при добавлении нового вызывается эта функция.

Если у кого-то есть идеи о том, что здесь происходит, это будет огромной помощью. Кроме того, если потребуется дополнительная информация, я также смогу предоставить ее.


person user3168754    schedule 07.01.2014    source источник


Ответы (1)


Это классическая ошибка RapidXML. Всякий раз, когда вы передаете указатель char в RapidXML, он просто сохраняет указатель, а не копирует строку. Это четко задокументировано, но все же часто привлекает внимание людей. http://rapidxml.sourceforge.net/manual.html#namespacerapidxml_1modifying_dom_tree

Ответ заключается в использовании функции allocate_string следующим образом:

 nodeToAdd->append_attribute(outputDocument.allocate_attribute("timestamp", 
                             outputDocument.allocate_string(ts->first.c_str()))); 

(Вам не нужно обертывать «отметку времени» в allocate_string, потому что это литерал и поэтому не изменится).

Я обычно использую свою собственную вспомогательную оболочку - что-то вроде этого: -

class MyRapidXmlDoc : public rapidxml::xml_document<char>
{
...
  Attribute* allocateAttribute(const string &name, const string &value = "")
  {
    if (value.empty())
      return allocate_attribute(allocate_string(name.c_str()));
    else
      return allocate_attribute(allocate_string(name.c_str()), allocate_string(value.c_str()));
  }
person Roddy    schedule 10.01.2014