Last active
March 22, 2022 12:54
-
-
Save williammustaffa/f6b7e02a43f468d622eb3d7ae08a5324 to your computer and use it in GitHub Desktop.
Load XML file into game maker ds_map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Reads a XML file and converts its content into a ds_map | |
* | |
* Example output: | |
* | |
* <ds_map>{ | |
* type: "root", | |
* content: "", | |
* nodes: <ds_list>[ | |
* <ds_map>{ | |
* type: "tagname", | |
* content: "", | |
* nodes: <ds_list>[...] | |
* }, | |
* ... | |
* ] | |
* } | |
* | |
* @param {String} path xml path to read | |
* @returns {DS_MAP} ds_map representation of the xml | |
*/ | |
function load_xml(path) { | |
var file = file_text_open_read(working_directory + path); | |
// Create rootnode | |
var ds_root = ds_map_create(); | |
ds_map_set(ds_root, "type", "root"); | |
ds_map_set(ds_root, "content", ""); | |
ds_map_add_list(ds_root, "nodes", ds_list_create()); | |
// Modes: | |
// 0 = Not reading tag definitions | |
// 1 = Reading tag type name | |
// 2 = Waiting for tag attribute | |
// 3 = Reading tag attribute name | |
// 4 = Waiting for attribute value start | |
// 5 = Reading tag attribute value | |
var str_temp = ""; | |
var attr_temp = ""; | |
var closure = false; | |
var mode = 0; | |
var ds_node = ds_root; | |
while (!file_text_eof(file)) { | |
var str_line = file_text_readln(file); | |
//show_message(str_line); | |
for (var pos = 1; pos < string_length(str_line); pos++) { | |
var char = string_char_at(str_line, pos); | |
// Replace text newline to GMS compliant new line | |
if (char == "\r" or char == "\n") { | |
char = "#"; | |
} | |
switch(mode) { | |
// Reading content | |
case 0: | |
// If we find a new tag | |
if (char == "<") { | |
// Add node content | |
ds_map_set(ds_node, "content", ds_node[? "content"] + str_temp); | |
str_temp = ""; | |
if (string_char_at(str_line, pos + 1) == "/") { | |
closure = true; | |
pos++; | |
} | |
if (!closure) { | |
// If it's not closing the tag we create it | |
var ds_new_node = ds_map_create(); | |
ds_map_set(ds_new_node, "type", "undefined"); | |
ds_map_set(ds_new_node, "content", ""); | |
ds_map_set(ds_new_node, "parent", ds_node); | |
// Add linked lists | |
ds_map_add_list(ds_new_node, "nodes", ds_list_create()); | |
// Add to parent nodes list | |
var ds_node_list = ds_node[? "nodes"]; | |
ds_list_add(ds_node_list, ds_new_node); | |
// Link added list item to parent map for later cleanup | |
ds_list_mark_as_map(ds_node_list, ds_list_size(ds_node_list) - 1); | |
// Set current node as the new node as we are modifying it | |
ds_node = ds_new_node; | |
} | |
// Initiate tag name reading | |
mode = 1; | |
} else { | |
str_temp += char; | |
} | |
break; | |
// Reading tag name | |
case 1: | |
if (string_lettersdigits(char) != "") { | |
str_temp += char; | |
} else { | |
if (!closure) { | |
ds_map_set(ds_node, "type", str_temp); | |
} | |
str_temp = ""; | |
mode = 2; | |
} | |
break; | |
// Waiting to start reading tag attributes | |
case 2: | |
if (string_lettersdigits(char) != "") { | |
mode = 3 | |
} else { | |
// since we need to | |
break; | |
} | |
// Reading tag attribute name | |
case 3: | |
if (string_lettersdigits(char) != "") { | |
str_temp += char; | |
} else { | |
attr_temp = str_temp; | |
str_temp = ""; | |
// If we find the equal sign, means we are going to read the tag value | |
// mode 4 which will wait for value | |
// mode 2 for waiting for next attribute | |
mode = char == "=" ? 4 : 2; | |
}; | |
break; | |
// Wait to start reading tag attribute value | |
case 4: | |
if (char == "\"") { | |
mode = 5 | |
} else { | |
mode = 2; | |
}; | |
break; | |
// Reading attribute value | |
case 5: | |
if (char != "\"") { | |
str_temp += char; | |
} else { | |
ds_map_set(ds_node, attr_temp, str_temp); | |
attr_temp = ""; | |
str_temp = ""; | |
mode = 2; | |
} | |
break; | |
} | |
// If we are reading a tag and we find this character, it's a closure tag | |
if (mode != 0 and char == "/") closure = true; | |
if (char == ">") { | |
// if we are closing the tag we go to upper scope | |
if (closure) { | |
// If has no text then delete content | |
if (string_lettersdigits(ds_node[? "content"]) == "") { | |
ds_map_delete(ds_node, "content"); | |
} | |
ds_node = ds_node[? "parent"]; | |
closure = false; | |
} | |
// Reset tag | |
mode = 0; | |
} | |
} | |
} | |
return ds_root; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment