public override XmlParserState PushChar (char c, IXmlParserContext 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) { var 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 XmlParserState PushChar(char c, IXmlParserContext 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 var 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."); context.StateTag = NOMATCH; } } else { // not any part of a '-->', so make sure matching is reset context.StateTag = NOMATCH; } return(null); }
public override XmlParserState PushChar(char c, IXmlParserContext 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) { var 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 XmlParserState PushChar (char c, IXmlParserContext 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 var 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."); context.StateTag = NOMATCH; } } else { // not any part of a '-->', so make sure matching is reset context.StateTag = NOMATCH; } return null; }
public override XmlParserState PushChar(char c, IXmlParserContext context, ref string rollback) { XElement element = context.Nodes.Peek() as XElement; if (element == null || element.IsComplete) { var parent = element; element = new XElement(context.LocationMinus(2)); // 2 == < + current char element.Parent = parent; 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 XmlParserState PushChar (char c, IXmlParserContext 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 XmlParserState PushChar(char c, IXmlParserContext context, ref string rollback) { var element = context.Nodes.Peek() as XElement; if (element == null || element.IsEnded) { var parent = element; element = new XElement(context.Position - 2) { Parent = parent }; // 2 == < + current char context.Nodes.Push(element); if (context.BuildTree) { var parentContainer = (XContainer)context.Nodes.Peek(element.IsClosed ? 0 : 1); parentContainer.AddChildNode(element); } } if (c == '<') { if (element.IsNamed) { context.LogError("Unexpected '<' in tag '" + element.Name.FullName + "'."); Close(element, context, context.Position - 1); } else { context.LogError("Tag has no name.", element.Span.Start); } rollback = string.Empty; return(Parent); } Debug.Assert(!element.IsEnded); 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 == '>') { element.HasEndBracket = true; if (context.StateTag == MAYBE_SELF_CLOSING) { element.Close(element); } if (!element.IsNamed) { context.LogError("Tag closed prematurely."); } else { Close(element, context, context.Position); } 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 = FREE; if (context.CurrentStateLength > 1 && XmlChar.IsFirstNameChar(c)) { rollback = string.Empty; return(AttributeState); } if (!element.IsNamed && XmlChar.IsFirstNameChar(c)) { rollback = string.Empty; return(NameState); } if (XmlChar.IsWhitespace(c)) { return(null); } context.LogError("Unexpected character '" + c + "' in tag.", context.Position - 1); context.StateTag = ATTEMPT_RECOVERY; return(null); }