Jump to content


Photo

Simplxml 1.0.2 Xml Parser


  • Please log in to reply
28 replies to this topic

#1 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 17 September 2006 - 07:38 PM

SimplXML
Version 1.0.2, by Ghostkeeper

SimplXML is an XML (eXtensible Markup Language) Parser for Game Maker (registered) completely within 24kb of GML code. It reads an XML file and puts it in a tree-like structure, making it easy to use for the average programmer.
I created this set of scripts to let game makers be able to use the oh-so-handy XML files in their games and applications. I noticed there was a reasonably large demand, but only one tryout about 1,5 years ago.
Meanwhile, I've gotten some competition! If you're having trouble with this XML parser, take a look at this script by Major Victory. It's more line based than SimplXML, it uses the SAX method in stead of the DOM method to read it.
Coding this baby wasn't easy. It took me a full 2 weeks coding just 1 script (the loading script obviously). Yet still, not all functions of XML as stated by w3c are implented (non-declaring parameters, language identification, element type declarations and parsed entities, document type declaration, I didn't think it would be used much / easy enough to program). The functions that are supported and a full documentation of all supported rules is in the readme file.

In the zip file is an example of how to extract information, as well as information on how to use SimplXML and what structure is the supported one.

xml_findvalue() is made by Carlos Ramos, I am grateful to him to make me that script, and you should be too! ^_^

Download: (15kb, zipped, version 1.0.2)
ghostkeeper.nl

Version History:
SimplXML 1.0.2 - Updated Carlos Ramos' xml_findvalue() script, he just posted an update. Thanks, mate!SimplXML 1.0.1 - Fixed a small problem with xml_findvalue() and xml_findposition() that would give an error. - Added the .gme file (GM7's beta extension file) to the pack. This will be removed when GM7 goes to alpha mode.SimplXML 1.0.0 - Got enough reactions and did enough tests to release the project in alpha. - Implented 3 new scripts: xml_findvalue(), xml_findposition() and xml_close().SimplXML 0.3.3 - Implented <![cdata[ ... ]]> tag support. - Made the code check for if the file exists before trying to read it.SimplXML 0.3.2 - Bug fixed where a filtered entity gets placed at the wrong position.SimplXML 0.3.1 - Bug fixed where a space at the end of a line caused the program to freeze.SimplXML 0.3.0 - Initial release. 0.1.0 and 0.2.0 were tryouts but failed. Eventually on the third complete redo I succeed.

Have fun with it! :huh:

Edited by Ghostkeeper, 04 February 2007 - 10:27 AM.

  • 0

#2 takua108

takua108

    GMC Member

  • GMC Member
  • 582 posts

Posted 20 September 2006 - 03:15 AM

Wow. That's pretty awesome. I'm still looking into its functionality, but it looks good to me so far. I just wanna parse a configuration file into my game, and this looks like it'll do the trick.

I'll check back in once I've worked further with this. Again, this look sweet so far!
  • 0

#3 Killamancer

Killamancer

    GMC Member

  • GMC Member
  • 116 posts

Posted 20 September 2006 - 04:13 AM

what is xml and parse?
  • 0

#4 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 20 September 2006 - 01:14 PM

what is xml

XML is a language that is used to store data. It's often used by professional programs too. Take a look at the example .xml file I included with the download.

and parse?

To parse XML is letting a program read it (as far as I understood, English is not my native language).

I'll look into some more examples, like how to actually make a game with this (the current example only reads it and shows the contents in a tree-form).
Uses for XML are (among others):
- News pages (RSS feeds)
- Configuration files.
- Databases.
- File system.
- Menu structure.
- Even an HTML browser! (hard, but this is the first step)

Edited by Ghostkeeper, 20 October 2006 - 01:48 PM.

  • 0

#5 takua108

takua108

    GMC Member

  • GMC Member
  • 582 posts

Posted 20 September 2006 - 09:12 PM

It doesn't look at DTD at all, does it? I just figured out how to use DTD today and it would be nice (but not necessary at all) if it could validate the XML document using DTD.

And this was posted at school, so again, I'll verify that everything works once I get home. I'm sure it will ^^

EDIT: Okay...I'm stumped. My XML file looks like this:
[codebox]<!-- ============================================= -->
<!-- = The TOPDOWN Engine Configuration XML File = -->
<!-- ============================================= -->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE configuration SYSTEM "config.dtd">

<configuration>
<graphics>
<config name="resolution_w" value="1024" />
<config name="resolution_h" value="768" />
<config name="vsync" value="0" />
</graphics>

<performance>

<config name="water_reflect_objects" value="0" />
<config name="water_reflect_sky" value="0" />
<config name="shells" value="0" />
<config name="particles" value="0" />
</performance>

