public XElement Generate(ItemRepeaterTag tag, IEnumerable<DataReader> dataReaders, XElement previous = null, XElement parent = null, bool forcedElementSave = false)
 {
     var startElement = tag.StartItemRepeater;
     var endElement = tag.EndItemRepeater;
     var inlineWrapping = CheckInlineWrappingMode(startElement, endElement);
     var itemRepeaterElements =
         TraverseUtils.SecondElementsBetween(startElement, endElement).Select(MakeElementCallback).ToList();
     var flgCleanUpElements = previous == null;
     XElement current;
     if (inlineWrapping && flgCleanUpElements)
     {
         current = startElement;
     }
     else
     {
         if (previous == null)
         {
             current = startElement.Parent.Name.Equals(WordMl.ParagraphName) ? startElement.Parent : startElement;
         }
         else
         {
             current = previous;                    
         }
     }
     for (var index = 1; index <= dataReaders.Count(); index++)
     {
         XElement nestedRepeaterEndElementTmp = null;
         XElement endIfElementTmp = null;
         current = this.ProcessElements(
                                        itemRepeaterElements,
                                        dataReaders.ElementAt(index - 1),
                                        current,
                                        (inlineWrapping && (parent != null)) ? parent : null,
                                        index,
                                        ref nestedRepeaterEndElementTmp,
                                        ref endIfElementTmp,                                               
                                        inlineWrapping && (parent != null)
         );
     }
     if (flgCleanUpElements && !forcedElementSave)
     {
         foreach (var itemRepeaterElement in itemRepeaterElements)
         {
             itemRepeaterElement.XElement.Remove();
         }                                
         startElement.Remove();                
         endElement.Remove();
         
     }            
     return current;
 }       
 public XElement Parse(ItemRepeaterTag tag, IList<DataReader> dataReaders, XElement current = null)
 {
     var startElement = tag.StartItemRepeater;
     var endElement = tag.EndItemRepeater;
     List<ItemRepeaterElement> itemRepeaterElements;            
         itemRepeaterElements =
             this.MarkLastElements(
                 TraverseUtils.ElementsBetween(startElement, endElement).Select(MakeElementCallback).ToList())
                 .ToList();
     
     var nestedRepeaters = this.MarkNotSeparatedRepeaters(this.GetAllNestedRepeaters(tag), itemRepeaterElements);
     if (startElement.Parent.Name == WordMl.ParagraphName)
     {
         startElement = startElement.Parent;
     }
     var flgDeleteStartEnd = current == null;
     current = current ?? startElement;
     var repeaterElements = this.GetSiblingElements(itemRepeaterElements.ToList(), nestedRepeaters.ToList()).Where(sel => !(sel.XElement.IsTag("enditemrepeater") || sel.XElement.IsTag("itemrepeater")));
     XElement currentNested;
     for (var index = 1; index <= dataReaders.Count(); index++)
     {
         this.SetRepeaterElementsVisible(repeaterElements.ToList());
         ICollection<XElement> bisectElements;
         var ifCount = 1;
         var flg = false;
         repeaterElements = this.MarkInvisibleElements(repeaterElements, dataReaders[index - 1], ref ifCount, ref flg, index == dataReaders.Count);
         if (ifCount != 1)
         {
             throw new Exception("ItemIf error. Check REndIf count.");
         }
         current = this.ProcessElements(repeaterElements, dataReaders[index - 1], current, null, index, out bisectElements);
         currentNested = this.ProcessNestedRepeaters(tag, dataReaders[index - 1], (!bisectElements.Any()) ? new List<XElement>() { current } : bisectElements);
         if ((currentNested != null) && repeaterElements.Last().IsBeforeNestedRepeater)
         {
             current = currentNested;
         }
     }
     if (flgDeleteStartEnd)
     {
         foreach (var itemRepeaterElement in itemRepeaterElements)
         {                
             itemRepeaterElement.XElement.Remove();                
         }            
         startElement.Remove();
         endElement.Remove();
     }
     return current;
 }
        private XElement ProcessNestedRepeaters(ItemRepeaterTag tag, DataReader dataReader, ICollection<XElement> bisectElements)
        {
            XElement current = null;
            int i = 0;
            foreach (var nestedRepeater in tag.NestedRepeaters)
            {
                if (nestedRepeater.NestedRepeaters.Count == 0)
                {
                    if (!nestedRepeater.IsNotSeparatedRepeater)
                    {
                        current = bisectElements.ElementAt(i);

                        ++i;
                    }
                    current = this.RenderDataReaders(nestedRepeater, dataReader, current);
                }               
            }
            return current;
        }
        private XElement RenderDataReaders(ItemRepeaterTag tag, DataReader dataReader, XElement current)
        {
            var elements = TraverseUtils.ElementsBetween(tag.StartItemRepeater,
                    ((tag.EndItemRepeater.Parent.Name == WordMl.ParagraphName)
                    && (!tag.EndItemRepeater.Parent.Elements().Contains(tag.StartItemRepeater))
                    && (tag.StartItemRepeater.Parent.Elements().Any(el => el.IsSdt() && !el.IsTag("itemrepeater")))
                    ) ? tag.EndItemRepeater.Parent : tag.EndItemRepeater)
                    .Select(MakeElementCallback)
                    .ToList();
            var processedElements = new List<ItemRepeaterElement>();
            if (elements.Count > 1)
            {
                processedElements.AddRange(this.CreateParagraphForInlineElements(elements));
            }
            else
            {
                processedElements.Add(elements[0]);
            }
            processedElements = this.SetRepeaterElementsVisible(processedElements.ToList()).ToList();
            var flgWrapInline = false;
            if (processedElements.Count == 1)
            {
                var rootContainer = processedElements.FirstOrDefault();
                if ((rootContainer != null) && rootContainer.XElement.Name.Equals(WordMl.ParagraphName))
                {
                    var originalContainer = elements[0].XElement.Parent;
                    var endItemRepeater = originalContainer.Elements().FirstOrDefault(el => el.IsTag("enditemrepeater"));
                    if (endItemRepeater != null)
                    {
                        flgWrapInline = elements.All(e => e.XElement.Parent.Elements().Contains(endItemRepeater));
                    }
                }
            }
            var dataReaders = dataReader.GetReaders(tag.Source).ToList();
            for (var index = 1; index <= dataReaders.Count; index++)
            {
                ICollection<XElement> bisectElements;
                var ifCount = 1;
                var flg = false;
                processedElements = this.MarkInvisibleElements(processedElements, dataReaders[index - 1], ref ifCount, ref flg, index == dataReaders.Count).ToList();
                if (ifCount != 1)
                {
                    throw new Exception("RItemIf error. Check REndIf count.");
                }
                var inlineWrapping = (index > 1) && flgWrapInline;
                if (inlineWrapping)
                {
                    current = current.Elements().Last();
                }
                current = this.ProcessElements(
                    inlineWrapping ? processedElements.First().Elements.ToList() : processedElements,
                    dataReaders[index - 1],
                    inlineWrapping ? null : current,
                    inlineWrapping ? current.Parent : null,
                    index,
                    out bisectElements,
                    (index > 1) && flgWrapInline);
            }
            return current;

        }
 private ICollection<ItemRepeaterTag> GetAllNestedRepeaters(ItemRepeaterTag tag)
 {
     var result = new List<ItemRepeaterTag>();
     foreach (var nestedRepeater in tag.NestedRepeaters)
     {
         if (nestedRepeater.NestedRepeaters.Count != 0)
         {
             result.AddRange(this.GetAllNestedRepeaters(nestedRepeater));
         }
         else
         {
             result.Add(nestedRepeater);
         }
     }
     return result;
 }
        private XElement ProcessElements(IEnumerable<ItemRepeaterElement> elements, DataReader dataReader, XElement start, XElement parent, int index, ref XElement nestedRepeaterEndElement, ref XElement endIfElement, bool nestedElement = false)
        {
            XElement result = null;
            XElement previous = start;

            foreach (var itemRepeaterElement in elements)
            {               
                var flgStucturedElementProcessed = this.CheckAndProcessStartIfElementForContinue(itemRepeaterElement,
                                                                                                  dataReader,
                                                                                                  ref endIfElement)
                                                    ||
                                                    this.CheckAndProcessEndIfElementForContinue(itemRepeaterElement,
                                                                                                ref endIfElement)
                                                    ||
                                                    this.CheckAndProcessEndItemRepeaterElementForContinue(
                                                        itemRepeaterElement, ref nestedRepeaterEndElement)
                                                        || this.CheckTableElementForContinue(itemRepeaterElement);                                                                                
                if (!flgStucturedElementProcessed)
                {
                    var flgNestedElementCheckedForContinue = this.CheckNestedConditionElementForContinue(
                                                             itemRepeaterElement, endIfElement)
                                                             ||
                                                             this.CheckNestedElementForContinue(elements.First(),
                                                                                                itemRepeaterElement,
                                                                                                nestedRepeaterEndElement);                                                              
                                                              
                    if (!flgNestedElementCheckedForContinue)
                    {
                        if (itemRepeaterElement.IsItemHtmlContent)
                        {
                            result = HtmlContentProcessor.MakeHtmlContentProcessed(itemRepeaterElement.XElement,
                                                                                   dataReader.ReadText(
                                                                                       itemRepeaterElement.Expression),
                                                                                   true);
                        }
                        else if (itemRepeaterElement.IsItemRepeater)
                        {
                            var itemRepeaterTag = new ItemRepeaterTag()
                                {
                                    StartItemRepeater = itemRepeaterElement.StartTag,
                                    EndItemRepeater = itemRepeaterElement.EndTag,
                                    Source = itemRepeaterElement.Expression
                                };
                            var itemRepeaterGenerator = new ItemRepeaterGenerator();
                            previous = itemRepeaterGenerator.Generate(itemRepeaterTag,
                                                                      dataReader.GetReaders(itemRepeaterTag.Source),
                                                                      previous, parent);
                            nestedRepeaterEndElement = itemRepeaterTag.EndItemRepeater;                            
                            result = null;
                        }
                        else if (itemRepeaterElement.IsIndex)
                        {
                            result = DocxHelper.CreateTextElement(itemRepeaterElement.XElement,
                                                                  itemRepeaterElement.XElement.Parent,
                                                                  index.ToString(CultureInfo.CurrentCulture),
                                                                  !nestedElement);
                        }
                        else if (itemRepeaterElement.IsItem)
                        {
                            result = DocxHelper.CreateTextElement(itemRepeaterElement.XElement,
                                                                  itemRepeaterElement.XElement.Parent,
                                                                  dataReader.ReadText(itemRepeaterElement.Expression),
                                                                  dataReader.ReadAttribute(itemRepeaterElement.Expression, "style"),
                                                                  !nestedElement);
                        }
                        else if (itemRepeaterElement.IsItemTable)
                        {
                            result = ItemTableGenerator.ProcessItemTableElement(itemRepeaterElement.StartTag, itemRepeaterElement.EndTag,
                                                                        dataReader);
                            if (nestedElement)
                            {
                                previous.AddAfterSelf(result);
                                previous = result;
                                result = null;
                            }           
                        }
                        else
                        {
                            var element = new XElement(itemRepeaterElement.XElement);
                            element.RemoveNodes();
                            result = element;
                            if (itemRepeaterElement.HasElements)
                            {
                                var parsedLastElement = this.ProcessElements(itemRepeaterElement.Elements, dataReader,
                                                                             previous,
                                                                             result, index, ref nestedRepeaterEndElement,
                                                                             ref endIfElement, true);
                                if (itemRepeaterElement.Elements.Any(ire => ire.XElement.IsSdt()) && DocxHelper.IsEmptyParagraph(result))
                                {
                                    result = null;
                                }
                                if (itemRepeaterElement.Elements.Any(ire => ire.IsItemTable) ||
                                    itemRepeaterElement.Elements.Any(
                                        ire =>
                                        ire.IsItemRepeater && !CheckInlineWrappingMode(ire.StartTag, ire.EndTag)))
                                {
                                    previous = parsedLastElement;
                                }
                                
                            }
                            else
                            {
                                element.Value = itemRepeaterElement.XElement.Value;
                            }
                        }
                        if (result != null)
                        {
                            if (!nestedElement)
                            {
                                previous.AddAfterSelf(result);
                                previous = result;
                            }
                            else
                            {
                                parent.Add(result);
                            }
                        }
                    }
                    else
                    {
                        result = null;
                    }
                }
                else
                {
                    result = null;
                }
            }            
            return result ?? previous;
        }