ISXDK:Using XML Setting Files

From Lavish Software Wiki
Jump to: navigation, search

Summary

This tutorial is to teach you how to use XML Setting Files in your custom extensions. I created a simple extension named ISXXML with mkisx to modify xml settings and walk you through what I did. NOTE: The code created in this tutorial is available at http://www.lavishsoft.com/wiki/samples/ISXXML.rar

Step 1: Creating an XML file to use

I created a very simple XML file, based loosely on a football players information. The outer set has to be named <InnerSpaceSettings> to work correctly. Inside <InnerSpaceSettings> I create a subset for each player, but you could just as easily make a subset for each team, and have each player be a subset of the team or as many subsets as you would like. Inside each set (player) I have 3 settings, number, position, and years played.

Example code
<?xml version='1.0'?>
<InnerSpaceSettings>
         <Set Name="Ralph Wiggum">
		<Setting Name="Number">33</Setting>
		<Setting Name="Position">Wide Receiver</Setting>
		<Setting Name="Years played">1</Setting>
	  </Set>
</InnerSpaceSettings>

Step 2: Adding new functions to Initialize and Shutdown

I add new functions to load and save my XML file when the extensions loads and shuts down.

Additions to Initialize
XMLStartup();
Addition to Shutdown
XMLShutdown();

Step 2.1: I add XMLStartup and XMLShutdown to class ISXXML

Here I simply add XMLStartup and XMLShutdown to the other functions called on initialize and shutdown in class ISXXML

Class ISXXML code
class ISXXML :
	public ISXInterface
{
public:
	ISXXML(void);
 	~ISXXML(void);
	virtual bool Initialize(ISInterface *p_ISInterface);
	virtual void Shutdown();

	void ConnectServices();
	void RegisterCommands();
	void RegisterAliases();
	void RegisterDataTypes();
	void RegisterTopLevelObjects();
	void RegisterServices();
	void RegisterTriggers();
        void XMLStartup();
	void DisconnectServices();
	void UnRegisterCommands();
	void UnRegisterAliases();
	void UnRegisterDataTypes();
	void UnRegisterTopLevelObjects();
	void UnRegisterServices();
        void XMLShutdown();
	void DoNothing();
};

Step 2.2: I create my functions XMLStartup and XMLShutdown

Here are the functions I created to handle opening and saving my XML file.

XMLStartup function.
void ISXXML::XMLStartup()
{
ident=pISInterface->OpenSettings("Football.xml");
}
XMLShutdown function - saves the xml file and outputs success or failure to the console.
void ISXXML::XMLShutdown()
{
	if (pISInterface->ExportSet(ident,"football.xml"))
	{
		printf("Success");
	}
	else
	{
		printf("Failure");
	}
	pISInterface->UnloadSet(ident);
}


Step 3: Adding 3 new commands

Step 3.1: I forward declare my 3 commands

I decide to name my 3 commands ListPlayers, AddPlayer, and RemovePlayer. I also add an unsigned long ident to use a placeholder for my XML's outer set GUID.

int __cdecl CMD_ListPlayers(int argc, char *argv[]);
int __cdecl CMD_AddPlayer(int argc, char *argv[]);
int __cdecl CMD_RemovePlayer(int argc, char *argv[]);
unsigned long ident;

Step 3.2: I add my 3 commands to the RegisterCommands function

RegisterCommands code
void ISXXML::RegisterCommands()
{
	pISInterface->AddCommand("ListPlayers",CMD_ListPlayers,true,false);
	pISInterface->AddCommand("AddPlayer",CMD_AddPlayer,true,false);
	pISInterface->AddCommand("RemovePlayer",CMD_RemovePlayer,true,false);
}

Step 3.3: I add my 3 commands to the UnRegisterCommands function

void ISXXML::UnRegisterCommands()
{
	pISInterface->RemoveCommand("ListPlayers");
	pISInterface->RemoveCommand("AddPlayer");
	pISInterface->RemoveCommand("RemovePlayer");
}

Step 3.4: I create CMD_ListPlayers and the Listplayers callback function

This section shows CMD_Listplayers which simply uses the pISInterface->EnumSets function to go through each subset of ident (my outer set GUID) and use the callback function ListPlayers on each set. The ListPlayers callback function takes all the data out of each subset and displays it the user.

ListPlayers callback function
void __cdecl ListPlayers(const char *Name, void *pData)
{
	unsigned long Number=0,YPlayed=0;
	unsigned long ID=pISInterface->FindSet(ident,(char *)Name);
	char Position[50]="\0";
	pISInterface->GetSetting(ID,"Number",Number);
	pISInterface->GetSetting(ID,"Position",Position,sizeof(Position));
	pISInterface->GetSetting(ID,"Years Played",YPlayed);
	printf("Player Name: %s Number: %d Position: %s Years Played: %d",Name,Number,Position,YPlayed);
}
CMD_ListPlayers
int __cdecl CMD_ListPlayers(int argc, char *argv[])
{
	pISInterface->EnumSets(ident,ListPlayers,0);
	return 0;
}

Step 3.5: I create CMD_AddPlayer function

Here I create CMD_AddPlayer. The first part of the function checks to see if the command was given with the incorrect number of arguments and if so it gives the correct syntax and returns from the function. The next part attempts to create a subset of our outer set with the <Name> of the player, if successful it fills in information for number, position, and years played telling the user it was successful. If it fails it it tells the user that the player already exists.

CMD_AddPlayer
int __cdecl CMD_AddPlayer(int argc, char *argv[])
{
    if (argc != 5)
	{
	     printf("Syntax: %s <Name> <Number> <Position> <Years Played>",argv[0]);
	     return 0;
	}
	unsigned long ID=pISInterface->CreateSet(ident,argv[1]);
	if (ID!=0)
	{
            pISInterface->SetSetting(ID,"Number",argv[2]);
            pISInterface->SetSetting(ID,"Position",argv[3]);
	     pISInterface->SetSetting(ID,"Years Played",argv[4]);
	     printf("Player %s added!",argv[1]);
	}
	else
	{
	     printf("Player already exists");
	}
return 0;
}

Step 3.6: I create CMD_RemovePlayer function

Here I create CMD_RemovePlayer function. If it is not given exactly two arguments (name of the command is argv[0], <name> is argv[1] totalling two arguments) it will display the syntax and return out of the function, otherwise it finds the set with the given <name> and clears it. It will return <name> deleted! on success and <name> not found on failure.

CMD_RemovePlayer
int __cdecl CMD_RemovePlayer(int argc, char *argv[])
{
	if (argc != 2)
	{
               printf("Syntax: %s <Name>",argv[0]);
 		return 0;
	}
	else
	{
		unsigned long ID=pISInterface->FindSet(ident,argv[1]);
		if (pISInterface->ClearSet(ID))
		{
			printf("%s deleted!",argv[1]);
		}
		else
		{
			printf("%s not found",argv[1]);
		}
	}
	return 0;
}



See Also