<violence>
<config name="blood_cloud" value="0" />
<config name="blood_splatter" value="0" />

<config name="blood_stay" value="0" />
<config name="gibs" value="0" />
<config name="gibs_spray" value="0" />
</violence>

<player>
<config name="name" value="takua108" />
<config name="color_primary" value="000000" />
<config name="color_secondary" value="FFFFFF" />

</player>

<statistics>
<config name="enabled" value="0" />
</statistics>

<messenger>
<config name="enabled" value="0" />
<config name="status_text" value="music" />
</messenger>

<autoupdate>
<config name="enabled" value="0" />
<config name="remind_check" value="0" />
<config name="remind_new" value="0" />
</autoupdate>

</configuration>[/codebox]
How do I read the attributes of each "<config />," filtered by their parent tag (i.e. configuration, performance, violence, etc.)?

Thanks a million, though; the XML was parsed perfectly!

Edited by takua108, 21 September 2006 - 02:55 AM.

  • 0

#6 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 24 September 2006 - 09:42 AM

Okay...I'm stumped. My XML file looks like this:

<!--            =============================================            --><!--            = The TOPDOWN Engine Configuration XML File =            --><!--            =============================================            --><?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE configuration SYSTEM "config.dtd"><configuration>    <graphics>        <config name="resolution_w" value="1024" />        <config name="resolution_h" value="768" />        <config name="vsync" value="0" />    </graphics>    <performance>        <config name="water_reflect_objects" value="0" />        <config name="water_reflect_sky" value="0" />        <config name="shells" value="0" />        <config name="particles" value="0" />    </performance>    <violence>        <config name="blood_cloud" value="0" />        <config name="blood_splatter" value="0" />        <config name="blood_stay" value="0" />        <config name="gibs" value="0" />        <config name="gibs_spray" value="0" />    </violence>    <player>        <config name="name" value="takua108" />        <config name="color_primary" value="000000" />        <config name="color_secondary" value="FFFFFF" />    </player>    <statistics>        <config name="enabled" value="0" />    </statistics>    <messenger>        <config name="enabled" value="0" />        <config name="status_text" value="music" />    </messenger>    <autoupdate>        <config name="enabled" value="0" />        <config name="remind_check" value="0" />        <config name="remind_new" value="0" />    </autoupdate></configuration>
How do I read the attributes of each "<config />," filtered by their parent tag (i.e. configuration, performance, violence, etc.)?

<{POST_SNAPBACK}>

