RapidXML解析动作映射XML出现异常,请求技术排查
Let's break down why your parsing code is producing inconsistent, mismatched results between action names and their rebind inputs—even though the loop structure looks correct at first glance.
Common Culprits & Fixes
1. Missing Error Checking (Biggest Suspect)
Your current code assumes every node and attribute exists without any validation. If your XML has even one missing name attribute on an <action> node, or a <rebind> without an input attribute, accessing ->value() directly will trigger undefined behavior—which manifests as random values, mismatched pairs, or crashes.
For example, if an <action> node lacks a name attribute, action_node->first_attribute("name") returns nullptr, and calling ->value() on that will read garbage memory, leading to "random" action names in your logs.
2. XML Structure Inconsistencies
Double-check your XML to ensure:
- All
<rebind>nodes are direct children of their parent<action>nodes (no accidental nesting under other nodes) - No
<actionmap>nodes are missing theirnameattribute - No duplicate node names are causing unexpected traversal jumps (e.g., an extra
<action>node outside the intended hierarchy)
3. File Reading Issues
Your code doesn't verify if the file was opened successfully, or if the buffer was populated correctly. If the file read fails, your buffer might be incomplete or empty, leading to malformed parsing and random results.
Fixed Code with Validation & Debugging
Here's an updated version of your code with strict error checking, which will catch missing nodes/attributes and prevent undefined behavior:
// Create XML document xml_document<> doc; xml_node<> * root_node; // Read the xml file into a vector ifstream theFile(fqn_file); if (!theFile.is_open()) { wxLogMessage("Failed to open file: %s", fqn_file.c_str()); return; } vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>()); buffer.push_back('\0'); theFile.close(); // Clean up file handle // Parse the buffer doc.parse<0>(&buffer[0]); root_node = doc.first_node("ActionMaps"); if (!root_node) { wxLogMessage("Root node <ActionMaps> not found!"); return; } // Iterate over 'ActionMaps' subtree for (xml_node<> * actionmap_node = root_node->first_node("actionmap"); actionmap_node; actionmap_node = actionmap_node->next_sibling()) { xml_attribute<> * amap_name_attr = actionmap_node->first_attribute("name"); if (!amap_name_attr) { wxLogMessage("Skipping actionmap node with no 'name' attribute"); continue; } wxLogMessage("Found actionmap subsection: %s", amap_name_attr->value()); // Iterate over 'action' subtree for(xml_node<> * action_node = actionmap_node->first_node("action"); action_node; action_node = action_node->next_sibling()) { xml_attribute<> * action_name_attr = action_node->first_attribute("name"); if (!action_name_attr) { wxLogMessage("Skipping action node with no 'name' attribute"); continue; } const char* action_name = action_name_attr->value(); wxLogMessage("Found action: %s", action_name); // Iterate over 'rebind' subtree for(xml_node<> * rebind_node = action_node->first_node("rebind"); rebind_node; rebind_node = rebind_node->next_sibling()) { xml_attribute<> * rebind_input_attr = rebind_node->first_attribute("input"); if (!rebind_input_attr) { wxLogMessage("Skipping rebind node for action '%s' with no 'input' attribute", action_name); continue; } wxLogMessage("Action '%s' has rebind input: %s", action_name, rebind_input_attr->value()); } } }
Additional Debugging Steps
- Print the raw XML buffer to confirm you're parsing the exact file content you expect (e.g., no truncation or encoding issues)
- Add debug logs for node counts (e.g., count how many
<action>nodes are in each<actionmap>) to verify the traversal is hitting all nodes - Validate your XML with a schema or linter to catch structural errors that might be confusing RapidXML
内容的提问来源于stack exchange,提问作者AlbinoBlacksheep

