Frage

I'm writing a set of results to an XML file. Each result set contains a series of results. My problem is that (during several executions of the code) when I try to write some new results a result to a set, the XML parser gets the very first (top) result set in an existing XML file, and appends the results to that (old) set. E.g:

<root>
  <result_set result_number="0">    <--- Parser selects this result set
    <result number="0">
      <tolerance>100</tolerance>
    </result>
    <result number="1">
        <tolerance>100</tolerance>
    </result>
    <resultnumber="0">          <---- This should be added to result set 1      
      <tolerance>100</tolerance>
    </result>
  </result_set>
  <result_set result_number="1"/>   <-- New result set added to Xml, missing results
</root>

Therefore, I would like to know whether it is possible to add the latest result set write to the top of the XML file? Alternatively, when retrieving the latest results set, fetch the last one in the list?

I hope I've explained myself clearly. Thanks

(Sample code I'm using)

void initialise(std::string filename)
{
  ptree pt;
  xml_writer_settings<char> w('\t', 1);
  read_xml(filename, pt, boost::property_tree::xml_parser::trim_whitespace);
  std::ofstream xmlFile(filename.c_str(), std::ios::out);

  // Probably not the best way to check for a root node
  try
  {
    ptree & rootNode = pt.get_child("root");
  }
  catch(...)
  {
    xmlFile << "<root></root>" << std::endl;
    read_xml(filename, pt, boost::property_tree::xml_parser::trim_whitespace);
  }


  ptree & rootNode = pt.get_child("root");
  ptree resultSetNode;
  resultSetNode.add("<xmlattr>.result_number", 0);
  rootNode.add_child("result_set", resultSetNode);
  write_xml(filename, pt, std::locale(), w);

}

void save1(std::string filename)
{
  ptree pt;
  xml_writer_settings<char> w('\t', 1);
  read_xml(filename, pt, boost::property_tree::xml_parser::trim_whitespace);

  ptree &resultSetNode = pt.get_child("root.result_set");
  ptree resultNode;
  resultNode.put("tolerance", 100);
  resultSetNode.add_child("result", resultNode);

  write_xml(filename, pt, std::locale(), w);

}

int main()
{
  initialise("sample.xml");

  for(int i = 0; i < 2; ++i)
  {
    save1("sample.xml");
  }
  std::cout << "Success!!!\n";
  return 0;
}
War es hilfreich?

Lösung

This is a copy/paste of my reply on the boost mailing list:

I think you are misunderstanding the whole thing here.

You have a lot of nodes whose xpath is root/result_set, but all of them has an attribute that identifies them: result_number.

When you call get_child you are getting an arbitrary node (from boost documentation):

self_type & get_child(const path_type & path) ;

Get the child at the given path, or throw ptree_bad_path.

Notes:
Depending on the path, the result at each level may not be completely determinate, i.e. if the same key appears multiple times, which child is chosen is not specified. This can lead to the path not being resolved even though there is a descendant with this path.
Example:

  a -> b -> c
    -> b

The path "a.b.c" will succeed if the resolution of "b" chooses the first such node, but fail if it chooses the second.

I guess you should use iterators on root to find the last executed set and then get a reference to that node and then add the results to it:

   from begin() to end(), find the max result_number or 
   just the one that matches count()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top