I created this script for you:
xmlfile = xml_open(working_directory+"/YourFile.xml");currentgroup = 0;grouplevel = 0;currentoption = 0;i = 0;repeat(xml_getlength(xmlfile))    {    switch(xml_getvalue(xmlfile,i))        {        case "graphics":            {            currentgroup = 1;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        case "performance":            {            currentgroup = 2;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        case "violence":            {            currentgroup = 3;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        case "player":            {            currentgroup = 4;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        case "statistics":            {            currentgroup = 5;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        case "messenger":            {            currentgroup = 6;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        case "autoupdate":            {            currentgroup = 7;            grouplevel = xml_getlevel(xmlfile,i);            j = 0;            break;            };        default:            {            if(xml_getlevel(xmlfile,i) == grouplevel+3)                {                switch(xml_getvalue(xmlfile,i))                    {                    case "resolution_w": global.resolution_w = real(xml_getvalue(xmlfile,i+2)); break;                    case "resolution_h": global.resolution_h = real(xml_getvalue(xmlfile,i+2)); break;                    case "vsync": global.vsync = real(xml_getvalue(xmlfile,i+2)); break;                    case "water_reflect_objects": global.water_reflect_objects = real(xml_getvalue(xmlfile,i+2)); break;                    case "water_reflect_sky": global.water_reflect_sky = real(xml_getvalue(xmlfile,i+2)); break;                    case "shells": global.shells = real(xml_getvalue(xmlfile,i+2)); break;                    case "particles": global.particles = real(xml_getvalue(xmlfile,i+2)); break;                    case "blood_cloud": global.blood_cloud = real(xml_getvalue(xmlfile,i+2)); break;                    case "blood_splatter": global.blood_splatter = real(xml_getvalue(xmlfile,i+2)); break;                    case "blood_stay": global.blood_stay = real(xml_getvalue(xmlfile,i+2)); break;                    case "gibs": global.gibs = real(xml_getvalue(xmlfile,i+2)); break;                    case "gibs_spray": global.gibs_spray = real(xml_getvalue(xmlfile,i+2)); break;                    case "name": global.name = xml_getvalue(xmlfile,i+2); break;                    case "color_primary": global.color_primary = xml_getvalue(xmlfile,i+2); break;                    case "color_secondary": global.color_secondary = xml_getvalue(xmlfile,i+2); break;                    case "status_text": global.status_text = xml_getvalue(xmlfile,i+2); break;                    case "remind_check": global.remind_check = real(xml_getvalue(xmlfile,i+2)); break;                    case "remind_new": global.remind_new = real(xml_getvalue(xmlfile,i+2)); break;                    case "enabled":                        {                        if(currentgroup == 5){global.statistics_enabled = real(xml_getvalue(xmlfile,i+2));};                        if(currentgroup == 6){global.messenger_enabled = real(xml_getvalue(xmlfile,i+2));};                        if(currentgroup == 7){global.autoupdate_enabled = real(xml_getvalue(xmlfile,i+2));};                        };                    };                };            };        };    i += 1;    };
Be sure to update your filename. Working with this kind of data is hard and you shouldn't be shy to use long code with many switch and if statements. I'd also be glad to help people on their interpretation of XML files like Takua108's. By the way, Takua, I checked out your W.I.P. topic in your signature, looks promising :D.

And no, it doesn't look at the DTD at all. Main reason: I don't understand it myself! Could you give me some explaination? I've taken a look at it at the w3c page I found (the page in the first post), and it seems quite hard to program too, next to the entities. Another reason: After you said about the DTD, I scanned my C: drive for XML files. I picked several out, but none of them had a <!DOCTYPE> tag.

Last thing: I updated to SimplXML 0.3.2, with another bug filtered. I'll add a version history to the first post.
  • 0

#7 takua108

takua108

    GMC Member

  • GMC Member
  • 582 posts

Posted 01 October 2006 - 10:34 PM

Wow. I didn't check this topic for awhile, and I was surprised to see that you responded with a fully-functional script. Looking at your code, I understand how your system works now.

Thanks a billion for this system and that script, they're lifesavers! ::lmao::
  • 0

#8 the_mysterious_gamer

the_mysterious_gamer

    GMC Member

  • New Member
  • 431 posts

Posted 22 November 2006 - 07:16 PM

This is great, I could see this in use as an alternative for INIs. But as a parser/compiler freak, I do have to tell you something: its coded terribly. Your entire parser is contained in one script, I cannot see any error handling functions and it isnt structured... at all! PM me and I could help you with this.
  • 0

#9 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 22 November 2006 - 07:31 PM

Haha thanks for reanimating my topic!

The terrible coding is because things went wrong all time. Somewhere half way I realized that the string_copy() function returns a string shifted than I thought. I often just tested it, and modified the function (implented +1 or -1 or +2 or something) to make it work right. Also, when testing, sometimes string_copy() returned an empty string, and I used string_delete() in stead which worked right most of the time.
I know now I was just using it wrong probably. However, the code is quite complicated and I don't feel to dig in it again to make it more consistent.

About the entire parser being in one script, I think that's the best way to be, it takes less memory and is easier to overview. There is however (you probably noticed it) a frequent call to the xml_filter() script. This is the only one that I used so often that I found it handy to make a seperate script.

I removed all comment before I published it. If you look carefully though, you can see that there are still empty lines between every action that is performed.

I've learnt very much about string handling functions in GM while coding this. During the code, my coding has adapted and improved. That's why it's so messy.

And nope, there are no error handling functions in there. Thank you for the request though.
  • 0

#10 the_mysterious_gamer

the_mysterious_gamer

    GMC Member

  • New Member
  • 431 posts

Posted 22 November 2006 - 07:53 PM

You may think its easier now to keep it in an unstructured way, but I bet you could half, if not quarter (I can make a parser for GML in 300 lines), the lines of code, by making it in a top down structured way. In the long run it will be easier, to look at, and to add to. If you first write some E/BNF of it and create a function for every rule updating will just come naturally, and little to no editting is needed for new features.

EDIT

Haha thanks for reanimating my topic!


I never quite understood that comment until I read the dates...

Edited by the_mysterious_gamer, 22 November 2006 - 08:02 PM.

  • 0

#11 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 22 November 2006 - 09:16 PM

I just posted an update.
I'm sorry to be so slow. This is not due to the messy code :rolleyes: The election results of our government are on TV and I'm following it.
  • 0

#12 Carlos_Ramos

Carlos_Ramos

    GMC Member

  • New Member
  • 42 posts

Posted 14 December 2006 - 12:34 AM

I know it's almost been a month, but thanks for these scripts :huh:
This is a clever way to store the XML info, I would never have figured this out.

[EDIT]
I'm writing an add-on script to search for the value of a specific tag via the tags name to help you out

Edited by Carlos_Ramos, 14 December 2006 - 02:40 AM.

  • 0

#13 Jugado

Jugado

    GMC Member

  • New Member
  • 38 posts

Posted 14 December 2006 - 01:32 AM

Keep working Ghostkeeper. Nice job!!!
It would be nice to see in a future GM working with a XML database, for example this one: dbxml
  • 0

#14 Carlos_Ramos

Carlos_Ramos

    GMC Member

  • New Member
  • 42 posts

Posted 14 December 2006 - 02:48 AM

Ok, here's a script to find the value of a tag. (You'll need to create and rename a script, then copy the following code into it)

////xml_findvalue//////////////////////////////////////////////////
// This function finds the value of specific tag based on its name
//
// (argument0: (real) ID of the XML file, as returned by xml_open()
// (argument1: (string) tag name
// (argument2: (real) place to start looking
// return: (string) The value of the tag
// return: -1 if no value found
///////////////////////////////////////////Carlos Ramos////////////

//Search through the entire file
repeat(xml_getlength(argument0))
{
    value = xml_getvalue(argument0,argument2);  //Grabs the value at location i

    //Checks if the next positions layer is greater than this one, if so, then return the value
    if(string(value) == string(argument1) && xml_getlevel(argument0, argument2+1) > xml_getlevel(argument0, argument2))
    {
        return xml_getvalue(argument0,argument2+1); //Return the string
    }

    argument2+=1;   //Next position
}

return -1;  //No values found, end function

The way it works is by checking the current level, and returning the value that is one level less.

Next, I'll make it so you can enter in a tags pathname, for more specific searches.
  • 0

#15 Carlos_Ramos

Carlos_Ramos

    GMC Member

  • New Member
  • 42 posts

Posted 14 December 2006 - 03:33 AM

Ok, I've got it. Replace the last script with this one, this script works with both pathnames, and single tag names:

//////////////////////////xml_findvalue////////////////////////////////
// This function looks for the value of a tag at with a specific pathname
//
// (argument0: (real) ID of the XML file, as returned by xml_open()
// (argument1: (string) tag url
// (argument2: (real) place to start looking
// return: (string) The value of the tag
// return: -1 if no value found
/////////////////////////////////////////////////////Carlos Ramos/////////

//Setup Variables
num = 0;    //Number of strings
str[0] = argument1; //Stores the individual sections of a string, index 0 = the string containin '/'
parent_level = 0; //The parents level
cur_tag = 0;    //The current tag we are searching for

//Split up the url into separate strings
for(i = 1; i <= string_count("\",str[0]); i += 1)
{
    str[i] = string_copy(str[0],0,string_pos("\",str[0]));   //Grab a section
    str[0] = string_copy(str[0],string_pos("\",str[0])+1,string_length(str[0])-1); //Remove the grabbed section from the url string
    i-=1;   //Because we took one out, we need to decrease the current i
}

//Search through the entire file
repeat(xml_getlength(argument0))
{
    value = xml_getvalue(argument0,argument2);  //Grabs the value at location i

    if(cur_tag >= num){cur_tag = 0;}    //str[0] actually contains the last tag, so look for this last
    
    //show_message(str[cur_tag] + " :: " + value);
    //If we find the wanted tag, store it's info
    if(str[cur_tag] == value)
    {
        parent_level = xml_getlevel(argument0,argument2);   //Store this level
        
        //No longer searching here, so clear the parent variables    
        if(xml_getlevel(argument0,argument2+1) <= parent_level){parent_level = 0; cur_tag = 1;}

        if(cur_tag == 0){return xml_getvalue(argument0,argument2+1);}   //Return the value
        cur_tag += 1;
    }

    //No longer searching here, so clear the parent variables    
    if(xml_getlevel(argument0,argument2) <= parent_level){parent_level = 0; cur_tag = 1;}
    
    argument2+=1;   //Next position
}

return -1;  //No values found, end function

This function allows you to search for the value of a tag's pathname. Lets take the following:
<a>
   <b>
   <e>
         <d>  </d></e>
   <f>
      <c>
         <d> Hello World </d></f></c></b></a>
To extract "Hello World", you would look for the tag named d. However, the first d contains no useful information. So, to extract the d we need, we use
xml_findvalue(xml_file, "a\f\d");

Hope this helps out.
  • 0

#16 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 15 December 2006 - 06:08 PM

Sure does!

I've completed version 1.0.0 and I've included (a slightly modified version of) your script in this, Carlos.

Also, be sure to check out the new function to get the position of an item with a certain path.
  • 0

#17 Ansgar

Ansgar

    OM Studios

  • New Member
  • 333 posts

Posted 15 December 2006 - 07:20 PM

This might be quite handy. I hope I'll find a use for it.
One little glitchie: The readme file still says it's version 0.3.1 :)

Cheers
-Ansgar aka Zombone-

EDIT: It's fixed now. Thumbs up.

Edited by Ansgar, 16 December 2006 - 11:11 AM.

  • 0

#18 Ankerheegaard

Ankerheegaard

    GMC Member

  • New Member
  • 6 posts

Posted 03 January 2007 - 07:43 AM

Hi there,

Looks like a great way to extend Game Maker, but I have this simple XML file like this;

<?xml version="1.0" encoding="ANSI" standalone="no"?>
    <Areas>	
	<Area ID="1" Object="100068" Name="Fiona" Country="Denmark" />
	<Area ID="2" Object="100070" Name="Holstein" Country="Denmark" />
   </Areas>

Ill try to extract the values by ID but I keep getting only the first value "Fiona" when i use the following code;
area_name=xml_findvalue(XML_FILE_NAME,"Areas\ID\2\Name");
What am I doing wrong?

Thank you in advance.
  • 0

#19 tangibleLime

tangibleLime

    Lunatic

  • Retired Staff
  • 2520 posts
  • Version:GM:HTML5

Posted 03 January 2007 - 11:34 AM

You forgot my script set (based off of databot's): http://www.technosof...ipts/GM-XML.zip
  • 0

#20 Ankerheegaard

Ankerheegaard

    GMC Member

  • New Member
  • 6 posts

Posted 03 January 2007 - 12:18 PM

You forgot my script set (based off of databot's): http://www.technosof...ipts/GM-XML.zip

<{POST_SNAPBACK}>

Thank you for your quick reply, but I think I got the same problem with your scripts. I still only get the first area (Fiona).
  • 0

#21 Ghostkeeper

Ghostkeeper

    That's Logic

  • New Member
  • 189 posts

Posted 08 January 2007 - 05:09 PM

Sorry for the slow reply. I was on a winter holliday to swiss. :(
As for your data, you are reading it all wrong. This code
area_name=xml_findvalue(XML_FILE_NAME,"Areas\ID\2\Name");
will look for the (root) map 'Areas', then search for 'ID', which it won't find in the root map (it's in the submap 'Area'), then look for '2', then 'Name'. What it SHOULD do, is look for the (root) map 'Areas', then search for 'Area', then for 'ID', and it's value. Then with the value stored, go back to the submap 'Area', and look for 'Name'. Then all that's left to do is store the Name with the appropriate ID.
Sounds complicated huh?

I hope this code will explain it to you:
pos = 0;
while(pos != -1)
    {
    ID = real(xml_findvalue(XML_FILE_NAME,"Areas/Area/ID",pos));
    Name = xml_findvalue(XML_FILE_NAME,"Areas/Area/Name",pos);
    area_names[ID] = Name;
    pos = xml_findposition(XML_FILE_NAME,"Areas/Area",pos);
    if(pos != -1)
        {
        pos += 9; //Skip to the next area. (every area has 9 items in your example, the map 'Area', four submaps and four items, one in each submap)
        };
    };
show_message("Name no. 1 is '"+area_names[1]+"'.#Name no. 2 is '"+area_names[2]+"'.");
While writing this piece of code to Ankerheegaard, I noticed that the two xml_find scripts threw an error because it compared a real value with a string sometimes. I fixed it in version 1.0.1. As for you, Ankerheegard, you don't have to download and implent it again, just place the string() function around the two values that are compared in the rules that throw an error.

Edited by Ghostkeeper, 08 January 2007 - 05:20 PM.

  • 0

#22 Carlos_Ramos

Carlos_Ramos

    GMC Member

  • New Member
  • 42 posts

Posted 01 February 2007 - 03:22 AM

I know it's late in the game, but I've updated the xml_findvalue() code. I think I might have messed up earlier, and certain elements could not be read. This script now fully loads a any element at any address, granted that the node exists. I also commented the code a little better.

Just copy and paste into the old xml_findvalue script.



//////xml_findvalue//////////////////////////////////////////////////////////
//This function looks for a tag with a specific pathname and returns the   //
//first value within that tag.                                             //
//                                                                         //
//argument0: (real) ID of the XML file, as returned by xml_open().         //
//argument1: (string) Path of the tag to look for, submaps seperated by '/'//
//    or by '\', and including the root map, but not the final slash.      //
//argument2: (real) The place to start looking, the first matching tag is  //
//    returned.                                                            //
//return: (string) The first value within the tag with the given path. A   //
//    (real) value -1 is returned if the path could not be found.          //
///////////////////////////////////////////////////////////Carlos Ramos//////

//Setup Variables
argument1 = string_replace(argument1,"/","\");  //Replace all / with \ in the original address
address[0] = argument1; //Stores each element in the address into its own variable (index 0 stores the original address)
element_num = 0;    //Number of address elements
cur_val = "";   //The value at the current location within the XML File
cur_element = 1;    //The address element we are looking for
cur_level = 0;  //The level of the last address element we found
last_good_position = 1; //Stores the position in the XML file of the last good element

//Divide the address into separate elements
for(i = 0; i<= string_count("\",argument1);i += 1)
{
    address[i+1] = string_copy(address[0],1,string_pos("\",address[0])-1);  //Copy all characters to the left of the first \
    if(address[i+1] == ""){address[i+1] = address[0];}  //If no '\' are found, then copy the rest of the string
    address[0] = string_copy(address[0],string_pos("\",address[0])+1,string_length(address[0]));   //Remove all characters to the left of the first \ in the address[0] variable...truncuate address[0]
    element_num += 1;   //Increment the Element Number variable
}

//Search through the entire file
repeat(xml_getlength(argument0))
{
    cur_value = xml_getvalue(argument0, argument2); //Get the value at the current location

    //Compare the current value with the current Address Element
    if(cur_value == address[cur_element])
    {
        //The level we are looking at is a grandchild, so we must start over
        if(xml_getlevel(argument0, argument2) > xml_getlevel(argument0,last_good_position)+1)
        {
            cur_level = 0;  //Clear the variable that tells us the location of a found element, because we no longer know
            cur_element = 1;    //Start from scratch
        }

        cur_level = xml_getlevel(argument0, argument2); //Remember this address elements level...when we goto a level that is lower (ie is either a parent of this element or not a family member) then stop looking through the children for the next element
        last_good_position = argument2; //Remember the position of this address element
        
        //If we are on the last address element, then we found what we were looking for!!!
        if(cur_element >= element_num){return xml_getvalue(argument0,argument2+1);} //Return this elements Child Value
        
        cur_element += 1;   //We found an element, time to start looking for the next one

        //If the next element is not a child, or is the EOF...then we must restart the search at the current position
        if((xml_getlevel(argument0,argument2+1) <= cur_level) || argument2+1 > xml_getlength(argument0))
        {
            cur_level = 0;  //Clear the variable that tells us the location of a found element, because we no longer know
            cur_element = 1;    //Start from scratch
        }
    }
    
    argument2 += 1; //Look at the next element
}
return -1;



So for example, taking a look at the following XML file:
<Lemmings>
  <Walk>
  	<Sprite>Sprites\Lemming_Walk_01.bmp</Sprite>
  	<Frames>8</Frames>
  	<Speed>0.5</Speed>
  	<X_Origin>4</X_Origin>
  	<Y_Origin>6</Y_Origin>
  </Walk>

  <Fall>
  	<Sprite>Sprites\Lemming_Fall_01.bmp</Sprite>
  	<Frames>4</Frames>
  	<Speed>.25</Speed>
  	<X_Origin>4</X_Origin>
  	<Y_Origin>6</Y_Origin>
  </Fall>

  <Splat>
  	<Sprite>Sprites\Lemming_Splat_01.bmp</Sprite>
  	<Frames>17</Frames>
  	<Speed>.25</Speed>
  	<X_Origin>10</X_Origin>
  	<Y_Origin>6</Y_Origin>
  </Splat>

  <Dig>
  	<Sprite>Sprites\Lemming_Dig_01.bmp</Sprite>
  	<Frames>8</Frames>
  	<Speed>.25</Speed>
  	<X_Origin>7</X_Origin>
  	<Y_Origin>8</Y_Origin>
  </Dig>
	</Lemmings>
You could easily grab the sprite filename for say, a Digging Lemming, by the following code :
xml_findvalue(XMLID, "Lemmings\Dig\Sprite");
or
xml_findvalue(XMLID, "Dig\Sprite");

Edited by Carlos_Ramos, 01 February 2007 - 03:22 AM.

  • 0

#23 Petah

Petah

    GMC Member

  • GMC Member
  • 72 posts

Posted 28 August 2007 - 12:22 PM

In this XML code:
<root>
	<child>1</child>
	<child>2</child>
	<child>3</child>
</root>
How do I return the data from that second and third child tags?

As far as I can tell its not working like it should, I have tried this:
xid = xml_open("test.xml")

pos = 0
show_message(string(pos) + ":" + xml_findvalue(xid,"root\child",pos))
pos = xml_findposition(xid,"root\child",pos)
show_message(string(pos) + ":" + xml_findvalue(xid,"root\child",pos))
pos = xml_findposition(xid,"root\child",pos)
show_message(string(pos) + ":" + xml_findvalue(xid,"root\child",pos))

xml_close(xid)
Which results in 0:1,1:1,-1:1.
  • 0

#24 dahandy

dahandy

    GMC Member

  • New Member
  • 29 posts

Posted 20 November 2007 - 07:18 PM

What about this XML file? It returns -1 when I search for anything that is is "name" -section.

<?xml version="1.0" encoding="utf-8"?>

<userconfig>
	<var name="Language" value=""/>
	<var name="Theme" value="Classic"/>
	<var name="DisplayWidth" value="1440"/>
	<var name="DisplayHeight" value="900"/>
	<var name="DisplayBPP" value="32"/>
	<var name="DisplayWindowed" value="false"/>
	<var name="MenuBackgroundGraphics" value="High"/>
	<var name="GameGraphics" value="High"/>
	<var name="DrawLib" value="OPENGL"/>
	<var name="AudioEnable" value="true"/>
	<var name="AudioSampleRate" value="22050"/>
	<var name="AudioSampleBits" value="16"/>
	<var name="AudioChannels" value="Mono"/>
	<var name="EngineSoundEnable" value="true"/>
	<var name="ControllerMode1" value="Keyboard"/>
	<var name="KeyDrive1" value="Up"/>
	<var name="KeyBrake1" value="Down"/>
	<var name="KeyFlipLeft1" value="Left"/>
	<var name="KeyFlipRight1" value="Right"/>
	<var name="KeyChangeDir1" value="Space"/>
	<var name="ControllerMode2" value="Keyboard"/>
	<var name="KeyDrive2" value="A"/>
	<var name="KeyBrake2" value="Q"/>
	<var name="KeyFlipLeft2" value="Z"/>
	<var name="KeyFlipRight2" value="E"/>
	<var name="KeyChangeDir2" value="W"/>
	<var name="ControllerMode3" value="Keyboard"/>
	<var name="KeyDrive3" value="R"/>
	<var name="KeyBrake3" value="F"/>
	<var name="KeyFlipLeft3" value="T"/>
	<var name="KeyFlipRight3" value="Y"/>
	<var name="KeyChangeDir3" value="V"/>
	<var name="ControllerMode4" value="Keyboard"/>
	<var name="KeyDrive4" value="Y"/>
	<var name="KeyBrake4" value="H"/>
	<var name="KeyFlipLeft4" value="U"/>
	<var name="KeyFlipRight4" value="I"/>
	<var name="KeyChangeDir4" value="N"/>
	<var name="AutosaveHighscoreReplays" value="true"/>
	<var name="JoyIdx1" value="0"/>
	<var name="JoyAxisPrim1" value="1"/>
	<var name="JoyAxisPrimMax1" value="32760"/>
	<var name="JoyAxisPrimMin1" value="-32760"/>
	<var name="JoyAxisPrimUL1" value="1024"/>
	<var name="JoyAxisPrimLL1" value="-1024"/>
	<var name="JoyAxisSec1" value="0"/>
	<var name="JoyAxisSecMax1" value="32760"/>
	<var name="JoyAxisSecMin1" value="-32760"/>
	<var name="JoyAxisSecUL1" value="1024"/>
	<var name="JoyAxisSecLL1" value="-1024"/>
	<var name="JoyButtonChangeDir1" value="0"/>
	<var name="DefaultProfile" value="DaHandy"/>
	<var name="ScreenshotFormat" value="png"/>
	<var name="NotifyAtInit" value="false"/>
	<var name="ShowMiniMap" value="true"/>
	<var name="ShowEngineCounter" value="false"/>
	<var name="StoreReplays" value="true"/>
	<var name="ReplayFrameRate" value="25"/>
	<var name="CompressReplays" value="true"/>
	<var name="ContextHelp" value="true"/>
	<var name="MenuMusic" value="true"/>
	<var name="InitZoom" value="true"/>
	<var name="DeathAnim" value="true"/>
	<var name="WebHighscores" value="true"/>
	<var name="CheckHighscoresAtStartup" value="true"/>
	<var name="CheckNewLevelsAtStartup" value="true"/>
	<var name="ShowInGameWorldRecord" value="false"/>
	<var name="WebConfAtInit" value="false"/>
	<var name="WebHighscoresURL" value="http://xmoto.tuxfamily.org/highscores.xml"/>
	<var name="WebLevelsURL" value="http://xmoto.tuxfamily.org/levels.xml"/>
	<var name="WebThemesURL" value="http://xmoto.tuxfamily.org/themes.xml"/>
	<var name="WebThemesURLBase" value="http://xmoto.tuxfamily.org/sprites"/>
	<var name="WebRoomsURL" value="http://xmoto.tuxfamily.org/rooms.xml"/>
	<var name="WebHighscoresIdRoom" value="1"/>
	<var name="ProxyType" value=""/>
	<var name="ProxyServer" value=""/>
	<var name="ProxyPort" value="-1"/>
	<var name="ProxyAuthUser" value=""/>
	<var name="ProxyAuthPwd" value=""/>
	<var name="WebHighscoreUploadURL" value="http://xmoto.tuxfamily.org/tools/UploadReplay.php"/>
	<var name="WebHighscoreUploadLogin" value=""/>
	<var name="WebHighscoreUploadPassword" value=""/>
	<var name="EnableGhost" value="true"/>
	<var name="GhostStrategy_MYBEST" value="true"/>
	<var name="GhostStrategy_THEBEST" value="true"/>
	<var name="GhostStrategy_BESTOFROOM" value="true"/>
	<var name="ShowGhostTimeDiff" value="true"/>
	<var name="DisplayGhostInfo" value="true"/>
	<var name="HideGhosts" value="false"/>
	<var name="GhostMotionBlur" value="false"/>
	<var name="QSQualityMIN" value="1"/>
	<var name="QSDifficultyMIN" value="1"/>
	<var name="QSQualityMAX" value="5"/>
	<var name="QSDifficultyMAX" value="1"/>
	<var name="MultiStopWhenOneFinishes" value="true"/>
</userconfig>

Edited by dahandy, 20 November 2007 - 07:19 PM.

  • 0

#25 kiujhytg2

kiujhytg2

    GMC Member

  • New Member
  • 2 posts

Posted 02 November 2009 - 04:04 PM

[quote name='Petah' post='2303857' date='Aug 28 2007, 01:25 PM']In this XML code:
xid = xml_open(get_open_filename("XML files|*.xml",""))pos = xml_findposition(xid,"root\child",0)  //Find the position of the 1st tag called "child" in the tag "root"show_message(string(pos) + ":" + xml_findvalue(xid,"child",pos)) //Give the value of the 1st tag called "child". Note that the path is "child" not "root\child" because we are already inside the tag "root"pos = xml_findposition(xid,"child",pos+1) //Find the position of the next tag called "child". Again, we are already in "root" so we don't need to include it in the path. We start a pos+1 to avoid repeating tagsshow_message(string(pos) + ":" + xml_findvalue(xid,"child",pos)) //Give the value of the next tag called "child"pos = xml_findposition(xid,"child",pos+1) //And again, find the position of the next tag called "child"show_message(string(pos) + ":" + xml_findvalue(xid,"child",pos)) //And again, give the valuexml_close(xid)

Summary of changes:
The 1st value of pos is xml_findposition(xid,"root\child",0) not 0
xml_findvalue and xml_findposition (except the 1st xml_findposition) is given path "child" not "root\child"
xml_findposition is given start position pos+1 not pos

Hope this helps.
  • 0

#26 DefuzionGames

DefuzionGames

    GMC Member

  • GMC Member
  • 1426 posts
  • Version:Unknown

Posted 15 March 2012 - 02:04 PM

link is down
  • 0

#27 Fraot

Fraot

    GMC Member

  • GMC Member
  • 11 posts

Posted 09 May 2012 - 05:54 PM

Hey! A beautiful idea!

I want to use xml's in my game for ease of translation in the future, but for now, I want to easily edit all the texts in my game.

How to call a certain text structure?

Let's say I have this little code:
<dialogs>
    <bosses>
        <boss1>
             <d1>
              "Hey dude! Lol."
             </d1>
             <d2>
               "Hahahahah, you suck."
             </d2>
        </boss1>
    </bosses>
</dialogs>

I know I would use "dialogs/bosses/boss1/d1" for the first line. But how to call it in a draw_text<more stuff>();?
  • 0

#28 grugin

grugin

    GMC Member

  • GMC Member
  • 127 posts

Posted 08 June 2012 - 09:20 AM

I can confirm that the link is down. Someone can re-upload it please ?
  • 0

#29 thecrazygamemaster

thecrazygamemaster

    Devcodier

  • GMC Member
  • 785 posts
  • Version:GM:Studio

Posted 22 July 2012 - 08:08 AM

Hey! A beautiful idea!

I want to use xml's in my game for ease of translation in the future, but for now, I want to easily edit all the texts in my game.

How to call a certain text structure?

Let's say I have this little code:

<dialogs>
    <bosses>
        <boss1>
             <d1>
              "Hey dude! Lol."
             </d1>
             <d2>
               "Hahahahah, you suck."
             </d2>
        </boss1>
    </bosses>
</dialogs>

I know I would use "dialogs/bosses/boss1/d1" for the first line. But how to call it in a draw_text<more stuff>();?


Load each element into a separate variable and draw both variables separately using draw_text(x,y,variablename). Link is down, put it up!
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users