Example #1
0
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            System.Diagnostics.Debug.Assert(((XAttribute)context.Nodes.Peek()).Value == null);

            if (c == '\n' || c == '\r')
            {
                XAttribute att = (XAttribute)context.Nodes.Peek();
                context.LogWarning("Unexpected newline in value for attribute '" + att.Name.FullName + "'.", att.Region.Start);
            }

            if (c == '<')
            {
                //the parent state should report the error
                rollback = string.Empty;
                return(Parent);
            }
            else if (c == '"')
            {
                //ending the value
                XAttribute att = (XAttribute)context.Nodes.Peek();
                att.Value = context.KeywordBuilder.ToString();
                return(Parent);
            }
            else
            {
                context.KeywordBuilder.Append(c);
                return(null);
            }
        }
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			//NOTE: This is (mostly) duplicated in HtmlTagState
			//handle inline tags implicitly closed by block-level elements
			if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState)
			{
				XClosingTag ct = (XClosingTag) context.Nodes.Peek ();
				if (!ct.Name.HasPrefix && ct.Name.IsValid) {
					//Note: the node stack will always be at least 1 deep due to the XDocument
					var parent = context.Nodes.Peek (1) as XElement;
					//if it's not a matching closing tag
					if (parent != null && !string.Equals (ct.Name.Name, parent.Name.Name, StringComparison.OrdinalIgnoreCase)) {
						//attempt to implicitly close the parents
						while (parent != null && parent.ValidAndNoPrefix () && parent.IsImplicitlyClosedBy (ct)) {
							context.Nodes.Pop ();
							context.Nodes.Pop ();
							if (warnAutoClose) {
								context.LogWarning (string.Format ("Tag '{0}' implicitly closed by closing tag '{1}'.",
									parent.Name.Name, ct.Name.Name), parent.Region);
							}
							//parent.Region.End = element.Region.Start;
							//parent.Region.EndColumn = Math.Max (parent.Region.EndColumn - 1, 1);
							parent.Close (parent);
							context.Nodes.Push (ct);

							parent = context.Nodes.Peek (1) as XElement;
						}
					}
				} 
			}
			
			return base.PushChar (c, context, ref rollback);
		}
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			//NOTE: This is (mostly) duplicated in HtmlClosingTagState
			//handle "paragraph" tags implicitly closed by block-level elements
			if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState)
			{
				XElement element = (XElement) context.Nodes.Peek ();
				//Note: the node stack will always be at least 1 deep due to the XDocument
				XElement parent = context.Nodes.Peek (1) as XElement;
				
				while (parent != null && parent.Name.IsValid && !parent.Name.HasPrefix && !element.Name.HasPrefix
				    && element.Name.IsValid
				    && !ElementTypes.IsInline (element.Name.Name)
				    && (ElementTypes.IsInline (parent.Name.Name) || ElementTypes.IsParagraph (parent.Name.Name))
				    )
				{
					
					context.Nodes.Pop ();
					context.Nodes.Pop ();
					if (warnAutoClose) {
						context.LogWarning (string.Format ("Tag '{0}' implicitly closed by tag '{1}'.",
							parent.Name.Name, element.Name.Name), parent.Region);
					}
					//parent.Region.End = element.Region.Start;
					//parent.Region.End.Column = Math.Max (parent.Region.End.Column - 1, 1);
					parent.Close (parent);
					context.Nodes.Push (element);
					
					parent = context.Nodes.Peek (1) as XElement;
				}
			}
						
			State ret = base.PushChar (c, context, ref rollback);
			
			//handle implicitly empty tags
			if (c == '>')
			{
				XElement element = context.Nodes.Peek () as XElement;
				if (element != null && !element.Name.HasPrefix && element.Name.IsValid
				    && ElementTypes.IsEmpty (element.Name.Name))
				{
					element.Close (element);
					context.Nodes.Pop ();
					
					if (warnAutoClose) {
						context.LogWarning (string.Format ("Implicitly closed empty tag '{0}'", element.Name.Name),
						                    element.Region);
					}
				}
			}
			
			return ret;
		}
