public ScraperNode(XmlNode xmlNode, InternalScriptSettings settings)
        {
            this.xmlNode = xmlNode;
            children = new List<ScraperNode>();
            this.ScriptSettings = settings;
            loadSuccess = loadChildren();

            // try to load our node attrbute
            foreach(Attribute currAttr in this.GetType().GetCustomAttributes(true))
                if (currAttr is ScraperNodeAttribute) {
                    nodeSettings = (ScraperNodeAttribute) currAttr;
                    continue;
                }

            if (nodeSettings.LoadNameAttribute) {

                // Load attributes
                foreach (XmlAttribute attr in xmlNode.Attributes) {
                    switch (attr.Name) {
                        case "name":
                            name = attr.Value;
                            break;
                    }
                }

               // Validate NAME attribute
                if (name == null) {
                    logger.Error("Missing NAME attribute on: " + xmlNode.OuterXml);
                    loadSuccess = false;
                    return;
                }

                // if it's a bad variable name we fail as well
                if (Name.Contains(" ")) {
                    logger.Error("Invalid NAME attribute (no spaces allowed) \"" + Name + "\" for " + xmlNode.OuterXml);
                    loadSuccess = false;
                    return;
                }
            }
        }
        private void loadActionNodes()
        {
            InternalScriptSettings settings = new InternalScriptSettings();
            settings.DebugMode = DebugMode;
            settings.Cache = cache;

            actionNodes = new Dictionary<string, ScraperNode>();
            foreach (XmlNode currAction in xml.DocumentElement.SelectNodes("child::action")) {
                ActionNode newNode = (ActionNode)ScraperNode.Load(currAction, settings);
                if (newNode != null && newNode.LoadSuccess)
                    actionNodes[newNode.Name] = newNode;
                else {
                    logger.Error("Error loading action node: " + currAction.OuterXml);
                    loadSuccessful = false;
                }
            }
        }
        public static ScraperNode Load(XmlNode xmlNode, InternalScriptSettings settings)
        {
            if (xmlNode == null || xmlNode.NodeType == XmlNodeType.Comment || xmlNode.NodeType == XmlNodeType.CDATA)
                return null;

            Type nodeType = null;
            string nodeTypeName = xmlNode.Name;

            // try to grab the type from our dictionary
            if (nodeTypes.ContainsKey(nodeTypeName))
                nodeType = nodeTypes[nodeTypeName];

            // if it's not there, search the assembly for the type
            else {
                Type[] typeList = Assembly.GetExecutingAssembly().GetTypes();
                foreach (Type currType in typeList)
                    foreach (Attribute currAttr in currType.GetCustomAttributes(true))
                        if (currAttr.GetType() == typeof(ScraperNodeAttribute) &&
                            nodeTypeName.Equals(((ScraperNodeAttribute)currAttr).NodeName)) {

                            // store our type and put it in our dictionary so we dont have to
                            // look it up again
                            nodeTypes[nodeTypeName] = currType;
                            nodeType = currType;
                            break;
                        }
            }

            // if we couldn't find anything log the unhandled node and exit
            if (nodeType == null) {
                logger.Error("Unsupported node type: " + xmlNode.OuterXml);
                return null;
            }

            // try to create a new scraper node object
            try {
                ConstructorInfo constructor = nodeType.GetConstructor(new Type[] { typeof(XmlNode), typeof(InternalScriptSettings) });
                ScraperNode newNode = (ScraperNode)constructor.Invoke(new object[] { xmlNode, settings });
                return newNode;
            }
            catch (Exception e) {
                if (e.GetType() == typeof(ThreadAbortException))
                    throw e;

                logger.Error("Error instantiating ScraperNode based on: " + xmlNode.OuterXml, e);
                return null;
            }
        }