private static void ResolveDocument(IDictionary<string, object> arguments, XmlDocument templateDocument, TemplateParsingState templateParsingState) { templateParsingState.OnDocumentLoaded(arguments, templateDocument.FirstChild as XmlElement); bool continueResolving; XmlNodeChangedEventHandler documentChanged = delegate(object sender, XmlNodeChangedEventArgs e) { continueResolving = true; }; templateDocument.NodeChanged += documentChanged; templateDocument.NodeInserted += documentChanged; templateDocument.NodeRemoved += documentChanged; // Keep resolving oc:if, oc:component, oc:script, and oc:css tags while they're loaded int loopsLeft = 20; do { int innerLoopsLeft = 20; do { continueResolving = false; foreach (XmlElement element in templateParsingState.IterateNonDeferredElements(templateDocument)) try { templateParsingState.OnProcessElementForConditionalsAndComponents(arguments, element); } catch (Exception e) { log.Error("An error occured while processing " + element.OuterXml, e); templateParsingState.ReplaceNodes( element, templateParsingState.GenerateWarningNode("An error occured processing " + element.OuterXml)); } innerLoopsLeft--; } while (continueResolving && (innerLoopsLeft > 0)); foreach (XmlElement element in templateParsingState.IterateNonDeferredElements(templateDocument)) try { templateParsingState.OnProcessElementForDependanciesAndTemplates(arguments, element); } catch (Exception e) { log.Error("An error occured while processing " + element.OuterXml, e); templateParsingState.ReplaceNodes( element, templateParsingState.GenerateWarningNode("An error occured processing " + element.OuterXml)); } loopsLeft--; } while (continueResolving && (loopsLeft > 0)); templateDocument.NodeChanged -= documentChanged; templateDocument.NodeInserted -= documentChanged; templateDocument.NodeRemoved -= documentChanged; }