DocumentVisitor Class
Base class for custom document visitors.
Inheritance Hierarchy
SystemObject
  Aspose.WordsDocumentVisitor

Namespace: Aspose.Words
Assembly: Aspose.Words (in Aspose.Words.dll) Version: 19.9
Syntax
public abstract class DocumentVisitor

The DocumentVisitor type exposes the following members.

Constructors
  NameDescription
Protected methodDocumentVisitor
Initializes a new instance of the DocumentVisitor class
Methods
  NameDescription
Public methodEquals
Determines whether the specified Object is equal to the current Object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetHashCode
Serves as a hash function for a particular type.
(Inherited from Object.)
Public methodGetType
Gets the type of the current instance.
(Inherited from Object.)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Public methodCode exampleVisitAbsolutePositionTab
Called when a AbsolutePositionTab node is encountered in the document.
Public methodCode exampleVisitBodyEnd
Called when enumeration of the main text story in a section has ended.
Public methodCode exampleVisitBodyStart
Called when enumeration of the main text story in a section has started.
Public methodCode exampleVisitBookmarkEnd
Called when an end of a bookmark is encountered in the document.
Public methodCode exampleVisitBookmarkStart
Called when a start of a bookmark is encountered in the document.
Public methodCode exampleVisitBuildingBlockEnd
Called when enumeration of a building block has ended.
Public methodCode exampleVisitBuildingBlockStart
Called when enumeration of a building block has started.
Public methodCode exampleVisitCellEnd
Called when enumeration of a table cell has ended.
Public methodCode exampleVisitCellStart
Called when enumeration of a table cell has started.
Public methodCode exampleVisitCommentEnd
Called when enumeration of a comment text has ended.
Public methodCode exampleVisitCommentRangeEnd
Called when the end of a commented range of text is encountered.
Public methodCode exampleVisitCommentRangeStart
Called when the start of a commented range of text is encountered.
Public methodCode exampleVisitCommentStart
Called when enumeration of a comment text has started.
Public methodCode exampleVisitDocumentEnd
Called when enumeration of the document has finished.
Public methodCode exampleVisitDocumentStart
Called when enumeration of the document has started.
Public methodCode exampleVisitEditableRangeEnd
Called when an end of an editable range is encountered in the document.
Public methodCode exampleVisitEditableRangeStart
Called when a start of an editable range is encountered in the document.
Public methodCode exampleVisitFieldEnd
Called when a field ends in the document.
Public methodCode exampleVisitFieldSeparator
Called when a field separator is encountered in the document.
Public methodCode exampleVisitFieldStart
Called when a field starts in the document.
Public methodCode exampleVisitFootnoteEnd
Called when enumeration of a footnote or endnote text has ended.
Public methodCode exampleVisitFootnoteStart
Called when enumeration of a footnote or endnote text has started.
Public methodCode exampleVisitFormField
Called when a form field is encountered in the document.
Public methodCode exampleVisitGlossaryDocumentEnd
Called when enumeration of a glossary document has ended.
Public methodCode exampleVisitGlossaryDocumentStart
Called when enumeration of a glossary document has started.
Public methodCode exampleVisitGroupShapeEnd
Called when enumeration of a group shape has ended.
Public methodCode exampleVisitGroupShapeStart
Called when enumeration of a group shape has started.
Public methodCode exampleVisitHeaderFooterEnd
Called when enumeration of a header or footer in a section has ended.
Public methodCode exampleVisitHeaderFooterStart
Called when enumeration of a header or footer in a section has started.
Public methodCode exampleVisitOfficeMathEnd
Called when enumeration of a Office Math object has ended.
Public methodCode exampleVisitOfficeMathStart
Called when enumeration of a Office Math object has started.
Public methodCode exampleVisitParagraphEnd
Called when enumeration of a paragraph has ended.
Public methodCode exampleVisitParagraphStart
Called when enumeration of a paragraph has started.
Public methodCode exampleVisitRowEnd
Called when enumeration of a table row has ended.
Public methodCode exampleVisitRowStart
Called when enumeration of a table row has started.
Public methodCode exampleVisitRun
Called when a run of text in the is encountered.
Public methodCode exampleVisitSectionEnd
Called when enumeration of a section has ended.
Public methodCode exampleVisitSectionStart
Called when enumeration of a section has started.
Public methodCode exampleVisitShapeEnd
Called when enumeration of a shape has ended.
Public methodCode exampleVisitShapeStart
Called when enumeration of a shape has started.
Public methodCode exampleVisitSmartTagEnd
Called when enumeration of a smart tag has ended.
Public methodCode exampleVisitSmartTagStart
Called when enumeration of a smart tag has started.
Public methodCode exampleVisitSpecialChar
Called when a SpecialChar node is encountered in the document.
Public methodCode exampleVisitStructuredDocumentTagEnd
Called when enumeration of a structured document tag has ended.
Public methodCode exampleVisitStructuredDocumentTagStart
Called when enumeration of a structured document tag has started.
Public methodCode exampleVisitSubDocument
Called when a subDocument is encountered.
Public methodCode exampleVisitTableEnd
Called when enumeration of a table has ended.
Public methodCode exampleVisitTableStart
Called when enumeration of a table has started.
Remarks

