/// <summary> /// Main method to parse for offsets. /// </summary> /// <remarks> /// This may be called recursively, but is designed to do a single loop parse (O)N /// </remarks> /// <param name="markup"></param> /// <param name="context"></param> /// <returns></returns> private OffsetItem ParseOffsets(string markup, ParseContext context, XmlReader reader) { if (String.IsNullOrEmpty(markup)) { return(null); } TracePosition trace = CreateTracePosition(context); while (reader.Read()) { //skip declaration if (XmlNodeType.XmlDeclaration == reader.NodeType || XmlNodeType.Whitespace == reader.NodeType) { continue; } this.HandleContextParse(reader, markup, trace); continue; } return(trace.RootOffset); }
private TracePosition CreateTracePosition(ParseContext context) { TracePosition trace = new TracePosition(); trace.ParseContextStack.Push(context); // trace.RootOffset = MyControlFactory.CreateRootOffset(context); return(trace); }
/// <summary> /// Adjusts the trace object to ascend back up the parsing tree, /// since this is the closing element for the current section. /// </summary> /// <param name="markup"></param> /// <param name="trace"></param> private void SetAscendTraceTree(string markup, TracePosition trace, bool isContextClose) { OffsetItem tmpOffset; int endPos = GetEndOfTagPosition(markup, trace.CurrentPosition); tmpOffset = trace.CurrentOffset; //move to content block trace.CurrentOffset = trace.CurrentOffset.ParentOffset; trace.ContainerTagStack.Pop(); if (isContextClose) { trace.ParseContextStack.Pop(); } tmpOffset.EndPosition = trace.GetLocalPosition(endPos); //advance CurrentPosition trace.CurrentPosition = endPos; }
/// <summary> /// Handle processing within markup contexts consisting only of defined-tag context. /// For processing markup which may contain custom tag templates or recognizes Literal sections, /// use the method <c>HandleOsContainerTagParse</c>. /// </summary> /// <param name="reader"></param> /// <param name="markup"></param> /// <param name="trace"></param> private void HandleContextParse(XmlReader reader, string markup, TracePosition trace) { bool isStartElement = (XmlNodeType.Element == reader.NodeType); bool isEndElement = (XmlNodeType.EndElement == reader.NodeType); if (XmlNodeType.Whitespace == reader.NodeType) { return; } TraceContainerTagInfo containerInfo = trace.GetCurrentContainerTag(); Type t = typeof(GadgetLiteral); //default control type for current tag if (isStartElement || isEndElement) { //if null tag, this is in a ContentBlock ?? //if (String.IsNullOrEmpty(containerInfo.Tag)) //{ // containerInfo.Tag = "Content"; //} if (isEndElement) { int prevCurrentPosition = trace.CurrentPosition; trace.CurrentPosition = markup.IndexOf("</" + reader.Name, trace.CurrentPosition); if (prevCurrentPosition == trace.CurrentPosition && !trace.PriorLoopWasStartElement && reader.Name == trace.PreviousEndTag) { trace.CurrentPosition = markup.IndexOf("</" + reader.Name, trace.CurrentPosition + 1); } trace.PreviousStartTag = null; trace.PriorLoopWasStartElement = false; trace.PreviousEndTag = reader.Name; //check for non-container tag if (trace.InNonContainerControl) { if (reader.Name == trace.CurrentNonContainerTagInfo.Tag && reader.Depth == trace.CurrentNonContainerTagInfo.NodeDepth) { trace.CurrentPosition = GetEndOfTagPosition(markup, trace.CurrentPosition); trace.FlushNonContainerTagOffset(); return; } else { return; } } ControlMap curMap; if (trace.IsInitialized()) { curMap = MyControlFactory.GetControlMap(trace.CurrentOffset.OffsetKey); } else { //special case for CustomTag parsing //Add in a missing context and container if (trace.InStaticTag && trace.StaticTagStartPosition == 0) { trace.StaticTagStartPosition = GetEndOfTagPosition(markup, 0); } trace.AddChildOffset(0, MyControlFactory.GetContextGroupOffsetKey(trace.Context)); //push first element as container tag, if empty if (null == containerInfo.Tag) { trace.AddCurrentNodeAsContainerTag(ControlFactory.GetTagName(markup), 0); containerInfo = trace.GetCurrentContainerTag(); } //this is questionable //curMap = MyControlFactory.GetControlMap(GadgetLiteral.DefaultOffsetKey); curMap = MyControlFactory.GetControlMap(t); } if (reader.Name == containerInfo.Tag && reader.Depth == containerInfo.NodeDepth) { //if (AllowLiteralTags(trace.Context)) //{ //check for final static tag if (trace.InStaticTag) { trace.FlushLiteralControlOffset(); } // } //set closing position SetAscendTraceTree(markup, trace, curMap.IsContextGroupContainer); return; } else if (MyControlFactory.AllowCustomTags(trace.Context) && IsCustomTagDefined(reader.Name)) { //handle closing custom tag so it isn't interpreted as a static t = typeof(CustomTag); } else { //advance to end of current close tag to handle final static script tag //we're in a nested tag that is a static, but the same as the container tag //watch to make sure this is not in error if (reader.Name == containerInfo.Tag) { trace.CurrentPosition = GetEndOfTagPosition(markup, trace.CurrentPosition); } } } else if (isStartElement) { int prevCurrentPosition = trace.CurrentPosition; trace.CurrentPosition = markup.IndexOf("<" + reader.Name, trace.CurrentPosition); if (prevCurrentPosition == trace.CurrentPosition && trace.PriorLoopWasStartElement && reader.Name == trace.PreviousStartTag) { trace.CurrentPosition = markup.IndexOf("<" + reader.Name, trace.CurrentPosition + 1); } trace.PreviousStartTag = reader.Name; trace.PriorLoopWasStartElement = true; trace.PreviousEndTag = null; if (trace.InNonContainerControl) { return; } string fullTag = markup.Substring(trace.CurrentPosition, GetEndOfTagPosition(markup, trace.CurrentPosition) - trace.CurrentPosition); t = MyControlFactory.GetControlType(fullTag, trace.Context); //if custom tag, register it if (ControlFactory.InheritsFromType(t, typeof(CustomTagTemplate))) { string custTag = ControlFactory.GetTagAttributeValue(fullTag, CustomTagTemplate.ATTRIBUTE_TAGDEF); RegisterCustomTag(custTag); } //Look for a custom tag if it is a literal. Then continue or exit if (t == typeof(GadgetLiteral)) { if (MyControlFactory.AllowCustomTags(trace.Context)) { if (IsCustomTagDefined(reader.Name)) { t = typeof(CustomTag); } } if (!MyControlFactory.AllowLiteralTags(trace.Context) && t != typeof(CustomTag)) { return; } } //Look for a non-container control and set value, if required if (t != typeof(GadgetLiteral)) { if (!ControlFactory.InheritsFromType(t, typeof(BaseContainerControl)) && !trace.InNonContainerControl && !reader.IsEmptyElement) { trace.SetCurrentNodeAsNonContainerTag(reader.Name, reader.Depth, MyControlFactory.GetOffsetKey(t, trace.Context)); return; } else if (trace.InStaticTag) //Flush a pending static tag { trace.FlushLiteralControlOffset(); } OffsetItem tempOffset = trace.AddChildOffset(trace.GetLocalPosition(), MyControlFactory.GetOffsetKey(t, trace.Context)); trace.CurrentPosition = GetEndOfTagPosition(markup, trace.CurrentPosition); if (reader.IsEmptyElement) { tempOffset.EndPosition = (trace.GetLocalPosition()); trace.PreviousStartTag = null; trace.PriorLoopWasStartElement = false; } else { //check to see if we're moving into a new context ControlMap curMap = MyControlFactory.GetControlMap(tempOffset.OffsetKey); if (curMap.IsContextGroupContainer) { if (trace.Context.ContainerControlType != curMap.ControlType) { trace.ParseContextStack.Push(new ParseContext(curMap.ControlType)); } //push current as container tag, if empty trace.AddCurrentNodeAsContainerTag(reader.Name, reader.Depth); } else if (ControlFactory.InheritsFromType(curMap.ControlType, typeof(BaseContainerControl))) { trace.AddCurrentNodeAsContainerTag(reader.Name, reader.Depth); } } } } } else { trace.PreviousEndTag = null; trace.PreviousStartTag = null; trace.PriorLoopWasStartElement = false; } //Look for non-container controls if (trace.InNonContainerControl) { return; } //Look for static elements if (!MyControlFactory.AllowLiteralTags(trace.Context)) { return; } else if (t == typeof(GadgetLiteral)) { if (!trace.InStaticTag) { trace.StaticTagStartPosition = trace.CurrentPosition; trace.InStaticTag = true; } return; } }