@@ -139,7 +139,7 @@ struct XmlDataParser
139139 if (!attributes.empty () || !children.empty ())
140140 {
141141 // Handle arrays for multiple same-tag children / attributes
142- std::unordered_map <std::string, DataTree> obj;
142+ std::map <std::string, DataTree> obj;
143143 std::unordered_map<std::string, std::vector<DataTree>> child_groups;
144144
145145 for (const auto & [child_tag, child_value] : children)
@@ -480,19 +480,10 @@ struct XmlDataSerializer
480480 {
481481 const auto & obj = value.as <DataTree::Object>();
482482
483- // Sort keys for consistent output
484- std::vector<DataTree::Object::key_type> keys;
485- std::transform (obj.begin (), obj.end (), std::back_inserter (keys),
486- [](const auto & pair) { return pair.first ; });
487- std::sort (keys.begin (), keys.end ());
488-
489483 // Opening tag with attributes
490484 output_ << indent_str << opening_tag;
491- for (size_t i = 0 ; i < keys. size (); ++i )
485+ for (const auto & [key, val] : obj )
492486 {
493- const auto & key = keys[i];
494- const auto & val = obj.at (key);
495-
496487 if (key.rfind (" @" , 0 ) == 0 )
497488 {
498489 // Attribute
@@ -512,11 +503,8 @@ struct XmlDataSerializer
512503 output_ << newline;
513504
514505 // Child elements and text content
515- for (size_t i = 0 ; i < keys. size (); ++i )
506+ for (const auto & [key, val] : obj )
516507 {
517- const auto & key = keys[i];
518- const auto & val = obj.at (key);
519-
520508 // Skip already handled attributes and text content handled later
521509 if (key.rfind (" @" , 0 ) == 0 || key == " #text" )
522510 continue ;
0 commit comments