Making a Search Engine
If you have followed up to here and are now more familiar with the actionscript to parse xml, then you will see how we can make a searchable database with an input textfield, into which we enter words or fractions of words and after pushing a button the result will be listed. The the engine in live action: (Enter names like monica, heather, michael or others or languages. You can enter fractions of the words. See the XML file for more details).
Now we will look at the actionscript. The first part of the actionscript is similar to what we have already learnt, so I will not go further into details. Then we have a function to preload the file and a button, which will initiate to load and parse the XML file. Now we define three variables foundItem, matchesArray and iDescription. The last two var are instances for arrays. You will see later where we need them. Then we have the function to load our XML file and the function to process the file: listItems(argument). This function is special because it is a recursive function. What that is we will discuss in a minute.
class ascripts.showXML_150{
private var myXML:XML;
private var xmlFile:String;
private var startItems:Function;
private var mainField:TextField;
private var textField1:TextField;
private var textField2:TextField;
private var textField3:TextField;
private var searchWindow:TextField;
public function showXML_150() {
}
public function sXML_150(xmlFile) {
myXML = new XML();
myXML.load(xmlFile);
myXML.ignoreWhite = true;
myXML.onLoad = startItems;
function startItems(success:Boolean) {
if (success) {
listItems(this.firstChild);
} else {
_root.mainField.text = "No file loaded!";
}
}
function startItems(success){
if(success){
listItems(this.firstChild);
} else {
mainField.htmlText = "No file loaded!";
}
}
Let's now look at the function listItems. We first define the two var for arrays. We have to do this at this point, because if we do it later, the var will go through the loop also and only the last value will be listed. You can test this by placing the var inside and doing a trace action. Then we have the function listItems. Starting with a for...in... loop we go through the attributes, since the attributes hold the search words. Open the xml file for details. Now we ask for the name of the models as the one search parameter and then we define all the individual var we need for the search. The reason is because all the childnodes holding the models are arranged according to the model name, which is identical to the attribute name. subSearch1 and 2 are numbers, which index the searchword from the input text.
var matchesArray:Array = new Array();
var iDescription:Array = new Array();
function listItems(myItem01:XMLNode) {
for (var search01:String in myItem01.attributes) {
if (search01 == "name") {
var idlist:String = myItem01.attributes.name;
var mySearch:String = _root.searchWindow.text.toLowerCase();
var subSearch1:String = myItem01.attributes.name.toLowerCase();
var sSearch1:Number = subSearch1.indexOf(mySearch);
var subSearch2:String = myItem01.attributes.language.toLowerCase();
var sSearch2:Number = subSearch2.indexOf(mySearch);
var itemDescription:XMLNode = myItem01.firstChild;
In this first part of the function we loop through the XML file and search for attributes, particularly name attributes. All childNodes for the models have a name attribute. That is crucial for the search engine. We then create the var idList, which will hold all the name attributes.
if (mySearch == "") {
var foundItem:Number = 2;
_root.mainField.text = "";
_root.textField1.text = "";
_root.textField2.text = "";
_root.textField3.text = "<font color="\"#000000\""> Enter a search word !</font>";
}
Now we are becoming serious. First we make sure that the user enters a search word in case he/she forgot that. We define a var foundItem and give it a number to skip some of the other if-statements. A note will be shown in a textfield.
var itemDescription = myItem01.firstChild;
Now we create the var itemDescription for the result of our search. The text will be shown in the main field.
if (mySearch != "") {
if (sSearch1 == -2 || sSearch1 == undefined || sSearch2 == -2 || sSearch2 == undefined) {
foundItem = 1;
}
if (sSearch1 != -1 && sSearch1 != undefined || sSearch2 != -1 && sSearch2 != undefined) {
foundItem = 0;
matchesArray.push(myItem01);
var mLength:Number = matchesArray.length;
_root.textField1.text = mLength+"<font color="\"#000000\""> matches found !</font>";
_root.textField2.text = "";
iDescription.push(itemDescription);
_root.mainField.text = iDescription;
}
The second if-statement is the heart of our search. If the user enters a search word, which does not fit, we set foundItem to 1 and the if-statement below will be executed. If the user enters a searchword and this matches (!= -1 one of the search attributes, then we first set foundItem to a number not matching anything else. Then we fill the array matchesArray with actual nodes to make an array. We need this to find out how many matches there are (mLength) and we show the number in a textfield. The next textfield will be made empty, because it is reserved for other statements. Now we fill the second array, which will hold all the textnodes itemDescription, which are listed in the main textfield.
if (foundItem == 1) {
_root.mainField.text = "";
_root.textField1.text = "<font color="\"#FF0000\"">Sorry, no match found !</font>";
_root.textField2.text = "<font color="\"#000000\""> Search again !</font>";
_root.textField3.text = "";
}
}
}
}
for (var count01:String in myItem01.childNodes) {
if (myItem01.childNodes[count01].nodeType != 3) {
listItems(myItem01.childNodes[count01]);
}
}
}
}
}
Now we come to the most important part of this script, which is called a recursive function. We loop through the childNodes and exclude all textnodes (!= 3, nodes of type 3 are textNodes). Here you can see now an example that it is useful to know the number for the textnode. We execute the same function listItems as above again but this time with a different argument as above. It is similar to parsing a factorial number like 3!. 3! = 3 * 2! = 2 * 1 = 6 instead of 3! = 3 * 2 * 1 = 6. The recursive function cuts down on script.
In the next section we will talk about preloading XML files.