public bool TryProcess(IDocumentProcessor docProcessor, XmlNode node, bool isRoot, ITemplate template, IRenderFunction currentRenderFunction) {
			if (node.NodeType != XmlNodeType.Element)
				return false;

			GenericElementProcessorContext context = new GenericElementProcessorContext();

			currentRenderFunction.AddFragment(new LiteralFragment("<" + node.Name));
			AddAttributeFragments(docProcessor, node, isRoot, template, currentRenderFunction, context);

			if (context.Id != null) {
				string tagName = node.Name;
				if (tagName.ToLowerCase() == "input" && context.Type != null)
					tagName += "/" + context.Type;
				template.AddMember(new NamedElementMember(tagName, context.Id));
			}

			if (noContentTags.Contains(node.Name)) {
				if (Utils.GetNumChildNodes(node) > 0)
					throw ParserUtils.TemplateErrorException("The tag " + node.Name + " can not have children.");
				currentRenderFunction.AddFragment(new LiteralFragment("/>"));
			}
			else {
				currentRenderFunction.AddFragment(new LiteralFragment(">"));
				Utils.DoForEachChild(node, delegate(XmlNode child) {
					docProcessor.ProcessRecursive(child, template, currentRenderFunction);
				});
				currentRenderFunction.AddFragment(new LiteralFragment("</" + node.Name + ">"));
			}

			return true;
		}
		public void TestAddSingleAttributeFragments_StyleInNonRootIsNotModified() {
			Expect.Call(docProcessor.ParseUntypedMarkup("width: 0px")).Return(new LiteralFragment("width: 0px"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "style", "width: 0px", false, template, renderFunction, context);
			Assert.AreEqual(" style=\"width: 0px\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}
		public void TestAddSingleAttributeFragments_StyleInRootAppendsSemicolonIfNonLiteralFragmentIsReturned() {
			Expect.Call(docProcessor.ParseUntypedMarkup("code")).Return(new CodeExpressionFragment("code"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "style", "code", true, template, renderFunction, context);
			Assert.AreEqual(" style=\"[EXPR:code];[Position]\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}
		public void TestAddSingleAttributeFragments_StyleInRootAppendsSemicolonIfOneIsMissing() {
			Expect.Call(docProcessor.ParseUntypedMarkup("width: 0px")).Return(new LiteralFragment("width: 0px"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "style", "width: 0px", true, template, renderFunction, context);
			Assert.AreEqual(" style=\"width: 0px;[Position]\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}
		public void TestAddSingleAttributeFragments_SimpleNameValuePairWorks() {
			Expect.Call(docProcessor.ParseUntypedMarkup("test\"Value\"")).Return(new LiteralFragment("test&quot;Value&quot;"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "testName", "test\"Value\"", false, template, renderFunction, context);
			Assert.AreEqual(" testName=\"test&quot;Value&quot;\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}
		public void TestAddSingleAttributeFragments_IdForNonRootElementWorks() {
			Expect.Call(template.HasMember("testid")).Return(false);
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "id", "testid", false, template, renderFunction, context);
			Assert.AreEqual(" id=\"[ID]_testid\"", ConcatenatedFragments);
			Assert.AreEqual("testid", context.Id);
			mocks.VerifyAll();
		}
		internal static void AddAttributeFragments(IDocumentProcessor docProcessor, XmlNode node, bool isRoot, ITemplate template, IRenderFunction fragments, GenericElementProcessorContext context) {
			bool hasStyle = false;
			Utils.DoForEachAttribute(node, delegate(XmlAttribute attr) {
				AddSingleAttributeFragments(docProcessor, attr.Name, attr.Value, isRoot, template, fragments, context);
				if (attr.Name == "style")
					hasStyle = true;
			});

			if (isRoot) {
				fragments.AddFragment(new LiteralFragment(" id=\""));
				fragments.AddFragment(new IdFragment());
				fragments.AddFragment(new LiteralFragment("\""));
				if (!hasStyle) {
					fragments.AddFragment(new LiteralFragment(" style=\""));
					fragments.AddFragment(new PositionFragment());
					fragments.AddFragment(new LiteralFragment("\""));
				}
			}
		}
        public bool TryProcess(IDocumentProcessor docProcessor, XmlNode node, bool isRoot, ITemplate template, IRenderFunction currentRenderFunction)
        {
            if (node.NodeType != XmlNodeType.Element)
            {
                return(false);
            }

            GenericElementProcessorContext context = new GenericElementProcessorContext();

            currentRenderFunction.AddFragment(new LiteralFragment("<" + node.Name));
            AddAttributeFragments(docProcessor, node, isRoot, template, currentRenderFunction, context);

            if (context.Id != null)
            {
                string tagName = node.Name;
                if (tagName.ToLowerCase() == "input" && context.Type != null)
                {
                    tagName += "/" + context.Type;
                }
                template.AddMember(new NamedElementMember(tagName, context.Id));
            }

            if (noContentTags.Contains(node.Name))
            {
                if (Utils.GetNumChildNodes(node) > 0)
                {
                    throw ParserUtils.TemplateErrorException("The tag " + node.Name + " can not have children.");
                }
                currentRenderFunction.AddFragment(new LiteralFragment("/>"));
            }
            else
            {
                currentRenderFunction.AddFragment(new LiteralFragment(">"));
                Utils.DoForEachChild(node, delegate(XmlNode child) {
                    docProcessor.ProcessRecursive(child, template, currentRenderFunction);
                });
                currentRenderFunction.AddFragment(new LiteralFragment("</" + node.Name + ">"));
            }

            return(true);
        }
		internal static void AddSingleAttributeFragments(IDocumentProcessor docProcessor, string attrName, string attrValue, bool isRoot, ITemplate template, IRenderFunction fragments, GenericElementProcessorContext context) {
			string actualName;
			if (attrName == "actualName") {
				// This will translate into "name", but not with our ID prefixed. We need this because for top-level templates we want the names undisturbed to allow for a nice form submission.
				// However, for nested forms which we won't submit using the normal techniques, we need to prefix it in order to make radio buttons work reliably.
				actualName = "name";
			}
			else
				actualName = attrName;
			
			fragments.AddFragment(new LiteralFragment(" " + actualName + "=\""));
			if (attrName == "id") {
				if (isRoot)
					throw ParserUtils.TemplateErrorException("Can't specify an ID for the top level element.");
				if (template.HasMember(attrValue))
					throw ParserUtils.TemplateErrorException("Duplicate member " + attrValue);
				context.Id = attrValue;

				fragments.AddFragment(new IdFragment());
				fragments.AddFragment(new LiteralFragment("_" + attrValue));
			}
			else if (attrName.ToLowerCase() == "for" || attrName.ToLowerCase() == "name") {
				fragments.AddFragment(new IdFragment());
				fragments.AddFragment(new LiteralFragment("_" + attrValue));
			}
			else {
				IFragment f = docProcessor.ParseUntypedMarkup(attrValue);
				fragments.AddFragment(f);
				if (attrName.ToLowerCase() == "type") {
					if (f is LiteralFragment)
						context.Type = ((LiteralFragment)f).Text;
				}
				else if (isRoot && attrName.ToLowerCase() == "style") {
					if (!(f is LiteralFragment) || !((LiteralFragment)f).Text.Trim().EndsWith(";"))
						fragments.AddFragment(new LiteralFragment(";"));
					fragments.AddFragment(new PositionFragment());
				}
			}

			fragments.AddFragment(new LiteralFragment("\""));
		}
		public void TestAddSingleAttributeFragments_IdForRootElementThrowsException() {
			var context = new GenericElementProcessorContext();
			Globals.AssertThrows(() => GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "id", "testid", true, template, renderFunction, context), (TemplateErrorException ex) => true);
		}
		public void TestAddAttributeFragments_RootAddsPositionAndStyle() {
			Expect.Call(docProcessor.ParseUntypedMarkup("val1")).Return(new LiteralFragment("val1"));
			Expect.Call(docProcessor.ParseUntypedMarkup("val2")).Return(new LiteralFragment("val2"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddAttributeFragments(docProcessor, Globals.GetXmlNode("<x attr1=\"val1\" attr2=\"val2\"/>"), true, template, renderFunction, context);
			Assert.AreEqual(" attr1=\"val1\" attr2=\"val2\" id=\"[ID]\" style=\"[Position]\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}
		public void TestAddSingleAttributeFragments_ErrorIfDuplicateMember() {
			Expect.Call(template.HasMember("ExistingMember")).Return(true);
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			Globals.AssertThrows(() => GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "id", "ExistingMember", false, template, renderFunction, context), (TemplateErrorException ex) => true);
			mocks.VerifyAll();
		}
		public void TestAddSingleAttributeFragments_ActualNameWorks() {
			Expect.Call(docProcessor.ParseUntypedMarkup("SomeName")).Return(new LiteralFragment("SomeName"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "actualName", "SomeName", false, template, renderFunction, context);
			Assert.AreEqual(" name=\"SomeName\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}
        internal static void AddAttributeFragments(IDocumentProcessor docProcessor, XmlNode node, bool isRoot, ITemplate template, IRenderFunction fragments, GenericElementProcessorContext context)
        {
            bool hasStyle = false;

            Utils.DoForEachAttribute(node, delegate(XmlAttribute attr) {
                AddSingleAttributeFragments(docProcessor, attr.Name, attr.Value, isRoot, template, fragments, context);
                if (attr.Name == "style")
                {
                    hasStyle = true;
                }
            });

            if (isRoot)
            {
                fragments.AddFragment(new LiteralFragment(" id=\""));
                fragments.AddFragment(new IdFragment());
                fragments.AddFragment(new LiteralFragment("\""));
                if (!hasStyle)
                {
                    fragments.AddFragment(new LiteralFragment(" style=\""));
                    fragments.AddFragment(new PositionFragment());
                    fragments.AddFragment(new LiteralFragment("\""));
                }
            }
        }
        internal static void AddSingleAttributeFragments(IDocumentProcessor docProcessor, string attrName, string attrValue, bool isRoot, ITemplate template, IRenderFunction fragments, GenericElementProcessorContext context)
        {
            string actualName;

            if (attrName == "actualName")
            {
                // This will translate into "name", but not with our ID prefixed. We need this because for top-level templates we want the names undisturbed to allow for a nice form submission.
                // However, for nested forms which we won't submit using the normal techniques, we need to prefix it in order to make radio buttons work reliably.
                actualName = "name";
            }
            else
            {
                actualName = attrName;
            }

            fragments.AddFragment(new LiteralFragment(" " + actualName + "=\""));
            if (attrName == "id")
            {
                if (isRoot)
                {
                    throw ParserUtils.TemplateErrorException("Can't specify an ID for the top level element.");
                }
                if (template.HasMember(attrValue))
                {
                    throw ParserUtils.TemplateErrorException("Duplicate member " + attrValue);
                }
                context.Id = attrValue;

                fragments.AddFragment(new IdFragment());
                fragments.AddFragment(new LiteralFragment("_" + attrValue));
            }
            else if (attrName.ToLowerCase() == "for" || attrName.ToLowerCase() == "name")
            {
                fragments.AddFragment(new IdFragment());
                fragments.AddFragment(new LiteralFragment("_" + attrValue));
            }
            else
            {
                IFragment f = docProcessor.ParseUntypedMarkup(attrValue);
                fragments.AddFragment(f);
                if (attrName.ToLowerCase() == "type")
                {
                    if (f is LiteralFragment)
                    {
                        context.Type = ((LiteralFragment)f).Text;
                    }
                }
                else if (isRoot && attrName.ToLowerCase() == "style")
                {
                    if (!(f is LiteralFragment) || !((LiteralFragment)f).Text.Trim().EndsWith(";"))
                    {
                        fragments.AddFragment(new LiteralFragment(";"));
                    }
                    fragments.AddFragment(new PositionFragment());
                }
            }

            fragments.AddFragment(new LiteralFragment("\""));
        }
		public void TestAddSingleAttributeFragments_ForAndNameAttributesWorks() {
			foreach (var attrName in new[] { "for", "name" }) {
				SetupRepo();
				mocks.ReplayAll();
				var context = new GenericElementProcessorContext();
				GenericElementProcessor.AddSingleAttributeFragments(docProcessor, attrName, "TestValue", false, template, renderFunction, context);
				Assert.AreEqual(" " + attrName + "=\"[ID]_TestValue\"", ConcatenatedFragments);
				mocks.VerifyAll();
			}
		}
		public void TestAddSingleAttributeFragments_TypeAttributeWorks() {
			SetupRepo();
			Expect.Call(docProcessor.ParseUntypedMarkup("TestValue")).Return(new LiteralFragment("TestValue"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddSingleAttributeFragments(docProcessor, "type", "TestValue", false, template, renderFunction, context);
			Assert.AreEqual(" type=\"TestValue\"", ConcatenatedFragments);
			Assert.AreEqual("TestValue", context.Type);
			mocks.VerifyAll();
		}
		public void TestAddAttributeFragments_StyleIsNotAddedIfExists() {
			Expect.Call(docProcessor.ParseUntypedMarkup("a: b")).Return(new LiteralFragment("a: b"));
			mocks.ReplayAll();
			var context = new GenericElementProcessorContext();
			GenericElementProcessor.AddAttributeFragments(docProcessor, Globals.GetXmlNode("<x style=\"a: b\"/>"), true, template, renderFunction, context);
			Assert.AreEqual(" style=\"a: b;[Position]\" id=\"[ID]\"", ConcatenatedFragments);
			mocks.VerifyAll();
		}