Table of Contents

Custom ISource Implementation

Namespace: Clippit.Word

The ISource interface allows using DocumentBuilder with custom content selectors. Implement this interface to define your own logic for selecting which elements from a source document should be included in the built document.

public interface ISource : ICloneable
{
    WmlDocument WmlDocument { get; set; }
    bool KeepSections { get; set; }
    bool DiscardHeadersAndFootersInKeptSections { get; set; }
    string InsertId { get; set; }

    IEnumerable<XElement> GetElements(WordprocessingDocument document);
}

The GetElements method is called by DocumentBuilder to retrieve the content elements from the source document. Your implementation controls which elements are returned.

RecursiveTableCellSource

RecursiveTableCellSource is an example custom ISource implementation that allows referencing content inside nested tables (tables within tables).

TableCellReference

Each TableCellReference specifies one level of table nesting:

public class TableCellReference
{
    public int TableElementIndex { get; set; }  // Index of table in current context
    public int RowIndex { get; set; }           // Row within the table
    public int CellIndex { get; set; }          // Cell within the row
}

RecursiveTableCellSource Class

public class RecursiveTableCellSource : ISource
{
    public WmlDocument WmlDocument { get; set; }
    public bool KeepSections { get; set; }
    public bool DiscardHeadersAndFootersInKeptSections { get; set; }
    public string InsertId { get; set; }

    // Navigation path through nested tables
    public List<TableCellReference> TableCellReferences { get; set; }

    // Content range within the final cell
    public int Start { get; set; }
    public int Count { get; set; }
}

RecursiveTableCellSource Sample

var document = new WmlDocument("nested-tables.docx");

// Navigate to: body -> table[0] -> row[1] -> cell[2] -> table[0] -> row[0] -> cell[1]
// Then extract 3 elements starting from element 0
var source = new RecursiveTableCellSource
{
    WmlDocument = document,
    TableCellReferences = new List<TableCellReference>
    {
        new() { TableElementIndex = 0, RowIndex = 1, CellIndex = 2 },  // Outer table
        new() { TableElementIndex = 0, RowIndex = 0, CellIndex = 1 }   // Inner table
    },
    Start = 0,
    Count = 3
};

var sources = new List<ISource> { source };
var result = DocumentBuilder.BuildDocument(sources);
result.SaveAs("extracted-content.docx");