Example #4
0
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			if (context.CurrentStateLength == 1 && context.PreviousState is HtmlScriptBodyState)
				return Parent;
			
			//NOTE: This is (mostly) duplicated in HtmlClosingTagState
			//handle "paragraph" tags implicitly closed by block-level elements
			if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState) {
				XElement element = (XElement) context.Nodes.Peek ();

				if (!element.Name.HasPrefix && element.Name.IsValid) {
					//Note: the node stack will always be at least 1 deep due to the XDocument
					var parent = context.Nodes.Peek (1) as XElement;

					while (parent.ValidAndNoPrefix () && parent.IsImplicitlyClosedBy (element)) {
						context.Nodes.Pop ();
						context.Nodes.Pop ();
						if (warnAutoClose) {
							context.LogWarning (string.Format ("Tag '{0}' implicitly closed by tag '{1}'.",
							                                   parent.Name.Name, element.Name.Name), parent.Region);
						}
						//parent.Region.End = element.Region.Start;
						//parent.Region.EndColumn = Math.Max (parent.Region.EndColumn - 1, 1);
						parent.Close (parent);
						context.Nodes.Push (element);

						parent = context.Nodes.Peek (1) as XElement;
					}
				}
			}
						
			State ret = base.PushChar (c, context, ref rollback);
			
			if (ret == Parent && c == '>') {
				var element = context.Nodes.Peek () as XElement;
				if (element != null && !element.Name.HasPrefix && element.Name.IsValid) {
					if (element.Name.Name.Equals ("script", StringComparison.OrdinalIgnoreCase)) {
					    return ScriptState;
					} else if (ElementTypes.IsEmpty (element.Name.Name)) {
						element.Close (element);
						context.Nodes.Pop ();
						
						if (warnAutoClose) {
							context.LogWarning (string.Format ("Implicitly closed empty tag '{0}'", element.Name.Name),
							                    element.Region);
						}
					}
				}
			}
			
			return ret;
		}
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            if (context.CurrentStateLength == 1)
            {
                context.Nodes.Push(new XComment(context.LocationMinus("<!--".Length + 1)));
            }

            if (c == '-')
            {
                //make sure we know when there are two '-' chars together
                if (context.StateTag == NOMATCH)
                {
                    context.StateTag = SINGLE_DASH;
                }
                else
                {
                    context.StateTag = DOUBLE_DASH;
                }
            }
            else if (context.StateTag == DOUBLE_DASH)
            {
                if (c == '>')
                {
                    // if the '--' is followed by a '>', the state has ended
                    // so attach a node to the DOM and end the state
                    XComment comment = (XComment)context.Nodes.Pop();

                    if (context.BuildTree)
                    {
                        comment.End(context.Location);
                        ((XContainer)context.Nodes.Peek()).AddChildNode(comment);
                    }

                    rollback = string.Empty;
                    return(Parent);
                }
                else
                {
                    context.LogWarning("The string '--' should not appear within comments.");
                }
            }
            else
            {
                // not any part of a '-->', so make sure matching is reset
                context.StateTag = NOMATCH;
            }

            return(null);
        }
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            //NOTE: This is (mostly) duplicated in HtmlTagState
            //handle inline tags implicitly closed by block-level elements
            if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState)
            {
                XClosingTag ct = (XClosingTag)context.Nodes.Peek();
                if (!ct.Name.HasPrefix && ct.Name.IsValid)
                {
                    //Note: the node stack will always be at least 1 deep due to the XDocument
                    var parent = context.Nodes.Peek(1) as XElement;
                    //if it's not a matching closing tag
                    if (parent != null && !string.Equals(ct.Name.Name, parent.Name.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        //attempt to implicitly close the parents
                        while (parent != null && parent.ValidAndNoPrefix() && parent.IsImplicitlyClosedBy(ct))
                        {
                            context.Nodes.Pop();
                            context.Nodes.Pop();
                            if (warnAutoClose)
                            {
                                context.LogWarning(string.Format("Tag '{0}' implicitly closed by closing tag '{1}'.",
                                                                 parent.Name.Name, ct.Name.Name), parent.Region);
                            }
                            //parent.Region.End = element.Region.Start;
                            //parent.Region.EndColumn = Math.Max (parent.Region.EndColumn - 1, 1);
                            parent.Close(parent);
                            context.Nodes.Push(ct);

                            parent = context.Nodes.Peek(1) as XElement;
                        }
                    }
                }
            }

            return(base.PushChar(c, context, ref rollback));
        }
