YSI:XML

From SA-MP Wiki

Jump to: navigation, search

Introduction

The YSI XML system is similar to the INI system in that it uses custom callbacks to load the data, however far more data can be loaded at once through a single callback. Sub tags can also have their own callbacks.

To parse an XML file you first need to define a set of "rules" which dictate how the file should be parsed and then load a file using those rules.

Example

Consider the following XML file:

<object name="bin">
  <model>1337</model>
  <x>10.0</x>
  <y>20.0</y>
  <z>30.0</z>
</object>

This is a very simple file with only one tag (a tag is one which has child tags or parameters, the others (model, x etc) are not tags because they only have a value, not more tags within them). If we wanted to load this file the first thing we would need to do would be to define the rules:

// Create a new rule set
new
	XML:xRules = XML_New();
// Check it created
if (xRules != NO_XML_FILE)
{
	// Add a function to handle the <object> tag
	XML_AddHandler(xRules, "object", "MyLoad_Object");
}

You then need to write a function to parse the object information. This should be public with no parameters and named the same as the third parameter in the XML_AddHandler function;

public MyLoad_Object()
{
	static
		key[MAX_XML_ENTRY_NAME],
		val[MAX_XML_ENTRY_TEXT];
	while (XML_GetKeyValue(key, val))
	{
		// Do something
		printf("key = \"%s\", val = \"%s\"", key, val);
	}
	return 1;
}

That is the basic framework of an XML callback. If you were to load the file above using these rules you would get in the console:

key = "name", val = "bin"
key = "model", val = "1337"
key = "x, val = "10.0"
key = "y, val = "20.0
key = "z, val = "30.0

As you can see it has printed all relevant key/value pairs, however they were defined originally. The variables are static for speed only.

The final thing to do is to actually load a file, this is very simple, just do:

XML_Parse(xRules, "filename");

That will load the file using the given callbacks to get the data. The complete example is:

public OnGameModeInit()
{
	// Create a new rule set
	new
		XML:xRules = XML_New();
	// Check it created
	if (xRules != NO_XML_FILE)
	{
		// Add a function to handle the <object> tag
		XML_AddHandler(xRules, "object", "MyLoad_Object");
		XML_Parse(xRules, "filename");
	}
}
 
public MyLoad_Object()
{
	static
		key[MAX_XML_ENTRY_NAME],
		val[MAX_XML_ENTRY_TEXT];
	while (XML_GetKeyValue(key, val))
	{
		new
			Float:x,
			Float:y,
			Float:z,
			model;
		while (XML_GetKeyValue(name, val))
		{
			if (!strcmp(name, "x", true)) x = floatstr(val);
			else if (!strcmp(name, "y", true)) y = floatstr(val);
			else if (!strcmp(name, "z", true)) z = floatstr(val);
			else if (!strcmp(name, "model", true)) model = strval(val);
		}
		CreateDynamicObject(model, x, y, z, 0.0, 0.0, 0.0);
	}
	return 1;
}