예제 #1
0
 internal XmlTreeParser(XmlSpineParser fromSpine)
     : base(fromSpine.GetContext().ShallowCopy(), fromSpine.RootState)
 {
     Context.BuildTree = true;
     Context.ConnectNodes();
     Context.Diagnostics = new List <XmlDiagnosticInfo> ();
 }
        /// <summary>
        /// Advances the parser to end the node at the current position and gets that node's path.
        /// </summary>
        /// <param name="parser">A spine parser. Its state will be modified.</param>
        /// <param name="text">The text snapshot corresponding to the parser.</param>
        /// <returns></returns>
        public static List <XObject> AdvanceToNodeEndAndGetNodePath(this XmlSpineParser parser, ITextSource text, int maximumReadahead = DEFAULT_READAHEAD_LIMIT)
        {
            var context = parser.GetContext();

            int startOffset = parser.Position;
            int startDepth  = parser.Spine.Count;

            //if in potential start of a state, advance into the next state
            var end = Math.Min(text.Length - context.Position, maximumReadahead) + context.Position;

            if (parser.Position < end && (XmlRootState.IsNotFree(context) || (context.CurrentState is XmlRootState && text[parser.Position] == '<')))
            {
                do
                {
                    parser.Push(text[parser.Position]);
                } while (parser.Position < end && XmlRootState.IsNotFree(context));

                //if it transitioned to another state, eat until we get a new node on the stack
                if (parser.Position < end && !(context.CurrentState is XmlRootState) && context.Nodes.Count <= startDepth)
                {
                    parser.Push(text[parser.Position]);
                }
            }

            var path = parser.Spine.ToNodePath();

            // make sure the leaf node is ended
            if (path.Count > 0)
            {
                var leaf = path[path.Count - 1];
                if (!(leaf is XDocument))
                {
                    AdvanceUntilEnded(parser, leaf, text, maximumReadahead - (parser.Position - startOffset));
                }
                //the leaf node might have a child that's a better match for the offset
                if (leaf is XContainer c && c.FindAtOffset(startOffset) is XObject o)
                {
                    path.Add(o);
                }
            }

            return(path);
        }