Example #7
0
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			if (context.CurrentStateLength == 1) {
				context.Nodes.Push (new XComment (context.LocationMinus ("<!--".Length + 1)));
			}
			
			if (c == '-') {
				//make sure we know when there are two '-' chars together
				if (context.StateTag == NOMATCH)
					context.StateTag = SINGLE_DASH;
				else
					context.StateTag = DOUBLE_DASH;
				
			} else if (context.StateTag == DOUBLE_DASH) {
				if (c == '>') {
					// if the '--' is followed by a '>', the state has ended
					// so attach a node to the DOM and end the state
					XComment comment = (XComment) context.Nodes.Pop ();
					
					if (context.BuildTree) {
						comment.End (context.Location);
						((XContainer) context.Nodes.Peek ()).AddChildNode (comment);
					}
					
					rollback = string.Empty;
					return Parent;
				} else {
					context.LogWarning ("The string '--' should not appear within comments.");
				}
			} else {
				// not any part of a '-->', so make sure matching is reset
				context.StateTag = NOMATCH;
			}
			
			return null;
		}
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            if (context.CurrentStateLength == 0 && context.PreviousState is HtmlScriptBodyState)
            {
                return(Parent);
            }

            //NOTE: This is (mostly) duplicated in HtmlClosingTagState
            //handle "paragraph" tags implicitly closed by block-level elements
            if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState)
            {
                XElement element = (XElement)context.Nodes.Peek();
                //Note: the node stack will always be at least 1 deep due to the XDocument
                XElement parent = context.Nodes.Peek(1) as XElement;

                while (parent != null && parent.Name.IsValid && !parent.Name.HasPrefix && !element.Name.HasPrefix &&
                       element.Name.IsValid &&
                       !ElementTypes.IsInline(element.Name.Name) &&
                       (ElementTypes.IsInline(parent.Name.Name) || ElementTypes.IsParagraph(parent.Name.Name))
                       )
                {
                    context.Nodes.Pop();
                    context.Nodes.Pop();
                    if (warnAutoClose)
                    {
                        context.LogWarning(string.Format("Tag '{0}' implicitly closed by tag '{1}'.",
                                                         parent.Name.Name, element.Name.Name), parent.Region);
                    }
                    //parent.Region.End = element.Region.Start;
                    //parent.Region.End.Column = Math.Max (parent.Region.End.Column - 1, 1);
                    parent.Close(parent);
                    context.Nodes.Push(element);

                    parent = context.Nodes.Peek(1) as XElement;
                }
            }

            State ret = base.PushChar(c, context, ref rollback);

            if (ret == Parent && c == '>')
            {
                var element = context.Nodes.Peek() as XElement;
                if (element != null && !element.Name.HasPrefix && element.Name.IsValid)
                {
                    if (element.Name.Name.Equals("script", StringComparison.OrdinalIgnoreCase))
                    {
                        return(ScriptState);
                    }
                    else if (ElementTypes.IsEmpty(element.Name.Name))
                    {
                        element.Close(element);
                        context.Nodes.Pop();

                        if (warnAutoClose)
                        {
                            context.LogWarning(string.Format("Implicitly closed empty tag '{0}'", element.Name.Name),
                                               element.Region);
                        }
                    }
                }
            }

            return(ret);
        }
