protected void ProcessTag(Tag tag) { string name = tag.Name.ToLowerInvariant(); switch (name) { case "template": // skip those, because those are processed first break; case "else": ProcessElements(tag.InnerElements); break; case "apply": object val = EvalExpression(tag.AttributeValue("template")); ProcessTemplate(val.ToString(), tag); break; case "foreach": ProcessForEach(tag); break; default: ProcessTemplate(tag.Name, tag); break; } }
private Tag CollectForTag(Tag tag, ref int index) { if (tag.IsClosed) // if self-closing tag, do not collect inner elements { return tag; } if (string.Compare(tag.Name, "if", true) == 0) { tag = new TagIf(tag.Line, tag.Col, tag.AttributeValue("test")); } Tag collectTag = tag; for (index++; index < elements.Count; index++) { Element elem = elements[index]; if (elem is Text) collectTag.InnerElements.Add(elem); else if (elem is Expression) collectTag.InnerElements.Add(elem); else if (elem is Tag) { Tag innerTag = (Tag)elem; if (string.Compare(innerTag.Name, "else", true) == 0) { if (collectTag is TagIf) { ((TagIf)collectTag).FalseBranch = innerTag; collectTag = innerTag; } else throw new ParseException("else tag has to be positioned inside of if or elseif tag", innerTag.Line, innerTag.Col); } else if (string.Compare(innerTag.Name, "elseif", true) == 0) { if (collectTag is TagIf) { Tag newTag = new TagIf(innerTag.Line, innerTag.Col, innerTag.AttributeValue("test")); ((TagIf)collectTag).FalseBranch = newTag; collectTag = newTag; } else throw new ParseException("elseif tag is not positioned properly", innerTag.Line, innerTag.Col); } else collectTag.InnerElements.Add(CollectForTag(innerTag, ref index)); } else if (elem is TagClose) { TagClose tagClose = (TagClose)elem; if (string.Compare(tag.Name, tagClose.Name, true) == 0) return tag; throw new ParseException("Close tag for " + tagClose.Name + " doesn't have matching start tag.", elem.Line, elem.Col); } else throw new ParseException("Invalid element: " + elem.GetType().ToString(), elem.Line, elem.Col); } throw new ParseException("Start tag: " + tag.Name + " does not have matching end tag.", tag.Line, tag.Col); }
protected void ProcessForEach(Tag tag) { Expression expCollection = tag.AttributeValue("collection"); if (expCollection == null) { WriteError("Foreach is missing required attribute: collection", tag.Line, tag.Col); return; } object collection = EvalExpression(expCollection); if (!(collection is IEnumerable)) { WriteError("Collection used in foreach has to be enumerable", tag.Line, tag.Col); return; } Expression expVar = tag.AttributeValue("var"); if (expCollection == null) { WriteError("Foreach is missing required attribute: var", tag.Line, tag.Col); return; } object varObject = EvalExpression(expVar); if (varObject == null) varObject = "foreach"; string varname = varObject.ToString(); Expression expIndex = tag.AttributeValue("index"); string indexname = null; if (expIndex != null) { object obj = EvalExpression(expIndex); if (obj != null) indexname = obj.ToString(); } IEnumerator ienum = ((IEnumerable)collection).GetEnumerator(); int index = 0; while (ienum.MoveNext()) { index++; object value = ienum.Current; _variables[varname] = value; if (indexname != null) _variables[indexname] = index; ProcessElements(tag.InnerElements); } }