/// <summary> Scan for style definitions.
		/// Accumulates text from the page, until &lt;/[a-zA-Z] is encountered.
		/// </summary>
		/// <param name="tag">The tag this scanner is responsible for.
		/// </param>
		/// <param name="lexer">The source of CDATA.
		/// </param>
		/// <param name="stack">The parse stack, <em>not used</em>.
		/// </param>
		public override ITag Scan(ITag tag, Lexer lexer, NodeList stack)
		{
			INode content;
			int position;
			INode node;
			TagAttribute attribute;
			System.Collections.ArrayList vector;
			
			content = lexer.ParseCDATA();
			position = lexer.Position;
			node = lexer.NextNode(false);
			if (null != node)
				if (!(node is ITag) || !(((ITag) node).IsEndTag() && ((ITag) node).TagName.Equals(tag.Ids[0])))
				{
					lexer.Position = position;
					node = null;
				}
			
			// build new end tag if required
			if (null == node)
			{
				attribute = new TagAttribute("/style", null);
				vector = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
				vector.Add(attribute);
				node = lexer.NodeFactory.CreateTagNode(lexer.Page, position, position, vector);
			}
			tag.SetEndTag((ITag) node);
			if (null != content)
			{
				tag.Children = new NodeList(content);
				content.Parent = tag;
			}
			node.Parent = tag;
			tag.DoSemanticAction();
			
			return (tag);
		}
		/// <summary> Set an attribute.
		/// This replaces an attribute of the same name.
		/// To set the zeroth attribute (the tag name), use setTagName().
		/// </summary>
		/// <param name="attribute">The attribute to set.
		/// </param>
		public virtual void SetAttribute(TagAttribute attribute)
		{
			bool replaced;
			System.Collections.ArrayList attributes;
			int length;
			System.String name;
			TagAttribute test;
			System.String test_name;
			
			replaced = false;
			attributes = AttributesEx;
			length = attributes.Count;
			if (0 < length)
			{
				name = attribute.GetName();
				for (int i = 1; i < attributes.Count; i++)
				{
					test = (TagAttribute) attributes[i];
					test_name = test.GetName();
					if (null != test_name)
						if (test_name.ToUpper().Equals(name.ToUpper()))
						{
							attributes[i] = attribute;
							replaced = true;
						}
				}
			}
			if (!replaced)
			{
				// add whitespace between attributes
				if ((0 != length) && !((TagAttribute) attributes[length - 1]).Whitespace)
					attributes.Add(new TagAttribute(" "));
				attributes.Add(attribute);
			}
		}
		/// <summary> Scan for script.
		/// Accumulates text from the page, until &lt;/[a-zA-Z] is encountered.
		/// </summary>
		/// <param name="tag">The tag this scanner is responsible for.
		/// </param>
		/// <param name="lexer">The source of CDATA.
		/// </param>
		/// <param name="stack">The parse stack, <em>not used</em>.
		/// </param>
		public override ITag Scan(ITag tag, Lexer lexer, NodeList stack)
		{
			System.String language;
			System.String code;
			INode content;
			int position;
			INode node;
			TagAttribute attribute;
			System.Collections.ArrayList vector;
			
			if (tag is ScriptTag)
			{
				language = ((ScriptTag) tag).Language;
				if ((null != language) && (language.ToUpper().Equals("JScript.Encode".ToUpper()) || language.ToUpper().Equals("VBScript.Encode".ToUpper())))
				{
					code = ScriptDecoder.Decode(lexer.Page, lexer.Cursor);
					((ScriptTag) tag).ScriptCode = code;
				}
			}
			content = lexer.ParseCDATA(!STRICT);
			position = lexer.Position;
			node = lexer.NextNode(false);
			if (null != node)
				if (!(node is ITag) || !(((ITag) node).IsEndTag() && ((ITag) node).TagName.Equals(tag.Ids[0])))
				{
					lexer.Position = position;
					node = null;
				}
			
			// build new end tag if required
			if (null == node)
			{
				attribute = new TagAttribute("/script", null);
				vector = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
				vector.Add(attribute);
				node = lexer.NodeFactory.CreateTagNode(lexer.Page, position, position, vector);
			}
			tag.SetEndTag((ITag) node);
			if (null != content)
			{
				tag.Children = new NodeList(content);
				content.Parent = tag;
			}
			node.Parent = tag;
			tag.DoSemanticAction();
			
			return (tag);
		}
		/// <summary> Set an attribute.</summary>
		/// <param name="attribute">The attribute to set.
		/// </param>
		public virtual void SetAttributeEx(TagAttribute attribute)
		{
			SetAttribute(attribute);
		}
 public void TestToString()
 {
     var attr = new TagAttribute("align", "left");
     Assert.AreEqual("align=\"left\"", attr.ToString());
 }
 public void TestHtmlDecodingValue()
 {
     var attr = new TagAttribute("value", "3 &lt; 5");
     Assert.AreEqual("3 < 5", attr.Value);
 }
 public void TestEquivalence()
 {
     var attr = new TagAttribute("align", "left");
     var attr2 = new TagAttribute("align", "left");
     Assert.AreEqual(attr, attr2);
 }
            public static bool IsValidForTag(TagAttribute att, AcceptableTag tag)
            {
                bool result = false;

                if (tag.AcceptableAttributes.Contains(att.Name)) {
                    result = true;
                }

                return result;
            }
        private static List<TagAttribute> ParseAttributeList(string input, AcceptableTag tag)
        {
            string temp = input.Substring(tag.Tagname.Length + 1, input.Length - (tag.Tagname.Length + 2));
            if (temp.EndsWith("/"))
                temp = temp.TrimEnd('/');
            temp = temp.Trim();

            List<TagAttribute> result = new List<TagAttribute>();

            bool isParsingAttribute = false;
            bool isParsingAttributeValue = false;

            TagAttribute currentAttribute = null;

            // loop through all characters, splitting of attributes
            for (int i = 0; i < temp.Length; i++) {
                char current = temp[i];

                if (isParsingAttribute) {
                    if (isParsingAttributeValue) {
                        // append the current character
                        currentAttribute.Value += current;

                        // check to see if we're done with the attribute
                        if (currentAttribute.Value.Length >= 2) {
                            if (currentAttribute.Value.EndsWith("\"")) {
                                isParsingAttributeValue = false;
                                isParsingAttribute = false;
                                if (TagAttribute.IsValidForTag(currentAttribute, tag)) {
                                    currentAttribute.Value = currentAttribute.Value.TrimStart('"');
                                    currentAttribute.Value = currentAttribute.Value.TrimEnd('"');

                                    if (currentAttribute.Name == "src" || currentAttribute.Name == "href") {
                                        if (currentAttribute.Value.IndexOf("javascript", StringComparison.InvariantCultureIgnoreCase) > -1) {
                                            currentAttribute.Value = currentAttribute.Value.ToLowerInvariant().Replace("javascript", "");
                                        }

                                        if (currentAttribute.Value.IndexOf("vbscript", StringComparison.InvariantCultureIgnoreCase) > -1) {
                                            currentAttribute.Value = currentAttribute.Value.ToLowerInvariant().Replace("vbscript", "");
                                        }

                                    }

                                    result.Add(currentAttribute);
                                }
                                currentAttribute = null;
                            }
                        }
                    }
                    else {
                        // we're not parsing the value yet so check for "="
                        if (current == '=') {
                            // skip this charater but enable attribute value parsing;
                            isParsingAttributeValue = true;
                        }
                        else {
                            currentAttribute.Name += current;
                        }
                    }
                }
                else {
                    // not parsing right now, check to see if we need to start
                    if (!char.IsWhiteSpace(current)) {
                        // not white space so let's start our attribute name
                        currentAttribute = new TagAttribute(current.ToString(), "");
                        isParsingAttribute = true;
                    }

                }

            }

            return result;
        }