public void TestNextElementWithUpTransition() { var firstParagraph = new XElement("FirstParagraph"); var fpElement1 = new XElement("FPElement1"); var fpElementStart = new XElement("FPElementStart"); var fpElement3 = new XElement("FPElement3"); firstParagraph.Add(fpElement1, fpElementStart, fpElement3); var betweenParagraph = new XElement("BetweenParagraph"); var bpElement1 = new XElement("BPElement1"); var bpElement2 = new XElement("BPElement2"); betweenParagraph.Add(bpElement1, bpElement2); var lastParagraph = new XElement("LastParagraph"); var lpElement1 = new XElement("LPElement1"); var lpElementEnd = new XElement("LPElementEnd"); var lpElement3 = new XElement("LpElementThree"); lastParagraph.Add(lpElement1, lpElementEnd, lpElement3); var expectedDoc = new XDocument(new XElement("Root")); expectedDoc.Root.Add(firstParagraph, betweenParagraph, lastParagraph); var actualBetweenElements = TraverseUtils.SecondElementsBetween(fpElementStart, lpElementEnd); var nextElement = actualBetweenElements.First().NextElementWithUpTransition(); Assert.AreSame(nextElement, betweenParagraph); }
public void TestElementsBetweenStartElementInNestedElement() { var startParagraph = new XElement("startParagraph"); var firstElement = new XElement("elementFirst"); var startElement = new XElement("elementStart"); var thirdElement = new XElement("elementThird"); var fourthElement = new XElement("elementFourth"); startParagraph.Add(firstElement, startElement, thirdElement, fourthElement); var outerFirstElement = new XElement("outerElementFirst"); var outerSecondElement = new XElement("outerElementSecond"); var outerEndElement = new XElement("outerElementEnd"); var outerFourthElement = new XElement("outerElementFourth"); var expectedDoc = new XDocument(new XElement("Root")); expectedDoc.Root.Add(startParagraph, outerFirstElement, outerSecondElement, outerEndElement, outerFourthElement); var actualBetweenElements = TraverseUtils.SecondElementsBetween(startElement, outerEndElement); foreach (var actualBetweenElement in actualBetweenElements) { Console.WriteLine(actualBetweenElement); } Assert.AreEqual(4, actualBetweenElements.Count()); }
public override void Process() { base.Process(); ProcessDynamicContent(); if (TableTag == null) { throw new NullReferenceException(); } var tableRows = TableTag.Table.Elements(WordMl.TableRowName); var dynamicRow = TableTag.DynamicRow.HasValue ? tableRows.ElementAt(TableTag.DynamicRow.Value - 1) : tableRows.Last(); ReplaceValues(dynamicRow); if (this.CreateDynamicContentTags) { var innerElements = TraverseUtils.ElementsBetween(this.TableTag.TagTable, this.TableTag.TagEndTable).ToList(); innerElements.Remove(); this.TableTag.TagTable.AddBeforeSelf(DocxHelper.CreateDynamicContentElement(innerElements, this.TableTag.TagTable, this.DynamicContentLockingType)); this.CleanUp(this.TableTag.TagTable, this.TableTag.TagEndTable); } else { RemoveTags(); } }
public void TestParseNullProcess() { var root = new XElement(this.documentRoot); var startElement = TraverseUtils.TagElement(root, "Table"); var parser = new TableParser(); parser.Parse(null, startElement); }
public void TestAnySdtInOtherParagraph() { var startIf = this.documentRoot.Descendants(WordMl.SdtName).Single(d => d.Descendants(WordMl.TagName).Any(t => t.Attribute(WordMl.ValAttributeName).Value == "If")); var endIf = this.documentRoot.Descendants(WordMl.SdtName).Single(d => d.Descendants(WordMl.TagName).Any(t => t.Attribute(WordMl.ValAttributeName).Value == "EndIf")); var endIfCollection = TraverseUtils.NextTagElements(startIf).ToList(); Assert.AreEqual(1, endIfCollection.Count()); Assert.AreEqual(endIf, endIfCollection[0]); }
public void TestParseMissingEndTableTag() { var processorMock = new TagProcessorMock <TableProcessor>(); var parser = new TableParser(); var root = new XElement(this.documentRoot); TraverseUtils.TagElement(root, "EndTable").Remove(); var startElement = TraverseUtils.TagElement(root, "Table"); parser.Parse(processorMock, startElement); }
private void ProcessDynamicContent() { var dynamicContentTags = TraverseUtils.ElementsBetween(this.Tag.StartIf, this.Tag.EndIf).Where(element => element.IsSdt()).ToList(); foreach (var dynamicContentTag in dynamicContentTags) { var innerElements = dynamicContentTag.Element(WordMl.SdtContentName).Elements(); dynamicContentTag.AddAfterSelf(innerElements); dynamicContentTag.Remove(); } }
private TableTag GetTableTag(XElement root) { XElement table = root.Element(WordMl.TableName); const string ItemsSource = "//Test/Certificates/Certificate"; int? dynamicRowValue = 4; return(new TableTag { Table = table, ItemsSource = ItemsSource, DynamicRow = dynamicRowValue, TagTable = TraverseUtils.TagElement(root, "Table"), TagEndTable = TraverseUtils.TagElement(root, "EndTable"), }); }
public static void AddEmptyParagraphInTableCell(XElement altChunkElement) { var rsidR = TraverseUtils.GenerateRandomRsidR(); var rsidRPrAttr = altChunkElement.Ancestors(WordMl.TableRowName) .First() .Attribute(WordMl.RsidRPropertiesName); var rsidRAttr = altChunkElement.Ancestors(WordMl.TableRowName) .First() .Attribute(WordMl.RsidRName); var rsidP = (rsidRPrAttr != null) ? rsidRPrAttr.Value : rsidRAttr.Value; altChunkElement.AddAfterSelf( new XElement(WordMl.ParagraphName, new XAttribute(WordMl.RsidRName, rsidR), new XAttribute(WordMl.RsidRPropertiesName, rsidR), new XAttribute(WordMl.RsidRDefaultName, rsidR), new XAttribute(WordMl.RsidPName, rsidP))); }
public void TestRepeaterNotClosed() { const string TagName = "EndRepeater"; var endRepeater = TraverseUtils.TagElement(this.documentRoot, TagName); endRepeater.Remove(); var parser = new RepeaterParser(); try { parser.Parse(new TagProcessorMock <RepeaterProcessor>(), this.documentRoot.Descendants(WordMl.SdtName).First()); Assert.Fail("An exception shoud've been thrown"); } catch (Exception e) { Assert.AreEqual(string.Format(MessageStrings.TagNotFoundOrEmpty, TagName), e.Message); } }
public void TestParseCplx() { using (var docStream = AssemblyResourceHelper.GetResourceStream(this, "document_dontworking_if.xml")) { var doc = XDocument.Load(docStream); var documentRoot = doc.Root.Element(WordMl.WordMlNamespace + "body"); var parser = new IfParser(); var startElement = TraverseUtils.TagElement(documentRoot, "If"); var endElement = TraverseUtils.TagElement(documentRoot, "EndIf"); var parentProcessor = new RootProcessor(); parser.Parse(parentProcessor, startElement); var ifProcessor = (IfProcessor)parentProcessor.Processors.First(); var ifTag = ifProcessor.Tag; const string IfCondition = "//test/condition"; Assert.IsNotNull(ifProcessor); //Assert.IsTrue(IfCondition.Equals(ifTag.Conidition)); CollectionAssert.AreEqual(Encoding.UTF8.GetBytes(IfCondition), Encoding.UTF8.GetBytes(ifTag.Conidition)); Assert.AreEqual(startElement, ifTag.StartIf); Assert.AreEqual(endElement, ifTag.EndIf); var elements = ifTag.IfContent.ToList(); Assert.AreEqual(1, elements.Count()); /* * Assert.IsTrue(elements.Take(6).All(e => e.Name.Equals(WordMl.TextRunName))); * Assert.IsTrue(elements.Skip(6).Take(1).All(e => e.Name.Equals(WordMl.ParagraphName))); * Assert.IsTrue(elements.Skip(7).Take(1).All(e => e.Name.Equals(WordMl.ParagraphPropertiesName))); * Assert.IsTrue(elements.Skip(8).Take(1).All(e => e.Name.Equals(WordMl.BookmarkStartName))); * Assert.IsTrue(elements.Skip(9).Take(4).All(e => e.Name.Equals(WordMl.TextRunName))); * Assert.IsTrue(elements.Skip(13).Take(1).All(e => e.Name.Equals(WordMl.ProofingErrorAnchorName))); * Assert.IsTrue(elements.Skip(14).Take(1).All(e => e.Name.Equals(WordMl.TextRunName))); * Assert.IsTrue(elements.Skip(15).Take(1).All(e => e.Name.Equals(WordMl.ProofingErrorAnchorName))); * Assert.IsTrue(elements.Skip(16).Take(1).All(e => e.Name.Equals(WordMl.TextRunName))); */ Assert.AreEqual(startElement, ifTag.StartIf); Assert.AreEqual(endElement, ifTag.EndIf); } }
public override void Process() { base.Process(); this.ProcessDynamicContent(); bool truthful; try { truthful = bool.Parse(this.DataReader.ReadText(this.Tag.Conidition)); } catch (System.FormatException) { truthful = false; } catch (System.Xml.XPath.XPathException) { truthful = false; } if (!truthful) { if (this.CreateDynamicContentTags) { this.Tag.StartIf.AddBeforeSelf(DocxHelper.CreateDynamicContentElement(Enumerable.Empty <XElement>(), this.Tag.StartIf, this.DynamicContentLockingType)); } this.CleanUp(this.Tag.StartIf, this.Tag.EndIf); } else { if (this.CreateDynamicContentTags) { var innerElements = TraverseUtils.ElementsBetween(this.Tag.StartIf, this.Tag.EndIf).ToList(); innerElements.Remove(); this.Tag.StartIf.AddBeforeSelf(DocxHelper.CreateDynamicContentElement(innerElements, this.Tag.StartIf, this.DynamicContentLockingType)); this.CleanUp(this.Tag.StartIf, this.Tag.EndIf); } else { this.Tag.StartIf.Remove(); this.Tag.EndIf.Remove(); } } }
public override void Process() { base.Process(); this.ProcessDynamicContent(); var current = RepeaterTag.StartRepeater; var dataReaders = DataReader.GetReaders(RepeaterTag.Source).ToList(); var repeaterElements = TraverseUtils.SecondElementsBetween(RepeaterTag.StartRepeater, RepeaterTag.EndRepeater) .Select(RepeaterTag.MakeElementCallback).ToList(); for (var index = 0; index < dataReaders.Count; index++) { XElement endIfElementTmp = null; XElement endRepeaterElementTmp = null; XElement endItemTableElement = null; current = this.ProcessElements(repeaterElements, dataReaders[index], current, null, index + 1, ref endIfElementTmp, ref endRepeaterElementTmp, ref endItemTableElement); } foreach (var repeaterElement in repeaterElements) { repeaterElement.XElement.Remove(); } if (this.CreateDynamicContentTags) { var innerElements = TraverseUtils.ElementsBetween(this.RepeaterTag.StartRepeater, this.RepeaterTag.EndRepeater).ToList(); innerElements.Remove(); this.RepeaterTag.StartRepeater.AddBeforeSelf( DocxHelper.CreateDynamicContentElement( innerElements, this.RepeaterTag.StartRepeater, this.DynamicContentLockingType)); this.CleanUp(this.RepeaterTag.StartRepeater, this.RepeaterTag.EndRepeater); } else { this.RepeaterTag.StartRepeater.Remove(); this.RepeaterTag.EndRepeater.Remove(); } }
public void TestParse() { using (var docStream = AssemblyResourceHelper.GetResourceStream(this, "IfParserTest.xml")) { var doc = XDocument.Load(docStream); var documentRoot = doc.Root.Element(WordMl.WordMlNamespace + "body"); var parser = new IfParser(); var startElement = TraverseUtils.TagElement(documentRoot, "If"); var endElement = TraverseUtils.TagElement(documentRoot, "EndIf"); var parentProcessor = new RootProcessor(); parser.Parse(parentProcessor, startElement); var ifProcessor = (IfProcessor)parentProcessor.Processors.First(); var ifTag = ifProcessor.Tag; const string IfCondition = "//test/condition"; Assert.IsNotNull(ifProcessor); Assert.AreEqual(IfCondition, ifTag.Conidition); var content = ifTag.IfContent.ToList(); Assert.AreEqual(1, content.Count); Assert.AreEqual(WordMl.ParagraphName, content[0].Name); var paragraphChildren = content[0].Elements().ToList(); Assert.AreEqual(6, paragraphChildren.Count()); Assert.AreEqual(WordMl.ParagraphPropertiesName, paragraphChildren[0].Name); Assert.AreEqual(WordMl.ProofingErrorAnchorName, paragraphChildren[1].Name); Assert.AreEqual(WordMl.TextRunName, paragraphChildren[2].Name); Assert.AreEqual("Hello", paragraphChildren[2].Value); Assert.AreEqual(WordMl.ProofingErrorAnchorName, paragraphChildren[3].Name); Assert.AreEqual(WordMl.TextRunName, paragraphChildren[4].Name); Assert.AreEqual(", World!", paragraphChildren[4].Value); Assert.AreEqual(WordMl.SdtName, paragraphChildren[5].Name); Assert.IsTrue(paragraphChildren[5].IsTag("text")); Assert.AreEqual(startElement, ifTag.StartIf); Assert.AreEqual(endElement, ifTag.EndIf); var textProcessor = (TextProcessor)ifProcessor.Processors.FirstOrDefault(); Assert.IsNotNull(textProcessor); Assert.IsNotNull(textProcessor.TextTag); Assert.AreEqual("//test/text", textProcessor.TextTag.Expression); } }
public void TestElementBetweenEachInDifferentParagraphs() { var startIf = this.documentRoot.Descendants(WordMl.SdtName).Single(d => d.Descendants(WordMl.TagName).Any(t => t.Attribute(WordMl.ValAttributeName).Value == "If")); var endIf = this.documentRoot.Descendants(WordMl.SdtName).Single(d => d.Descendants(WordMl.TagName).Any(t => t.Attribute(WordMl.ValAttributeName).Value == "EndIf")); var elements = TraverseUtils.SecondElementsBetween(startIf, endIf).ToList(); Assert.AreEqual(17, elements.Count()); Assert.IsTrue(elements.Take(6).All(e => e.Name.Equals(WordMl.TextRunName))); Assert.IsTrue(elements.Skip(6).Take(1).All(e => e.Name.Equals(WordMl.ParagraphName))); Assert.IsTrue(elements.Skip(7).Take(1).All(e => e.Name.Equals(WordMl.ParagraphPropertiesName))); Assert.IsTrue(elements.Skip(8).Take(1).All(e => e.Name.Equals(WordMl.BookmarkStartName))); Assert.IsTrue(elements.Skip(9).Take(4).All(e => e.Name.Equals(WordMl.TextRunName))); Assert.IsTrue(elements.Skip(13).Take(1).All(e => e.Name.Equals(WordMl.ProofingErrorAnchorName))); Assert.IsTrue(elements.Skip(14).Take(1).All(e => e.Name.Equals(WordMl.TextRunName))); Assert.IsTrue(elements.Skip(15).Take(1).All(e => e.Name.Equals(WordMl.ProofingErrorAnchorName))); Assert.IsTrue(elements.Skip(16).Take(1).All(e => e.Name.Equals(WordMl.TextRunName))); }
private void ProcessDynamicContent() { var dynamicContentTags = TraverseUtils.ElementsBetween(this.TableTag.TagTable, this.TableTag.TagEndTable) .Where( element => element.IsSdt() && element.Element(WordMl.SdtPrName) .Element(WordMl.TagName) .Attribute(WordMl.ValAttributeName) .Value.ToLower() .Equals("dynamiccontent")) .ToList(); foreach (var dynamicContentTag in dynamicContentTags) { var innerElements = dynamicContentTag.Element(WordMl.SdtContentName).Elements(); dynamicContentTag.AddAfterSelf(innerElements); dynamicContentTag.Remove(); } }
public void TestOkay() { var parser = new RepeaterParser(); var tagProcessorMock = new TagProcessorMock <RepeaterProcessor>(); parser.Parse(tagProcessorMock, this.documentRoot.Descendants(WordMl.SdtName).First()); var result = tagProcessorMock.InnerProcessor.RepeaterTag; var repeaterElements = TraverseUtils.ElementsBetween(result.StartRepeater, result.EndRepeater) .Select(result.MakeElementCallback).ToList(); Assert.AreEqual(1, repeaterElements.Count); var childrenOfFirstElement = repeaterElements.First().Elements.ToList(); Assert.AreEqual(9, childrenOfFirstElement.Count); Assert.AreEqual("./Subject", childrenOfFirstElement[3].Expression); Assert.AreEqual(true, childrenOfFirstElement[5].IsIndex); Assert.AreEqual("./ExpireDate", childrenOfFirstElement[7].Expression); Assert.AreEqual("//test/certificates", result.Source); }
public void TestParseNested() { var parser = new RepeaterParser(); var rootProcessor = new RootProcessor(); parser.Parse(rootProcessor, this.nestedDocumentRoot.Descendants(WordMl.SdtName).First()); var repeaterProcessor = rootProcessor.Processors.First(); var result = ((RepeaterProcessor)repeaterProcessor).RepeaterTag; var repeaterElements = TraverseUtils.ElementsBetween(result.StartRepeater, result.EndRepeater) .Select(result.MakeElementCallback).ToList(); Assert.AreEqual(2, repeaterElements.Count); var textTag = repeaterElements.First(); Assert.IsTrue(textTag.XElement.IsSdt()); Assert.IsTrue(textTag.XElement.IsTag("Text")); var repeaterContent = repeaterElements[1].Elements.ToList(); Assert.AreEqual(10, repeaterContent.Count); var textSdt = repeaterContent[3]; Assert.IsNull(textSdt.Expression); Assert.IsTrue(textSdt.XElement.IsSdt()); Assert.IsTrue(textSdt.XElement.IsTag("Text")); Assert.AreEqual("./Subject", repeaterContent[4].Expression); Assert.AreEqual(true, repeaterContent[6].IsIndex); Assert.AreEqual("./ExpireDate", repeaterContent[8].Expression); Assert.AreEqual("//test/certificates", result.Source); Assert.IsTrue(repeaterProcessor.Processors.All(p => p is TextProcessor)); Assert.AreEqual(2, repeaterProcessor.Processors.Count); }
public void TestElementsBetweenEndElementInNestedElement() { var startElement = new XElement("elementStart"); var secondElement = new XElement("element2"); var thirdElement = new XElement("element3"); var inclusiveElement = new XElement("elementInclusive"); var nestedElementFirst = new XElement("elementNested1"); var nestedElementSecond = new XElement("elementNested2"); var nestedElementEnd = new XElement("elementNestedEnd"); var nestedElementThird = new XElement("elementNested3"); inclusiveElement.Add(nestedElementFirst, nestedElementSecond, nestedElementEnd, nestedElementThird); var afterElementFirst = new XElement("elementAfter1"); var afterElementSecond = new XElement("elementAfter2"); var expectedDoc = new XDocument(new XElement("Root")); expectedDoc.Root.Add(startElement, secondElement, thirdElement, inclusiveElement, afterElementFirst, afterElementSecond); /*foreach (var ancestor in nestedElementFirst.Ancestors()) * { * Console.WriteLine(ancestor); * }*/ Console.WriteLine("Source document:"); Console.WriteLine(expectedDoc); Console.WriteLine("--------"); var betweenElements = TraverseUtils.SecondElementsBetween(startElement, nestedElementEnd); foreach (var betweenElement in betweenElements) { Console.WriteLine(betweenElement); } Assert.AreEqual(4, betweenElements.Count()); //------------- }
public void TestParseVariousOrderTag() { var processorMock = new TagProcessorMock <TableProcessor>(); var parser = new TableParser(); var root = new XElement(this.documentRoot); var paragraph = root.Element(WordMl.ParagraphName); //var itemsElement = TraverseUtils.TagElement(root, "Items"); //itemsElement.AddBeforeSelf(paragraph); //var dynamicRowElement = TraverseUtils.TagElement(root, "DynamicRow"); //dynamicRowElement.AddBeforeSelf(paragraph); //var contentElement = TraverseUtils.TagElement(root, "Content"); //contentElement.AddBeforeSelf(paragraph); //var endContentElement = TraverseUtils.TagElement(root, "EndContent"); //endContentElement.AddBeforeSelf(paragraph); var tableElement = root.Element(WordMl.TableName); Assert.IsNotNull(tableElement); tableElement.AddBeforeSelf(paragraph); var endTableElement = TraverseUtils.TagElement(root, "EndTable"); endTableElement.AddBeforeSelf(paragraph); var startElement = TraverseUtils.TagElement(root, "Table"); parser.Parse(processorMock, startElement); var processor = processorMock.InnerProcessor; var tag = processor.TableTag; Assert.AreEqual(4, tag.DynamicRow); Assert.AreEqual("//test/certificates", tag.ItemsSource); Assert.AreEqual(tableElement, tag.Table); this.CheckTagElements(tag); // itemsElement.Remove(); //endTableElement.AddBeforeSelf(itemsElement); parser.Parse(processorMock, startElement); processor = processorMock.InnerProcessor; tag = processor.TableTag; Assert.AreEqual(4, tag.DynamicRow); Assert.AreEqual("//test/certificates", tag.ItemsSource); Assert.AreEqual(tableElement, tag.Table); this.CheckTagElements(tag); //dynamicRowElement.Remove(); //endTableElement.AddBeforeSelf(dynamicRowElement); parser.Parse(processorMock, startElement); processor = processorMock.InnerProcessor; tag = processor.TableTag; Assert.AreEqual(4, tag.DynamicRow); Assert.AreEqual("//test/certificates", tag.ItemsSource); Assert.AreEqual(tableElement, tag.Table); this.CheckTagElements(tag); //contentElement.Remove(); tableElement.Remove(); //endContentElement.Remove(); //endTableElement.AddBeforeSelf(contentElement); endTableElement.AddBeforeSelf(tableElement); //endTableElement.AddBeforeSelf(endContentElement); parser.Parse(processorMock, startElement); processor = processorMock.InnerProcessor; tag = processor.TableTag; Assert.AreEqual(4, tag.DynamicRow); Assert.AreEqual("//test/certificates", tag.ItemsSource); Assert.AreEqual(tableElement, tag.Table); this.CheckTagElements(tag); }
/// <summary> /// Removes all elements between and including passed elements /// </summary> /// <param name="from"></param> /// <param name="to"></param> public void CleanUp(XElement from, XElement to) { TraverseUtils.ElementsBetween(from, to).Remove(); from.Remove(); to.Remove(); }
private void ProcessElements(IEnumerable <TableElement> tableElements, DataReader dataReader, int index, XElement start, bool isTopLevel) { var tableElementsList = tableElements.ToList(); XElement previous = start; XElement firstCell = null; foreach (var currentTableElement in tableElementsList) { if (currentTableElement.IsCellColor) { this.SetCellColor(currentTableElement.StartTag.Ancestors(WordMl.TableCellName).First(), dataReader.ReadText(currentTableElement.Expression)); currentTableElement.StartTag.Remove(); } else if (currentTableElement.IsItemTable) { var tableCell = currentTableElement.StartTag.Ancestors(WordMl.TableCellName).Last(); var tableElement = TraverseUtils.SecondElementsBetween(currentTableElement.StartTag, currentTableElement.EndTag) .SingleOrDefault(el => el.Name.Equals(WordMl.TableName)); var parentCellWidth = GetCellWidth(tableCell); SetTableWidth(tableElement, parentCellWidth); XElement parentElement = null; if (currentTableElement.StartTag.Parent.Name.Equals(WordMl.ParagraphName)) { parentElement = currentTableElement.StartTag.Parent; } var itemTableGenerator = new ItemTableGenerator(); itemTableGenerator.Generate(currentTableElement.StartTag, currentTableElement.EndTag, dataReader); if (parentElement != null) { parentElement.Remove(); } } else if (currentTableElement.IsItemHtmlContent) { currentTableElement.StartTag = HtmlContentProcessor.MakeHtmlContentProcessed(currentTableElement.StartTag, dataReader.ReadText( currentTableElement.Expression)); } else if (currentTableElement.IsItemIf) { previous = this.ProcessItemIfElement(currentTableElement, dataReader, index, previous); //TODO: this if need testing if (firstCell == null) { firstCell = previous; } } else if (currentTableElement.IsItemRepeater) { this.ProcessItemRepeaterElement(currentTableElement, dataReader, index, previous); } else if (currentTableElement.IsItem || currentTableElement.IsIndex) { var resultText = currentTableElement.IsIndex ? index.ToString(CultureInfo.CurrentCulture) : dataReader.ReadText(currentTableElement.Expression); previous = this.ProcessCell(currentTableElement, previous, resultText); if (firstCell == null) { firstCell = previous; } currentTableElement.StartTag.Remove(); } } if (isTopLevel && firstCell != null) { ProcessStaticCells(firstCell, previous); } }