With DocumentVisitor you can define and execute custom operations that require enumeration over the document tree.

For example, Aspose.Words uses DocumentVisitor internally for saving Document in various formats and for other operations like finding fields or bookmarks over a fragment of a document.

To use DocumentVisitor:

  1. Create a class derived from DocumentVisitor.
  2. Override and provide implementations for some or all of the VisitXXX methods to perform some custom operations.
  3. Call Node.Accept on the Node that you want to start the enumeration from.

DocumentVisitor provides default implementations for all of the VisitXXX methods to make it easier to create new document visitors as only the methods required for the particular visitor need to be overridden. It is not necessary to override all of the visitor methods.

For more information see the Visitor design pattern.

Examples
Traverse a document with a visitor that prints all structure nodes that it encounters.
[C#]

public void DocStructureToText()
{
    // Open the document that has nodes we want to print the info of
    Document doc = new Document(MyDir + "DocumentVisitor.Destination.docx");

    // Create an object that inherits from the DocumentVisitor class
    DocStructurePrinter visitor = new DocStructurePrinter();

    // Accepting a visitor lets it start traversing the nodes in the document, 
    // starting with the node that accepted it to then recursively visit every child
    doc.Accept(visitor);

    // Once the visiting is complete, we can retrieve the result of the operation,
    // that in this example, has accumulated in the visitor
    Console.WriteLine(visitor.GetText());
}

/// <summary>
/// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
/// </summary>
public class DocStructurePrinter : DocumentVisitor
{
    public DocStructurePrinter()
    {
        mBuilder = new StringBuilder();
    }

    /// <summary>
    /// Gets the plain text of the document that was accumulated by the visitor.
    /// </summary>
    public String GetText()
    {
        return mBuilder.ToString();
    }

    /// <summary>
    /// Called when a Document node is encountered.
    /// </summary>
    public override VisitorAction VisitDocumentStart(Document doc)
    {
        int childNodeCount = doc.GetChildNodes(NodeType.Any, true).Count;

        // A Document node is at the root of every document, so if we let a document accept a visitor, this will be the first visitor action to be carried out
        IndentAndAppendLine("[Document start] Child nodes: " + childNodeCount);
        mDocTraversalDepth++;

        // Let the visitor continue visiting other nodes
        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when the visiting of a Document is ended.
    /// </summary>
    public override VisitorAction VisitDocumentEnd(Document doc)
    {
        // If we let a document accept a visitor, this will be the last visitor action to be carried out
        mDocTraversalDepth--;
        IndentAndAppendLine("[Document end]");

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a Section node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitSectionStart(Section section)
    {
        // Get the index of our section within the document
        NodeCollection docSections = section.Document.GetChildNodes(NodeType.Section, false);
        int sectionIndex = docSections.IndexOf(section);

        IndentAndAppendLine("[Section start] Section index: " + sectionIndex);
        mDocTraversalDepth++;

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when the visiting of a Section node is ended.
    /// </summary>
    public override VisitorAction VisitSectionEnd(Section section)
    {
        mDocTraversalDepth--;
        IndentAndAppendLine("[Section end]");

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a Body node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitBodyStart(Body body)
    {
        int paragraphCount = body.Paragraphs.Count;
        IndentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
        mDocTraversalDepth++;

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when the visiting of a Body node is ended.
    /// </summary>
    public override VisitorAction VisitBodyEnd(Body body)
    {
        mDocTraversalDepth--;
        IndentAndAppendLine("[Body end]");

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a Paragraph node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitParagraphStart(Paragraph paragraph)
    {
        IndentAndAppendLine("[Paragraph start]");
        mDocTraversalDepth++;

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when the visiting of a Paragraph node is ended.
    /// </summary>
    public override VisitorAction VisitParagraphEnd(Paragraph paragraph)
    {
        mDocTraversalDepth--;
        IndentAndAppendLine("[Paragraph end]");

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a Run node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitRun(Run run)
    {
        IndentAndAppendLine("[Run] \"" + run.GetText() + "\"");

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a SubDocument node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitSubDocument(SubDocument subDocument)
    {
        IndentAndAppendLine("[SubDocument]");

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Append a line to the StringBuilder and indent it depending on how deep the visitor is into the document tree.
    /// </summary>
    /// <param name="text"></param>
    private void IndentAndAppendLine(String text)
    {
        for (int i = 0; i < mDocTraversalDepth; i++)
        {
            mBuilder.Append("|  ");
        }

        mBuilder.AppendLine(text);
    }

    private int mDocTraversalDepth;
    private readonly StringBuilder mBuilder;
}
Examples
Shows how to use the Visitor pattern to add new operations to the Aspose.Words object model. In this case we create a simple document converter into a text format.
[C#]

// Open the document we want to convert.
    Document doc = new Document(MyDir + "Visitor.ToText.doc");

    // Create an object that inherits from the DocumentVisitor class.
    MyDocToTxtWriter myConverter = new MyDocToTxtWriter();

    // This is the well known Visitor pattern. Get the model to accept a visitor.
    // The model will iterate through itself by calling the corresponding methods
    // on the visitor object (this is called visiting).
    // 
    // Note that every node in the object model has the Accept method so the visiting
    // can be executed not only for the whole document, but for any node in the document.
    doc.Accept(myConverter);

    // Once the visiting is complete, we can retrieve the result of the operation,
    // that in this example, has accumulated in the visitor.
    Console.WriteLine(myConverter.GetText());
}

/// <summary>
/// Simple implementation of saving a document in the plain text format. Implemented as a Visitor.
/// </summary>
public class MyDocToTxtWriter : DocumentVisitor
{
    public MyDocToTxtWriter()
    {
        this.mIsSkipText = false;
        this.mBuilder = new StringBuilder();
    }

    /// <summary>
    /// Gets the plain text of the document that was accumulated by the visitor.
    /// </summary>
    public String GetText()
    {
        return this.mBuilder.ToString();
    }

    /// <summary>
    /// Called when a Run node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitRun(Run run)
    {
        this.AppendText(run.Text);

        // Let the visitor continue visiting other nodes.
        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a FieldStart node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitFieldStart(FieldStart fieldStart)
    {
        // In Microsoft Word, a field code (such as "MERGEFIELD FieldName") follows
        // after a field start character. We want to skip field codes and output field 
        // result only, therefore we use a flag to suspend the output while inside a field code.
        // 
        // Note this is a very simplistic implementation and will not work very well
        // if you have nested fields in a document. 
        this.mIsSkipText = true;

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a FieldSeparator node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitFieldSeparator(FieldSeparator fieldSeparator)
    {
        // Once reached a field separator node, we enable the output because we are
        // now entering the field result nodes.
        this.mIsSkipText = false;

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a FieldEnd node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitFieldEnd(FieldEnd fieldEnd)
    {
        // Make sure we enable the output when reached a field end because some fields
        // do not have field separator and do not have field result.
        this.mIsSkipText = false;

        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when visiting of a Paragraph node is ended in the document.
    /// </summary>
    public override VisitorAction VisitParagraphEnd(Paragraph paragraph)
    {
        // When outputting to plain text we output Cr+Lf characters.
        this.AppendText(ControlChar.CrLf);

        return VisitorAction.Continue;
    }

    public override VisitorAction VisitBodyStart(Body body)
    {
        // We can detect beginning and end of all composite nodes such as Section, Body, 
        // Table, Paragraph etc and provide custom handling for them.
        this.mBuilder.Append("*** Body Started ***\r\n");

        return VisitorAction.Continue;
    }

    public override VisitorAction VisitBodyEnd(Body body)
    {
        this.mBuilder.Append("*** Body Ended ***\r\n");
        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a HeaderFooter node is encountered in the document.
    /// </summary>
    public override VisitorAction VisitHeaderFooterStart(HeaderFooter headerFooter)
    {
        // Returning this value from a visitor method causes visiting of this
        // node to stop and move on to visiting the next sibling node.
        // The net effect in this example is that the text of headers and footers
        // is not included in the resulting output.
        return VisitorAction.SkipThisNode;
    }

    /// <summary>
    /// Called when an AbsolutePositionTab is encountered in the document.
    /// </summary>
    public override VisitorAction VisitAbsolutePositionTab(AbsolutePositionTab tab)
    {
        this.mBuilder.Append("\t");
        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a BookmarkStart is encountered in the document.
    /// </summary>
    public override VisitorAction VisitBookmarkStart(BookmarkStart bookmarkStart)
    {
        this.mBuilder.Append("[");
        return VisitorAction.Continue;
    }

    /// <summary>
    /// Called when a BookmarkEnd is encountered in the document.
    /// </summary>
    public override VisitorAction VisitBookmarkEnd(BookmarkEnd bookmarkEnd)
    {
        this.mBuilder.Append("]");
        return VisitorAction.Continue;
    }

    /// <summary>
    /// Adds text to the current output. Honours the enabled/disabled output flag.
    /// </summary>
    private void AppendText(String text)
    {
        if (!this.mIsSkipText)
            this.mBuilder.Append(text);
    }

    private readonly StringBuilder mBuilder;
    private bool mIsSkipText;
}
See Also