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); }