Example #9
0
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            XAttribute att = context.Nodes.Peek() as XAttribute;

            if (c == '<')
            {
                //parent handles message
                if (att != null)
                {
                    context.Nodes.Pop();
                }
                rollback = string.Empty;
                return(Parent);
            }

            //state has just been entered
            if (context.CurrentStateLength == 1)
            {
                if (context.PreviousState is XmlNameState)
                {
                    Debug.Assert(att.IsNamed);
                    context.StateTag = GETTINGEQ;
                }
                else if (context.PreviousState is XmlAttributeValueState)
                {
                    //Got value, so end attribute
                    context.Nodes.Pop();
                    att.End(context.LocationMinus(1));
                    IAttributedXObject element = (IAttributedXObject)context.Nodes.Peek();
                    element.Attributes.AddAttribute(att);
                    rollback = string.Empty;
                    return(Parent);
                }
                else
                {
                    //starting a new attribute
                    Debug.Assert(att == null);
                    Debug.Assert(context.StateTag == NAMING);
                    att = new XAttribute(context.LocationMinus(1));
                    context.Nodes.Push(att);
                    rollback = string.Empty;
                    return(XmlNameState);
                }
            }

            if (c == '>')
            {
                context.LogWarning("Attribute ended unexpectedly with '>' character.");
                if (att != null)
                {
                    context.Nodes.Pop();
                }
                rollback = string.Empty;
                return(Parent);
            }

            if (context.StateTag == GETTINGEQ)
            {
                if (char.IsWhiteSpace(c))
                {
                    return(null);
                }
                else if (c == '=')
                {
                    context.StateTag = GETTINGVAL;
                    return(null);
                }
            }
            else if (context.StateTag == GETTINGVAL)
            {
                if (char.IsWhiteSpace(c))
                {
                    return(null);
                }
                else if (c == '"')
                {
                    return(DoubleQuotedAttributeValueState);
                }
                else if (c == '\'')
                {
                    return(SingleQuotedAttributeValueState);
                }
                else if (char.IsLetterOrDigit(c))
                {
                    rollback = string.Empty;
                    return(UnquotedAttributeValueState);
                }
            }

            if (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsWhiteSpace(c))
            {
                if (context.StateTag == GETTINGEQ)
                {
                    context.LogError("Expecting = in attribute, got " + c + ".");
                }
                else if (context.StateTag == GETTINGVAL)
                {
                    context.LogError("Expecting attribute value, got " + c + ".");
                }
                else
                {
                    context.LogError("Unexpected character '" + c + "' in attribute.");
                }

                if (att != null)
                {
                    context.Nodes.Pop();
                }
                rollback = string.Empty;
                return(Parent);
            }

            rollback = string.Empty;
            return(Parent);
        }
Example #10
0
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            XElement element = context.Nodes.Peek() as XElement;

            if (element == null || element.IsComplete)
            {
                element = new XElement(context.LocationMinus(2));                   // 2 == < + current char
                context.Nodes.Push(element);
            }

            if (c == '<')
            {
                if (element.IsNamed)
                {
                    context.LogError("Unexpected '<' in tag '" + element.Name.FullName + "'.");
                    Close(element, context, context.LocationMinus(1));
                }
                else
                {
                    context.LogError("Unexpected '<' in unnamed tag.");
                }

                rollback = string.Empty;
                return(Parent);
            }

            Debug.Assert(!element.IsComplete);

            if (element.IsClosed && c != '>')
            {
                if (char.IsWhiteSpace(c))
                {
                    context.LogWarning("Unexpected whitespace after '/' in self-closing tag.");
                    return(null);
                }
                context.LogError("Unexpected character '" + c + "' after '/' in self-closing tag.");
                context.Nodes.Pop();
                return(Parent);
            }

            //if tag closed
            if (c == '>')
            {
                if (context.StateTag == MAYBE_SELF_CLOSING)
                {
                    element.Close(element);
                }
                if (!element.IsNamed)
                {
                    context.LogError("Tag closed prematurely.");
                }
                else
                {
                    Close(element, context, context.Location);
                }
                return(Parent);
            }

            if (c == '/')
            {
                context.StateTag = MAYBE_SELF_CLOSING;
                return(null);
            }

            if (context.StateTag == ATTEMPT_RECOVERY)
            {
                if (XmlChar.IsWhitespace(c))
                {
                    context.StateTag = RECOVERY_FOUND_WHITESPACE;
                }
                return(null);
            }

            if (context.StateTag == RECOVERY_FOUND_WHITESPACE)
            {
                if (!XmlChar.IsFirstNameChar(c))
                {
                    return(null);
                }
            }

            context.StateTag = OK;

            if (!element.IsNamed && XmlChar.IsFirstNameChar(c))
            {
                rollback = string.Empty;
                return(NameState);
            }

            if (context.CurrentStateLength > 1 && XmlChar.IsFirstNameChar(c))
            {
                rollback = string.Empty;
                return(AttributeState);
            }

            if (XmlChar.IsWhitespace(c))
            {
                return(null);
            }

            context.LogError("Unexpected character '" + c + "' in tag.", context.LocationMinus(1));
            context.StateTag = ATTEMPT_RECOVERY;
            return(null);
        }
