protected XmlParser(XmlRootState rootState) { RootState = rootState; Context = new XmlParserContext { CurrentStateLength = 0, CurrentState = rootState, PreviousState = rootState, KeywordBuilder = new StringBuilder(), Nodes = new NodeStack() }; Context.Nodes.Push(RootState.CreateDocument()); }
public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback) { System.Diagnostics.Debug.Assert(((XAttribute)context.Nodes.Peek()).Value == null); if (c == '<') { //the parent state should report the error rollback = string.Empty; return(Parent); } if (context.CurrentStateLength == 0) { if (c == '"') { context.StateTag = DOUBLEQUOTE; return(null); } if (c == '\'') { context.StateTag = SINGLEQUOTE; return(null); } context.StateTag = UNQUOTED; } int maskedTag = context.StateTag & TagMask; if (maskedTag == UNQUOTED) { return(BuildUnquotedValue(c, context, ref rollback)); } if ((c == '"' && maskedTag == DOUBLEQUOTE) || c == '\'' && maskedTag == SINGLEQUOTE) { //ending the value var att = (XAttribute)context.Nodes.Peek(); att.Value = context.KeywordBuilder.ToString(); return(Parent); } context.KeywordBuilder.Append(c); return(null); }
XmlParserState BuildUnquotedValue(char c, XmlParserContext context, ref string rollback) { if (char.IsLetterOrDigit(c) || c == '_' || c == '.') { context.KeywordBuilder.Append(c); return(null); } if (context.KeywordBuilder.Length == 0) { context.Diagnostics?.LogError($"The value of attribute '{(string)((XAttribute)context.Nodes.Peek ()).Name.FullName}' ended unexpectedly.", context.Position); rollback = string.Empty; return(Parent); } var att = (XAttribute)context.Nodes.Peek(); att.Value = context.KeywordBuilder.ToString(); rollback = string.Empty; return(Parent); }
public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback) { if (context.CurrentStateLength == 0) { context.Nodes.Push(new XCData(context.Position - STARTOFFSET)); } if (c == ']') { //make sure we know when there are two ']' chars together if (context.StateTag == NOMATCH) { context.StateTag = SINGLE_BRACKET; } else { context.StateTag = DOUBLE_BRACKET; } } else if (c == '>' && context.StateTag == DOUBLE_BRACKET) { // if the ']]' is followed by a '>', the state has ended // so attach a node to the DOM and end the state var cdata = (XCData)context.Nodes.Pop(); cdata.End(context.Position + 1); if (context.BuildTree) { ((XContainer)context.Nodes.Peek()).AddChildNode(cdata); } return(Parent); } else { // not any part of a ']]>', so make sure matching is reset context.StateTag = NOMATCH; } return(null); }
public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback) { if (context.CurrentStateLength == 0) { context.Nodes.Push(new XProcessingInstruction(context.Position - QUESTION)); } if (c == '?') { if (context.StateTag == NOMATCH) { context.StateTag = QUESTION; return(null); } } else if (c == '>' && context.StateTag == QUESTION) { // if the '?' is followed by a '>', the state has ended // so attach a node to the DOM and end the state var xpi = (XProcessingInstruction)context.Nodes.Pop(); // at this point the position isn't incremented to include the '>' yet // so make sure to include the closing '>' in the span xpi.End(context.Position + 1); if (context.BuildTree) { ((XContainer)context.Nodes.Peek()).AddChildNode(xpi); } return(Parent); } else { context.StateTag = NOMATCH; } return(null); }
public static char?GetDelimiterChar(XmlParserContext context) => context.CurrentState is XmlAttributeValueState ? (context.StateTag & TagMask) switch
public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback) { var doc = context.Nodes.Peek() as XDocType; if (doc == null) { doc = new XDocType(context.Position - STARTOFFSET); context.Nodes.Push(doc); } if (!doc.RootElement.IsValid) { if (XmlChar.IsWhitespace(c)) { return(null); } else if (XmlChar.IsFirstNameChar(c)) { rollback = ""; return(nameState); } } else if (doc.PublicFpi == null) { if (context.StateTag == 0) { if (c == 's' || c == 'S') { context.StateTag = 1; return(null); } else if (c == 'p' || c == 'P') { context.StateTag = -1; return(null); } if (XmlChar.IsWhitespace(c)) { return(null); } } else if (Math.Abs(context.StateTag) < 6) { if (context.StateTag > 0) { if ("YSTEM"[context.StateTag - 1] == c || "ystem"[context.StateTag - 1] == c) { context.StateTag++; if (context.StateTag == 6) { context.StateTag = 0; doc.PublicFpi = ""; } return(null); } } else { int absState = Math.Abs(context.StateTag) - 1; if ("UBLIC"[absState] == c || "ublic"[absState] == c) { context.StateTag--; return(null); } } } else { if (context.KeywordBuilder.Length == 0) { if (XmlChar.IsWhitespace(c)) { return(null); } else if (c == '"') { context.KeywordBuilder.Append(c); return(null); } } else { if (c == '"') { context.KeywordBuilder.Remove(0, 1); doc.PublicFpi = context.KeywordBuilder.ToString(); context.KeywordBuilder.Length = 0; context.StateTag = 0; } else { context.KeywordBuilder.Append(c); } return(null); } } } else if (doc.Uri == null) { if (context.KeywordBuilder.Length == 0) { if (XmlChar.IsWhitespace(c)) { return(null); } else if (c == '"') { context.KeywordBuilder.Append(c); return(null); } } else { if (c == '"') { context.KeywordBuilder.Remove(0, 1); doc.Uri = context.KeywordBuilder.ToString(); context.KeywordBuilder.Length = 0; } else { context.KeywordBuilder.Append(c); } return(null); } } else if (doc.InternalDeclarationRegion.Length == 0) { if (XmlChar.IsWhitespace(c)) { return(null); } switch (context.StateTag) { case 0: if (c == '[') { doc.InternalDeclarationRegion = new TextSpan(context.Position + 1, 0); context.StateTag = 1; return(null); } break; case 1: if (c == '<') { context.StateTag = 2; return(null); } else if (c == ']') { context.StateTag = 0; doc.InternalDeclarationRegion = TextSpan.FromBounds(doc.InternalDeclarationRegion.Start, context.Position); return(null); } break; case 2: if (c == '>') { context.StateTag = 1; } return(null); default: throw new InvalidOperationException(); } } doc = (XDocType)context.Nodes.Pop(); if (c == '<') { rollback = string.Empty; context.Diagnostics?.LogError("Doctype ended prematurely.", context.Position); } else if (c != '>') { context.Diagnostics?.LogError("Unexpected character '" + c + "' in doctype.", context.Position); } doc.End(context.Position); if (context.BuildTree) { ((XContainer)context.Nodes.Peek()).AddChildNode(doc); } return(Parent); }
protected XmlParser(XmlParserContext context, XmlRootState rootState) { Context = context; RootState = rootState; }
public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback) { var element = context.Nodes.Peek() as XElement; if (element == null || element.IsEnded) { var parent = element; element = new XElement(context.Position - STARTOFFSET) { Parent = parent }; 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.Diagnostics?.LogError("Unexpected '<' in tag '" + element.Name.FullName + "'.", context.Position); Close(element, context, context.Position); } else { context.Diagnostics?.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.Diagnostics?.LogWarning("Unexpected whitespace after '/' in self-closing tag.", context.Position); return(null); } context.Diagnostics?.LogError("Unexpected character '" + c + "' after '/' in self-closing tag.", context.Position); 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.Diagnostics?.LogError("Tag closed prematurely.", context.Position); element.End(context.Position + 1); } else { Close(element, context, context.Position + 1); } 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 > 0 && 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.Diagnostics?.LogError($"Unexpected character '{c}' in tag.", context.Position - 1); context.StateTag = ATTEMPT_RECOVERY; return(null); }
public static bool IsFree(XmlParserContext context) => context.CurrentState is XmlTagState && context.StateTag == FREE;