private ProcessResult FillContent(XContainer contentControl, IContentItem item) { var processResult = ProcessResult.NotHandledResult; if (!(item is SingleContent)) { processResult = ProcessResult.NotHandledResult; return(processResult); } var single = (SingleContent)item; // If there isn't a field with that name, add an error to the error string, and continue // with next field. if (contentControl == null) { processResult.AddError(new ContentControlNotFoundError(single)); return(processResult); } var content = contentControl.Element(W.SdtContent); var childElement = content.FirstLevelDescendantsAndSelf(W.Sdt) .First(sdt => single.ChildName == sdt.SdtTagName()); childElement.ElementsAfterSelf(W.Sdt).ToList().ForEach(e => e.Remove()); childElement.ElementsAfterSelf(W.R).ToList().ForEach(e => e.Remove()); childElement.ElementsBeforeSelf(W.Sdt).ToList().ForEach(e => e.Remove()); childElement.ElementsBeforeSelf(W.R).ToList().ForEach(e => e.Remove()); processResult.AddItemToHandled(item); var contentProcessResult = new ContentProcessor(_context) .SetRemoveContentControls(_isNeedToRemoveContentControls) .FillContent(childElement.Element(W.SdtContent), single.Fields); processResult.Merge(contentProcessResult); processResult.AddItemToHandled(item); if (_isNeedToRemoveContentControls) { childElement.RemoveContentControl(); } return(processResult); }
/// <summary> /// Fills content with one content item /// </summary> /// <param name="contentControl">Content control</param> /// <param name="item">Content item</param> private ProcessResult FillContent(XContainer contentControl, IContentItem item) { if (!(item is TableContent)) { return(ProcessResult.NotHandledResult); } var processResult = ProcessResult.NotHandledResult; var table = (TableContent)item; // If there isn't a table with that name, add an error to the error string, and continue // with next table. if (contentControl == null) { processResult.AddError(new ContentControlNotFoundError(table)); return(processResult); } // If the table doesn't contain content controls in cells, then error and continue with // next table. var cellContentControl = contentControl .Descendants(W.Sdt) .FirstOrDefault(); if (cellContentControl == null) { processResult.AddError(new CustomContentItemError(table, "doesn\'t contain content controls in cells")); return(processResult); } var fieldNames = table.FieldNames.ToList(); var prototypeRows = GetPrototype(contentControl, fieldNames); //Select content controls tag names var contentControlTagNames = prototypeRows .Descendants(W.Sdt) .Select(sdt => sdt.SdtTagName()) .Where(fieldNames.Contains) .ToList(); //If there are not content controls with the one of specified field name we need to add the warning if (contentControlTagNames.Intersect(fieldNames).Count() != fieldNames.Count) { var invalidFileNames = fieldNames .Where(fn => !contentControlTagNames.Contains(fn)) .ToList(); processResult.AddError( new CustomContentItemError(table, string.Format("doesn't contain rows with cell content {0} {1}", invalidFileNames.Count > 1 ? "controls" : "control", string.Join(", ", invalidFileNames.Select(fn => string.Format("'{0}'", fn)))))); } // Create a list of new rows to be inserted into the document. Because this is a document // centric transform, this is written in a non-functional style, using tree modification. var newRows = new List <List <XElement> >(); foreach (var row in table.Rows) { // Clone the prototypeRows into newRowsEntry. var newRowsEntry = prototypeRows.Select(prototypeRow => new XElement(prototypeRow)).ToList(); // Create new rows that will contain the data that was passed in to this method in // the XML tree. foreach (var sdt in newRowsEntry.FirstLevelDescendantsAndSelf(W.Sdt).ToList()) { // Get fieldName from the content control tag. var fieldName = sdt.SdtTagName(); var content = row.GetContentItem(fieldName); if (content != null) { var contentProcessResult = new ContentProcessor(_context) .SetRemoveContentControls(_isNeedToRemoveContentControls) .FillContent(sdt, content); processResult.Merge(contentProcessResult); } } // Add the newRow to the list of rows that will be placed in the newly generated table. newRows.Add(newRowsEntry); } prototypeRows.Last().AddAfterSelf(newRows); // Remove the prototype rows prototypeRows.Remove(); processResult.AddItemToHandled(table); return(processResult); }
// Fills prototype with values recursive. private PropagationProcessResult PropagatePrototype(Prototype prototype, IEnumerable <ListItemContent> content) { var processResult = new PropagationProcessResult(); var newRows = new List <XElement>(); foreach (var contentItem in content) { var currentLevelPrototype = prototype.CurrentLevelPrototype(contentItem.GetFieldNames()); if (currentLevelPrototype == null || !currentLevelPrototype.IsValid) { processResult.AddError(new CustomError( string.Format("Prototype for list item '{0}' not found", string.Join(", ", contentItem.GetFieldNames())))); continue; } // Create new item from the prototype. var newItemEntry = currentLevelPrototype.Clone(); foreach (var xElement in newItemEntry.PrototypeItems) { var newElement = new XElement(xElement); if (!newElement.DescendantsAndSelf(W.Sdt).Any()) { newRows.Add(newElement); continue; } foreach (var sdt in newElement.FirstLevelDescendantsAndSelf(W.Sdt).ToList()) { var fieldContent = contentItem.GetContentItem(sdt.SdtTagName()); if (fieldContent == null) { processResult.AddError(new CustomError( string.Format("Field content for field '{0}' not found", sdt.SdtTagName()))); continue; } var contentProcessResult = new ContentProcessor(_context) .SetRemoveContentControls(_isNeedToRemoveContentControls) .FillContent(sdt, fieldContent); processResult.Merge(contentProcessResult); } newRows.Add(newElement); } // If there are nested items fill prototype for them. if (contentItem.NestedFields != null) { var filledNestedFields = PropagatePrototype( prototype.Exclude(currentLevelPrototype), contentItem.NestedFields); newRows.AddRange(filledNestedFields.Result); } } processResult.Result = newRows; return(processResult); }