Example #11
0
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			XElement element = context.Nodes.Peek () as XElement;
			
			if (element == null || element.IsComplete) {
				element = new XElement (context.LocationMinus (2)); // 2 == < + current char
				context.Nodes.Push (element);
			}
			
			if (c == '<') {
				if (element.IsNamed) {
					context.LogError ("Unexpected '<' in tag '" + element.Name.FullName + "'.");
					Close (element, context, context.LocationMinus (1));
				} else {
					context.LogError ("Unexpected '<' in unnamed tag.");
				}
				
				rollback = string.Empty;
				return Parent;
			}
			
			Debug.Assert (!element.IsComplete);
			
			if (element.IsClosed && c != '>') {
				if (char.IsWhiteSpace (c)) {
					context.LogWarning ("Unexpected whitespace after '/' in self-closing tag.");
					return null;
				}
				context.LogError ("Unexpected character '" + c + "' after '/' in self-closing tag.");
				context.Nodes.Pop ();
				return Parent;
			}
			
			//if tag closed
			if (c == '>') {
				if (context.StateTag == MAYBE_SELF_CLOSING) {
					element.Close (element);
				}
				if (!element.IsNamed) {
					context.LogError ("Tag closed prematurely.");
				} else {
					Close (element, context, context.Location);
				}
				return Parent;
			}

			if (c == '/') {
				context.StateTag = MAYBE_SELF_CLOSING;
				return null;
			}

			if (context.StateTag == ATTEMPT_RECOVERY) {
				if (XmlChar.IsWhitespace (c)) {
					context.StateTag = RECOVERY_FOUND_WHITESPACE;
				}
				return null;
			}

			if (context.StateTag == RECOVERY_FOUND_WHITESPACE) {
				if (!XmlChar.IsFirstNameChar (c))
					return null;
			}

			context.StateTag = OK;

			if (!element.IsNamed && XmlChar.IsFirstNameChar (c)) {
				rollback = string.Empty;
				return NameState;
			}

			if (context.CurrentStateLength > 1 && XmlChar.IsFirstNameChar (c)) {
				rollback = string.Empty;
				return AttributeState;
			}
			
			if (XmlChar.IsWhitespace (c))
				return null;

			context.LogError ("Unexpected character '" + c + "' in tag.", context.LocationMinus (1));
			context.StateTag = ATTEMPT_RECOVERY;
			return null;
		}
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			XAttribute att = context.Nodes.Peek () as XAttribute;
			
			if (c == '<') {
				//parent handles message
				if (att != null)
					context.Nodes.Pop ();
				rollback = string.Empty;
				return Parent;
			}
			
			//state has just been entered
			if (context.CurrentStateLength == 1)  {
				
				if (context.PreviousState is XmlNameState) {
					Debug.Assert (att.IsNamed);
					context.StateTag = GETTINGEQ;
				}
				else if (context.PreviousState is XmlAttributeValueState) {
					//Got value, so end attribute
					context.Nodes.Pop ();
					att.End (context.LocationMinus (1));
					IAttributedXObject element = (IAttributedXObject) context.Nodes.Peek ();
					element.Attributes.AddAttribute (att);
					rollback = string.Empty;
					return Parent;
				}
				else {
					//starting a new attribute
					Debug.Assert (att == null);
					Debug.Assert (context.StateTag == NAMING);
					att = new XAttribute (context.LocationMinus (1));
					context.Nodes.Push (att);
					rollback = string.Empty;
					return XmlNameState;
				}
			}
			
			if (c == '>') {
				context.LogWarning ("Attribute ended unexpectedly with '>' character.");
				if (att != null)
					context.Nodes.Pop ();
				rollback = string.Empty;
				return Parent;
			}
			
			if (context.StateTag == GETTINGEQ) {
				if (char.IsWhiteSpace (c)) {
					return null;
				} else if (c == '=') {
					context.StateTag = GETTINGVAL;
					return null;
				}
			} else if (context.StateTag == GETTINGVAL) {
				if (char.IsWhiteSpace (c)) {
					return null;
				} else if (c== '"') {
					return DoubleQuotedAttributeValueState;
				} else if (c == '\'') {
					return SingleQuotedAttributeValueState;
				} else if (char.IsLetterOrDigit (c)) {
					rollback = string.Empty;
					return UnquotedAttributeValueState;
				}
			}
			
			if (Char.IsLetterOrDigit (c) || char.IsPunctuation (c) || char.IsWhiteSpace (c)) {
				string err;
				if (context.StateTag == GETTINGEQ)
					context.LogError ("Expecting = in attribute, got " + c + ".");
				else if (context.StateTag == GETTINGVAL)
					context.LogError ("Expecting attribute value, got " + c + ".");
				else
					context.LogError ("Unexpected character '" + c + "' in attribute.");
				
				if (att != null)
					context.Nodes.Pop ();
				rollback = string.Empty;
				return Parent;
			}
			
			rollback = string.Empty;
			return Parent;
		}
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			XElement element = context.Nodes.Peek () as XElement;
			
			if (element == null || element.IsComplete) {
				element = new XElement (context.LocationMinus (2)); // 2 == < + current char
				context.Nodes.Push (element);
			}
			
			if (c == '<') {
				if (element.IsNamed) {
					context.LogError ("Unexpected '<' in tag '" + element.Name.FullName + "'.");
					Close (element, context);
				} else {
					context.LogError ("Unexpected '<' in unnamed tag.");
				}
				
				rollback = string.Empty;
				return Parent;
			}
			
			Debug.Assert (!element.IsComplete);
			
			if (element.IsClosed && c != '>') {
				if (char.IsWhiteSpace (c)) {
					context.LogWarning ("Unexpected whitespace after '/' in self-closing tag.");
					return null;
				} else {
					context.LogError ("Unexpected character '" + c + "' after '/' in self-closing tag.");
					context.Nodes.Pop ();
					return Parent;
				}
			}
			
			//if tag closed
			if (c == '>') {
				if (!element.IsNamed) {
					context.LogError ("Tag closed prematurely.");
				} else {
					Close (element, context);
				}
				return Parent;
			}
			
			if (XmlChar.IsFirstNameChar (c)) {
				rollback = string.Empty;
				if (!element.IsNamed) {
					return NameState;
				} else {
					return AttributeState;
				}
			}
			
			if (c == '/') {
				element.Close (element);
				return null;
			}
			
			if (XmlChar.IsWhitespace (c))
				return null;
			
			if (element.IsNamed)
				Close (element, context);
			context.LogError ("Unexpected character '" + c + "' in tag.");
			
			rollback = string.Empty;
			return Parent;
		}
		public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			System.Diagnostics.Debug.Assert (((XAttribute) context.Nodes.Peek ()).Value == null);
			
			if (c == '\n' || c == '\r') {
				XAttribute att = (XAttribute) context.Nodes.Peek ();
				context.LogWarning ("Unexpected newline in value for attribute '" + att.Name.FullName +"'.", att.Region.Start);
			}
			
			if (c == '<') {
				//the parent state should report the error
				rollback = string.Empty;
				return Parent;
			} else if (c == '\'') {
				//ending the value
				XAttribute att = (XAttribute) context.Nodes.Peek ();
				att.Value = context.KeywordBuilder.ToString ();
				return Parent;
			}
			else {
				context.KeywordBuilder.Append (c);
				return null;
			}
		}