Esempio n. 1
0
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            var namedObject = context.Nodes.Peek() as INamedXObject;

            if (namedObject == null || namedObject.Name.Prefix != null)
            {
                throw new InvalidOperationException("Invalid state");
            }

            Debug.Assert(context.CurrentStateLength > 0 || IsValidNameStart(c),
                         "First character pushed to a XmlTagNameState must be a letter.");
            Debug.Assert(context.CurrentStateLength > 0 || context.KeywordBuilder.Length == 0,
                         "Keyword builder must be empty when state begins.");

            if (XmlChar.IsWhitespace(c) || c == '<' || c == '>' || c == '/' || c == '=')
            {
                rollback = string.Empty;
                if (context.KeywordBuilder.Length == 0)
                {
                    context.Diagnostics?.LogError("Zero-length name.", context.Position);
                    namedObject.Name = XName.Empty;
                }
                else
                {
                    string s = context.KeywordBuilder.ToString();
                    int    i = s.IndexOf(':');
                    if (i < 0)
                    {
                        namedObject.Name = s;
                    }
                    else
                    {
                        namedObject.Name = new XName(s.Substring(0, i), s.Substring(i + 1));
                    }
                }

                return(Parent);
            }
            if (c == ':')
            {
                if (context.KeywordBuilder.ToString().IndexOf(':') > 0 && context.BuildTree)
                {
                    context.Diagnostics?.LogError("Unexpected ':' in name.", context.Position);
                }
                context.KeywordBuilder.Append(c);
                return(null);
            }

            if (XmlChar.IsNameChar(c))
            {
                context.KeywordBuilder.Append(c);
                return(null);
            }

            rollback = string.Empty;
            context.Diagnostics?.LogError($"Unexpected character '{c}' in name", context.Position);
            return(Parent);
        }
        /// <summary>
        /// Gets the XML name at the parser's position.
        /// </summary>
        /// <param name="spine">A spine parser. It will not be modified.</param>
        /// <param name="text">The text snapshot corresponding to the parser.</param>
        /// <returns></returns>
        public static XName GetCompleteName(this XmlSpineParser spine, ITextSource text, int maximumReadahead = DEFAULT_READAHEAD_LIMIT)
        {
            Debug.Assert(spine.CurrentState is XmlNameState);

            int end   = spine.Position;
            int start = end - spine.CurrentStateLength;
            int mid   = -1;

            int limit = Math.Min(text.Length, end + maximumReadahead);

            //try to find the end of the name, but don't go too far
            for (; end < limit; end++)
            {
                char c = text[end];

                if (c == ':')
                {
                    if (mid == -1)
                    {
                        mid = end;
                    }
                    else
                    {
                        break;
                    }
                }
                else if (!XmlChar.IsNameChar(c))
                {
                    break;
                }
            }

            if (mid > 0 && end > mid + 1)
            {
                return(new XName(text.GetText(start, mid - start), text.GetText(mid + 1, end - mid - 1)));
            }
            return(new XName(text.GetText(start, end - start)));
        }