Overview
Ember's parser system handles reading and writing behavior tree XML files. Built on libxml2, it provides robust parsing with extensive configuration options to support different XML formats.
Core Classes
LibXMLBehaviorTreeParser
The main parser class for reading XML files into behavior trees.
auto result = parser.ParseFile("behavior_tree.xml");
if (result.success) {
auto tree = result.tree;
} else {
for (const auto& error : result.errors) {
std::cerr << error.message << std::endl;
}
}
Thread-safe XML parser using libxml2 for behavior tree files.
Key Methods
| Method | Description |
| ParseFile(path) | Parse a single XML file |
| ParseFromString(xml) | Parse XML from string |
| ParseMultipleFiles(paths) | Parse multiple files as project |
| SetConfig(config) | Set parser configuration |
| SetProgressCallback(cb) | Set progress reporting callback |
LibXMLBehaviorTreeSerializer
Serializes behavior trees back to XML format.
XML serializer using libxml2 for behavior tree files.
bool SerializeToFile(std::shared_ptr< BehaviorTree > tree, const EmberCore::String &filepath)
Serialize behavior tree to file.
Features
- Preserves comments and formatting
- Maintains attribute order
- Supports custom indentation
- Round-trip safe (parse → serialize → parse yields same tree)
Parser Configuration
ParserConfig
ParserConfig controls parsing behavior with extensive options.
config.root_element_name = "root";
config.tree_element_name = "BehaviorTree";
config.tree_id_attribute = "ID";
config.blackboard_element_name = "Blackboard";
config.blackboard_entry_element = "Entry";
config.preserve_whitespace = true;
config.validate_structure = true;
config.allow_unknown_nodes = false;
Configuration for XML parser behavior and element/attribute mappings.
Configuration Categories
| Category | Settings |
| Element Names | Root, tree, node element names |
| Attributes | ID, name, type attribute names |
| Blackboard | Blackboard and entry element names |
| Validation | Structure validation, unknown node handling |
| Formatting | Whitespace, comment preservation |
ParserProfile
ParserProfile wraps a ParserConfig with metadata for preset management.
profile.
SetName(
"BehaviorTree.CPP v4");
A named parser configuration profile with metadata.
void SetName(const String &name)
void SetConfig(const ParserConfig &config)
void SetDescription(const String &description)
bool SaveToFile(const String &filepath) const
Built-in Profiles
| Profile | Description |
| Default | BehaviorTree.CPP v4 format |
| Generic | Flexible format for custom schemas |
| Legacy | BehaviorTree.CPP v3 compatibility |
ConfigManager
Singleton managing parser profiles.
auto names = manager.GetProfileNames();
auto profile = manager.GetProfile("Default");
manager.AddProfile(myProfile);
manager.SaveProfiles();
static ConfigManager & GetInstance()
Multi-File Projects
BehaviorTreeProject
Manages multiple XML files as a cohesive project.
project.AddFile("main.xml");
project.AddFile("subtrees/combat.xml");
project.AddFile("subtrees/navigation.xml");
project.SetMainTree("main.xml", "MainBehavior");
auto report = project.Validate();
if (!report.is_valid) {
for (const auto& issue : report.issues) {
std::cerr << issue.message << std::endl;
}
}
Represents a BehaviorTree project containing multiple XML resources.
Project Features
- Cross-file SubTree references: Reference trees in other files
- Shared blackboards: Define blackboards accessible across files
- Dependency tracking: Automatic detection of file dependencies
- Validation: Check for missing references, circular dependencies
ProjectManager
Singleton for managing the active project.
pm.CreateProject("MyProject", "/path/to/project");
pm.OpenProject("/path/to/project.emberproj");
pm.SaveProject();
if (pm.HasActiveProject()) {
auto path = pm.GetActiveProjectPath();
}
static ProjectManager & GetInstance()
Parse Results
ParseResult
Result structure from parsing operations.
struct ParseResult {
bool success;
std::shared_ptr<BehaviorTree> tree;
std::vector<ParseError> errors;
std::vector<ParseError> warnings;
std::string file_path;
double parse_time_ms;
};
ParseError
Error information from parsing.
struct ParseError {
std::string message;
std::string file;
int line;
int column;
ErrorSeverity severity;
};
Progress Reporting
For large files or multi-file projects, implement IParseProgressCallback:
public:
bool OnProgress(
float progress,
const std::string& message)
override {
std::cout << (int)(progress * 100) << "% - " << message << std::endl;
return true;
}
};
MyProgressCallback callback;
Callback interface for reporting parsing progress.
virtual bool OnProgress(const String &message, int current, int total)=0
Called to report progress during parsing.
void SetProgressCallback(IParseProgressCallback *callback)
XML Format Details
Standard Structure
<?xml version="1.0" encoding="UTF-8"?>
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<Sequence>
<Action ID="SomeAction"/>
</Sequence>
</BehaviorTree>
<TreeNodesModel>
<Action ID="SomeAction">
<input_port name="param" type="string"/>
</Action>
</TreeNodesModel>
</root>
Blackboard Definitions
<root BTCPP_format="4">
<Blackboard>
<Entry key="target" type="Position" access="read_write"/>
<Entry key="health" type="int" default="100"/>
</Blackboard>
<BehaviorTree ID="MainTree">
</BehaviorTree>
</root>
SubTree References
<BehaviorTree ID="MainTree">
<Sequence>
<SubTree ID="CombatTree"/>
<SubTree ID="subtrees/patrol.xml::PatrolTree"/>
</Sequence>
</BehaviorTree>
Error Handling
Common Parse Errors
| Error | Cause | Solution |
| Missing root element | No <root> tag | Add root element |
| Unknown node type | Unregistered node | Add to TreeNodesModel or enable unknown nodes |
| SubTree not found | Missing referenced tree | Add tree or fix reference |
| Circular dependency | SubTree loop | Break the cycle |
| Invalid blackboard type | Type mismatch | Fix type declaration |
Handling Errors
auto result = parser.ParseFile("file.xml");
if (!result.success) {
for (const auto& error : result.errors) {
switch (error.severity) {
case ErrorSeverity::Error:
break;
case ErrorSeverity::Warning:
break;
}
}
}
#define LOG_ERROR(category, message)
#define LOG_WARNING(category, message)
See Also