com.aspose.words

Class DocumentVisitor

  • java.lang.Object
    • com.aspose.words.DocumentVisitor
public abstract class DocumentVisitor 
extends java.lang.Object

Base class for custom document visitors.

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(com.aspose.words.DocumentVisitor) 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.

Example:

Traverse a document with a visitor that prints all structure nodes that it encounters.
public void docStructureToText() throws Exception {
    // Open the document that has nodes we want to print the info of
    Document doc = new Document(getMyDir() + "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
    System.out.println(visitor.getText());
}

/// <summary>
/// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
/// </summary>
public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
        int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();

        // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
        // Get the index of our section within the document
        NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
        mDocTraversalDepth--;
        indentAndAppendLine("[Section end]");

        return VisitorAction.CONTINUE;
    }

    /// <summary>
    /// Called when a Body node is encountered in the document.
    /// </summary>
    public int visitBodyStart(final Body body) {
        int paragraphCount = body.getParagraphs().getCount();
        indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
        mDocTraversalDepth++;

        return VisitorAction.CONTINUE;
    }

    /// <summary>
    /// Called when the visiting of a Body node is ended.
    /// </summary>
    public int visitBodyEnd(final Body body) {
        mDocTraversalDepth--;
        indentAndAppendLine("[Body end]");

        return VisitorAction.CONTINUE;
    }

    /// <summary>
    /// Called when a Paragraph node is encountered in the document.
    /// </summary>
    public int visitParagraphStart(final Paragraph paragraph) {
        indentAndAppendLine("[Paragraph start]");
        mDocTraversalDepth++;

        return VisitorAction.CONTINUE;
    }

    /// <summary>
    /// Called when the visiting of a Paragraph node is ended.
    /// </summary>
    public int visitParagraphEnd(final Paragraph paragraph) {
        mDocTraversalDepth--;
        indentAndAppendLine("[Paragraph end]");

        return VisitorAction.CONTINUE;
    }

    /// <summary>
    /// Called when a Run node is encountered in the document.
    /// </summary>
    public int visitRun(final Run run) {
        indentAndAppendLine("[Run] \"" + run.getText() + "\"");

        return VisitorAction.CONTINUE;
    }

    /// <summary>
    /// Called when a SubDocument node is encountered in the document.
    /// </summary>
    public int visitSubDocument(final 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(final String text) {
        for (int i = 0; i < mDocTraversalDepth; i++) {
            mBuilder.append("|  ");
        }

        mBuilder.append(text + "\r\n");
    }

    private int mDocTraversalDepth;
    private StringBuilder mBuilder;
}

Method Summary
intvisitAbsolutePositionTab(AbsolutePositionTab tab)
Called when a AbsolutePositionTab node is encountered in the document.
intvisitBodyEnd(Body body)
Called when enumeration of the main text story in a section has ended.
intvisitBodyStart(Body body)
Called when enumeration of the main text story in a section has started.
intvisitBookmarkEnd(BookmarkEnd bookmarkEnd)
Called when an end of a bookmark is encountered in the document.
intvisitBookmarkStart(BookmarkStart bookmarkStart)
Called when a start of a bookmark is encountered in the document.
intvisitBuildingBlockEnd(BuildingBlock block)
Called when enumeration of a building block has ended.
intvisitBuildingBlockStart(BuildingBlock block)
Called when enumeration of a building block has started.
intvisitCellEnd(Cell cell)
Called when enumeration of a table cell has ended.
intvisitCellStart(Cell cell)
Called when enumeration of a table cell has started.
intvisitCommentEnd(Comment comment)
Called when enumeration of a comment text has ended.
intvisitCommentRangeEnd(CommentRangeEnd commentRangeEnd)
Called when the end of a commented range of text is encountered.
intvisitCommentRangeStart(CommentRangeStart commentRangeStart)
Called when the start of a commented range of text is encountered.
intvisitCommentStart(Comment comment)
Called when enumeration of a comment text has started.
intvisitDocumentEnd(Document doc)
Called when enumeration of the document has finished.
intvisitDocumentStart(Document doc)
Called when enumeration of the document has started.
intvisitEditableRangeEnd(EditableRangeEnd editableRangeEnd)
Called when an end of an editable range is encountered in the document.
intvisitEditableRangeStart(EditableRangeStart editableRangeStart)
Called when a start of an editable range is encountered in the document.
intvisitFieldEnd(FieldEnd fieldEnd)
Called when a field ends in the document.
intvisitFieldSeparator(FieldSeparator fieldSeparator)
Called when a field separator is encountered in the document.
intvisitFieldStart(FieldStart fieldStart)
Called when a field starts in the document.
intvisitFootnoteEnd(Footnote footnote)
Called when enumeration of a footnote or endnote text has ended.
intvisitFootnoteStart(Footnote footnote)
Called when enumeration of a footnote or endnote text has started.
intvisitFormField(FormField formField)
Called when a form field is encountered in the document.
intvisitGlossaryDocumentEnd(GlossaryDocument glossary)
Called when enumeration of a glossary document has ended.
intvisitGlossaryDocumentStart(GlossaryDocument glossary)
Called when enumeration of a glossary document has started.
intvisitGroupShapeEnd(GroupShape groupShape)
Called when enumeration of a group shape has ended.
intvisitGroupShapeStart(GroupShape groupShape)
Called when enumeration of a group shape has started.
intvisitHeaderFooterEnd(HeaderFooter headerFooter)
Called when enumeration of a header or footer in a section has ended.
intvisitHeaderFooterStart(HeaderFooter headerFooter)
Called when enumeration of a header or footer in a section has started.
intvisitOfficeMathEnd(OfficeMath officeMath)
Called when enumeration of a Office Math object has ended.
intvisitOfficeMathStart(OfficeMath officeMath)
Called when enumeration of a Office Math object has started.
intvisitParagraphEnd(Paragraph paragraph)
Called when enumeration of a paragraph has ended.
intvisitParagraphStart(Paragraph paragraph)
Called when enumeration of a paragraph has started.
intvisitRowEnd(Row row)
Called when enumeration of a table row has ended.
intvisitRowStart(Row row)
Called when enumeration of a table row has started.
intvisitRun(Run run)
Called when a run of text in the is encountered.
intvisitSectionEnd(Section section)
Called when enumeration of a section has ended.
intvisitSectionStart(Section section)
Called when enumeration of a section has started.
intvisitShapeEnd(Shape shape)
Called when enumeration of a shape has ended.
intvisitShapeStart(Shape shape)
Called when enumeration of a shape has started.
intvisitSmartTagEnd(SmartTag smartTag)
Called when enumeration of a smart tag has ended.
intvisitSmartTagStart(SmartTag smartTag)
Called when enumeration of a smart tag has started.
intvisitSpecialChar(SpecialChar specialChar)
Called when a SpecialChar node is encountered in the document.
intvisitStructuredDocumentTagEnd(StructuredDocumentTag sdt)
Called when enumeration of a structured document tag has ended.
intvisitStructuredDocumentTagStart(StructuredDocumentTag sdt)
Called when enumeration of a structured document tag has started.
intvisitSubDocument(SubDocument subDocument)
Called when a subDocument is encountered.
intvisitTableEnd(Table table)
Called when enumeration of a table has ended.
intvisitTableStart(Table table)
Called when enumeration of a table has started.
 

    • Method Detail

      • visitAbsolutePositionTab

        public int visitAbsolutePositionTab(AbsolutePositionTab tab)
                                    throws java.lang.Exception
        Called when a AbsolutePositionTab node is encountered in the document.
        Parameters:
        tab - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to use AbsolutePositionTab.
        public void documentToTxt() throws Exception {
            // This document contains two sentences separated by an absolute position tab.
            Document doc = new Document(getMyDir() + "AbsolutePositionTab.docx");
        
            // An AbsolutePositionTab is a child node of a paragraph.
            // AbsolutePositionTabs get picked up when looking for nodes of the SpecialChar type.
            Paragraph para = doc.getFirstSection().getBody().getFirstParagraph();
            AbsolutePositionTab absPositionTab = (AbsolutePositionTab) para.getChild(NodeType.SPECIAL_CHAR, 0, true);
        
            // This implementation of the DocumentVisitor pattern converts the document to plain text.
            MyDocToTxtWriter myDocToTxtWriter = new MyDocToTxtWriter();
        
            // We can run the DocumentVisitor over the whole first paragraph.
            para.accept(myDocToTxtWriter);
        
            // A tab character is placed where the AbsolutePositionTab was found.
            Assert.assertEquals(myDocToTxtWriter.getText(), "Before AbsolutePositionTab\tAfter AbsolutePositionTab");
        
            // An AbsolutePositionTab can accept a DocumentVisitor by itself too.
            myDocToTxtWriter = new MyDocToTxtWriter();
            absPositionTab.accept(myDocToTxtWriter);
        
            Assert.assertEquals(myDocToTxtWriter.getText(), "\t");
        }
        
        /// <summary>
        /// Visitor implementation that simply collects the Runs and AbsolutePositionTabs of a document as plain text.
        /// </summary>
        public static class MyDocToTxtWriter extends DocumentVisitor {
            public MyDocToTxtWriter() {
                mBuilder = new StringBuilder();
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                appendText(run.getText());
        
                // Let the visitor continue visiting other nodes.
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when an AbsolutePositionTab node is encountered in the document.
            /// </summary>
            public int visitAbsolutePositionTab(final AbsolutePositionTab tab) {
                // We'll treat the AbsolutePositionTab as a regular tab in this case.
                mBuilder.append("\t");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Adds text to the current output. Honors the enabled/disabled output flag.
            /// </summary>
            public void appendText(final String text) {
                mBuilder.append(text);
            }
        
            /// <summary>
            /// Gets the plain text of the document that was accumulated by the visitor.
            /// </summary>
            public String getText() {
                return mBuilder.toString();
            }
        
            private StringBuilder mBuilder;
        }
      • visitBodyEnd

        public int visitBodyEnd(Body body)
                        throws java.lang.Exception
        Called when enumeration of the main text story in a section has ended.
        Parameters:
        body - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitBodyStart

        public int visitBodyStart(Body body)
                          throws java.lang.Exception
        Called when enumeration of the main text story in a section has started.
        Parameters:
        body - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitBookmarkEnd

        public int visitBookmarkEnd(BookmarkEnd bookmarkEnd)
                            throws java.lang.Exception
        Called when an end of a bookmark is encountered in the document.
        Parameters:
        bookmarkEnd - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how add bookmarks and update their contents.
        public void createUpdateAndPrintBookmarks() throws Exception {
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
        
            // Add some bookmarks to the document
            for (int i = 1; i < 4; i++) {
                String bookmarkName = "Bookmark " + i;
        
                builder.startBookmark(bookmarkName);
                builder.write("Text content of " + bookmarkName);
                builder.endBookmark(bookmarkName);
            }
        
            BookmarkCollection bookmarks = doc.getRange().getBookmarks();
        
            // Look at initial values of our bookmarks
            printAllBookmarkInfo(bookmarks);
        
        
            // Update some values
            bookmarks.get(0).setName("Updated name of " + bookmarks.get(0).getName());
            bookmarks.get(1).setText("Updated text content of " + bookmarks.get(1).getName());
            bookmarks.get(2).remove();
        
            bookmarks = doc.getRange().getBookmarks();
        
            // Look at updated values of our bookmarks
            printAllBookmarkInfo(bookmarks);
        
        }
        
        /// <summary>
        /// Use an iterator and a visitor to print info of every bookmark from within a document.
        /// </summary>
        private static void printAllBookmarkInfo(final BookmarkCollection bookmarks) throws Exception {
            // Create a DocumentVisitor
            BookmarkInfoPrinter bookmarkVisitor = new BookmarkInfoPrinter();
        
            // Get the enumerator from the document's BookmarkCollection and iterate over the bookmarks
            Iterator<Bookmark> enumerator = bookmarks.iterator();
            while (enumerator.hasNext()) {
                Bookmark currentBookmark = enumerator.next();
        
                // Accept our DocumentVisitor it to print information about our bookmarks
                if (currentBookmark != null) {
                    currentBookmark.getBookmarkStart().accept(bookmarkVisitor);
                    currentBookmark.getBookmarkEnd().accept(bookmarkVisitor);
        
                    // Prints a blank line
                    System.out.println(currentBookmark.getBookmarkStart().getText());
                }
            }
        }
        
        /// <summary>
        /// Visitor that prints bookmark information to the console.
        /// </summary>
        public static class BookmarkInfoPrinter extends DocumentVisitor {
            public int visitBookmarkStart(final BookmarkStart bookmarkStart) throws Exception {
                System.out.println(MessageFormat.format("BookmarkStart name: \"{0}\", Content: \"{1}\"", bookmarkStart.getName(),
                        bookmarkStart.getBookmark().getText()));
                return VisitorAction.CONTINUE;
            }
        
            public int visitBookmarkEnd(final BookmarkEnd bookmarkEnd) {
                System.out.println(MessageFormat.format("BookmarkEnd name: \"{0}\"", bookmarkEnd.getName()));
                return VisitorAction.CONTINUE;
            }
        }
      • visitBookmarkStart

        public int visitBookmarkStart(BookmarkStart bookmarkStart)
                              throws java.lang.Exception
        Called when a start of a bookmark is encountered in the document.
        Parameters:
        bookmarkStart - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how add bookmarks and update their contents.
        public void createUpdateAndPrintBookmarks() throws Exception {
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
        
            // Add some bookmarks to the document
            for (int i = 1; i < 4; i++) {
                String bookmarkName = "Bookmark " + i;
        
                builder.startBookmark(bookmarkName);
                builder.write("Text content of " + bookmarkName);
                builder.endBookmark(bookmarkName);
            }
        
            BookmarkCollection bookmarks = doc.getRange().getBookmarks();
        
            // Look at initial values of our bookmarks
            printAllBookmarkInfo(bookmarks);
        
        
            // Update some values
            bookmarks.get(0).setName("Updated name of " + bookmarks.get(0).getName());
            bookmarks.get(1).setText("Updated text content of " + bookmarks.get(1).getName());
            bookmarks.get(2).remove();
        
            bookmarks = doc.getRange().getBookmarks();
        
            // Look at updated values of our bookmarks
            printAllBookmarkInfo(bookmarks);
        
        }
        
        /// <summary>
        /// Use an iterator and a visitor to print info of every bookmark from within a document.
        /// </summary>
        private static void printAllBookmarkInfo(final BookmarkCollection bookmarks) throws Exception {
            // Create a DocumentVisitor
            BookmarkInfoPrinter bookmarkVisitor = new BookmarkInfoPrinter();
        
            // Get the enumerator from the document's BookmarkCollection and iterate over the bookmarks
            Iterator<Bookmark> enumerator = bookmarks.iterator();
            while (enumerator.hasNext()) {
                Bookmark currentBookmark = enumerator.next();
        
                // Accept our DocumentVisitor it to print information about our bookmarks
                if (currentBookmark != null) {
                    currentBookmark.getBookmarkStart().accept(bookmarkVisitor);
                    currentBookmark.getBookmarkEnd().accept(bookmarkVisitor);
        
                    // Prints a blank line
                    System.out.println(currentBookmark.getBookmarkStart().getText());
                }
            }
        }
        
        /// <summary>
        /// Visitor that prints bookmark information to the console.
        /// </summary>
        public static class BookmarkInfoPrinter extends DocumentVisitor {
            public int visitBookmarkStart(final BookmarkStart bookmarkStart) throws Exception {
                System.out.println(MessageFormat.format("BookmarkStart name: \"{0}\", Content: \"{1}\"", bookmarkStart.getName(),
                        bookmarkStart.getBookmark().getText()));
                return VisitorAction.CONTINUE;
            }
        
            public int visitBookmarkEnd(final BookmarkEnd bookmarkEnd) {
                System.out.println(MessageFormat.format("BookmarkEnd name: \"{0}\"", bookmarkEnd.getName()));
                return VisitorAction.CONTINUE;
            }
        }
      • visitBuildingBlockEnd

        public int visitBuildingBlockEnd(BuildingBlock block)
                                 throws java.lang.Exception
        Called when enumeration of a building block has ended.

        Note: A building block node and its children are not visited when you execute a Visitor over a Document. If you want to execute a Visitor over a building block, you need to execute the visitor over GlossaryDocument or call BuildingBlock.accept(com.aspose.words.DocumentVisitor).

        Parameters:
        block - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to use GlossaryDocument and BuildingBlockCollection.
        public void glossaryDocument() throws Exception {
            Document doc = new Document();
        
            GlossaryDocument glossaryDoc = new GlossaryDocument();
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 1"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 2"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 3"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 4"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 5"));
        
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().getCount(), 5);
        
            doc.setGlossaryDocument(glossaryDoc);
        
            // There is a different ways how to get created building blocks
            Assert.assertEquals(glossaryDoc.getFirstBuildingBlock().getName(), "Block 1");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().get(1).getName(), "Block 2");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().toArray()[2].getName(), "Block 3");
            Assert.assertEquals(glossaryDoc.getLastBuildingBlock().getName(), "Block 5");
        
            // Get a block by gallery, category and name
            BuildingBlock block4 =
                    glossaryDoc.getBuildingBlock(BuildingBlockGallery.ALL, "(Empty Category)", "Block 4");
        
            // All GUIDs are the same by default
            Assert.assertEquals(block4.getGuid().toString(), "00000000-0000-0000-0000-000000000000");
        
            // To be able to uniquely identify blocks by GUID, each GUID must be unique
            // We will do that using a custom visitor
            GlossaryDocVisitor visitor = new GlossaryDocVisitor();
            glossaryDoc.accept(visitor);
        
            Assert.assertEquals(visitor.getDictionary().size(), 5);
        
            System.out.println(visitor.getText());
        
            // We can find our new blocks in Microsoft Word via Insert > Quick Parts > Building Blocks Organizer...
            doc.save(getArtifactsDir() + "BuildingBlocks.GlossaryDocument.dotx");
        }
        
        public static BuildingBlock createNewBuildingBlock(final GlossaryDocument glossaryDoc, final String buildingBlockName) {
            BuildingBlock buildingBlock = new BuildingBlock(glossaryDoc);
            buildingBlock.setName(buildingBlockName);
        
            return buildingBlock;
        }
        
        /// <summary>
        /// Simple implementation of giving each building block in a glossary document a unique GUID. Implemented as a Visitor.
        /// </summary>
        public static class GlossaryDocVisitor extends DocumentVisitor {
            public GlossaryDocVisitor() {
                mBlocksByGuid = new HashMap<>();
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public HashMap<UUID, BuildingBlock> getDictionary() {
                return mBlocksByGuid;
            }
        
            public int visitGlossaryDocumentStart(final GlossaryDocument glossary) {
                mBuilder.append("Glossary documnent found!\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGlossaryDocumentEnd(final GlossaryDocument glossary) {
                mBuilder.append("Reached end of glossary!\n");
                mBuilder.append("BuildingBlocks found: " + mBlocksByGuid.size() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockStart(final BuildingBlock block) {
                block.setGuid(UUID.randomUUID());
                mBlocksByGuid.put(block.getGuid(), block);
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockEnd(final BuildingBlock block) {
                mBuilder.append("\tVisited block \"" + block.getName() + "\"" + "\r\n");
                mBuilder.append("\t Type: " + block.getType() + "\r\n");
                mBuilder.append("\t Gallery: " + block.getGallery() + "\r\n");
                mBuilder.append("\t Behavior: " + block.getBehavior() + "\r\n");
                mBuilder.append("\t Description: " + block.getDescription() + "\r\n");
        
                return VisitorAction.CONTINUE;
            }
        
            private HashMap<UUID, BuildingBlock> mBlocksByGuid;
            private StringBuilder mBuilder;
        }
      • visitBuildingBlockStart

        public int visitBuildingBlockStart(BuildingBlock block)
                                   throws java.lang.Exception
        Called when enumeration of a building block has started.

        Note: A building block node and its children are not visited when you execute a Visitor over a Document. If you want to execute a Visitor over a building block, you need to execute the visitor over GlossaryDocument or call BuildingBlock.accept(com.aspose.words.DocumentVisitor).

        Parameters:
        block - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to use GlossaryDocument and BuildingBlockCollection.
        public void glossaryDocument() throws Exception {
            Document doc = new Document();
        
            GlossaryDocument glossaryDoc = new GlossaryDocument();
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 1"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 2"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 3"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 4"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 5"));
        
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().getCount(), 5);
        
            doc.setGlossaryDocument(glossaryDoc);
        
            // There is a different ways how to get created building blocks
            Assert.assertEquals(glossaryDoc.getFirstBuildingBlock().getName(), "Block 1");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().get(1).getName(), "Block 2");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().toArray()[2].getName(), "Block 3");
            Assert.assertEquals(glossaryDoc.getLastBuildingBlock().getName(), "Block 5");
        
            // Get a block by gallery, category and name
            BuildingBlock block4 =
                    glossaryDoc.getBuildingBlock(BuildingBlockGallery.ALL, "(Empty Category)", "Block 4");
        
            // All GUIDs are the same by default
            Assert.assertEquals(block4.getGuid().toString(), "00000000-0000-0000-0000-000000000000");
        
            // To be able to uniquely identify blocks by GUID, each GUID must be unique
            // We will do that using a custom visitor
            GlossaryDocVisitor visitor = new GlossaryDocVisitor();
            glossaryDoc.accept(visitor);
        
            Assert.assertEquals(visitor.getDictionary().size(), 5);
        
            System.out.println(visitor.getText());
        
            // We can find our new blocks in Microsoft Word via Insert > Quick Parts > Building Blocks Organizer...
            doc.save(getArtifactsDir() + "BuildingBlocks.GlossaryDocument.dotx");
        }
        
        public static BuildingBlock createNewBuildingBlock(final GlossaryDocument glossaryDoc, final String buildingBlockName) {
            BuildingBlock buildingBlock = new BuildingBlock(glossaryDoc);
            buildingBlock.setName(buildingBlockName);
        
            return buildingBlock;
        }
        
        /// <summary>
        /// Simple implementation of giving each building block in a glossary document a unique GUID. Implemented as a Visitor.
        /// </summary>
        public static class GlossaryDocVisitor extends DocumentVisitor {
            public GlossaryDocVisitor() {
                mBlocksByGuid = new HashMap<>();
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public HashMap<UUID, BuildingBlock> getDictionary() {
                return mBlocksByGuid;
            }
        
            public int visitGlossaryDocumentStart(final GlossaryDocument glossary) {
                mBuilder.append("Glossary documnent found!\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGlossaryDocumentEnd(final GlossaryDocument glossary) {
                mBuilder.append("Reached end of glossary!\n");
                mBuilder.append("BuildingBlocks found: " + mBlocksByGuid.size() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockStart(final BuildingBlock block) {
                block.setGuid(UUID.randomUUID());
                mBlocksByGuid.put(block.getGuid(), block);
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockEnd(final BuildingBlock block) {
                mBuilder.append("\tVisited block \"" + block.getName() + "\"" + "\r\n");
                mBuilder.append("\t Type: " + block.getType() + "\r\n");
                mBuilder.append("\t Gallery: " + block.getGallery() + "\r\n");
                mBuilder.append("\t Behavior: " + block.getBehavior() + "\r\n");
                mBuilder.append("\t Description: " + block.getDescription() + "\r\n");
        
                return VisitorAction.CONTINUE;
            }
        
            private HashMap<UUID, BuildingBlock> mBlocksByGuid;
            private StringBuilder mBuilder;
        }
      • visitCellEnd

        public int visitCellEnd(Cell cell)
                        throws java.lang.Exception
        Called when enumeration of a table cell has ended.
        Parameters:
        cell - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Traverse a document with a visitor that prints all tables that it encounters.
        public void tableToText() throws Exception {
            // Open the document that has tables we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            TableInfoPrinter visitor = new TableInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of all tables encountered in the document.
        /// </summary>
        public static class TableInfoPrinter extends DocumentVisitor {
            public TableInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideTable = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they consist of text from cells
                // So we are only interested in runs that are children of table nodes
                if (mVisitorIsInsideTable) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Table is encountered in the document.
            /// </summary>
            public int visitTableStart(final Table table) {
                int rows = 0;
                int columns = 0;
        
                if (table.getRows().getCount() > 0) {
                    rows = table.getRows().getCount();
                    columns = table.getFirstRow().getCount();
                }
        
                indentAndAppendLine("[Table start] Size: " + rows + "x" + columns);
                mDocTraversalDepth++;
                mVisitorIsInsideTable = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Table node is ended.
            /// </summary>
            public int visitTableEnd(final Table table) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Table end]");
                mVisitorIsInsideTable = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Row node is encountered in the document.
            /// </summary>
            public int visitRowStart(final Row row) {
                indentAndAppendLine("[Row start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Row node is ended.
            /// </summary>
            public int visitRowEnd(final Row row) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Row end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Cell node is encountered in the document.
            /// </summary>
            public int visitCellStart(final Cell cell) {
                Row row = cell.getParentRow();
                Table table = row.getParentTable();
        
                indentAndAppendLine("[Cell start] Row " + (table.indexOf(row) + 1) + ", Col "
                        + (row.indexOf(cell) + 1) + "");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Cell node is ended in the document.
            /// </summary>
            public int visitCellEnd(final Cell cell) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Cell end]");
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideTable;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitCellStart

        public int visitCellStart(Cell cell)
                          throws java.lang.Exception
        Called when enumeration of a table cell has started.
        Parameters:
        cell - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all tables that it encounters.
        public void tableToText() throws Exception {
            // Open the document that has tables we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            TableInfoPrinter visitor = new TableInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of all tables encountered in the document.
        /// </summary>
        public static class TableInfoPrinter extends DocumentVisitor {
            public TableInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideTable = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they consist of text from cells
                // So we are only interested in runs that are children of table nodes
                if (mVisitorIsInsideTable) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Table is encountered in the document.
            /// </summary>
            public int visitTableStart(final Table table) {
                int rows = 0;
                int columns = 0;
        
                if (table.getRows().getCount() > 0) {
                    rows = table.getRows().getCount();
                    columns = table.getFirstRow().getCount();
                }
        
                indentAndAppendLine("[Table start] Size: " + rows + "x" + columns);
                mDocTraversalDepth++;
                mVisitorIsInsideTable = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Table node is ended.
            /// </summary>
            public int visitTableEnd(final Table table) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Table end]");
                mVisitorIsInsideTable = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Row node is encountered in the document.
            /// </summary>
            public int visitRowStart(final Row row) {
                indentAndAppendLine("[Row start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Row node is ended.
            /// </summary>
            public int visitRowEnd(final Row row) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Row end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Cell node is encountered in the document.
            /// </summary>
            public int visitCellStart(final Cell cell) {
                Row row = cell.getParentRow();
                Table table = row.getParentTable();
        
                indentAndAppendLine("[Cell start] Row " + (table.indexOf(row) + 1) + ", Col "
                        + (row.indexOf(cell) + 1) + "");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Cell node is ended in the document.
            /// </summary>
            public int visitCellEnd(final Cell cell) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Cell end]");
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideTable;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitCommentEnd

        public int visitCommentEnd(Comment comment)
                           throws java.lang.Exception
        Called when enumeration of a comment text has ended.
        Parameters:
        comment - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all comment nodes that it encounters.
        public void commentsToText() throws Exception {
            // Open the document that has comments/comment ranges we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            CommentInfoPrinter visitor = new CommentInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of comments and comment ranges encountered in the document.
        /// </summary>
        public static class CommentInfoPrinter extends DocumentVisitor {
            public CommentInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideComment = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideComment) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeStart node is encountered in the document.
            /// </summary>
            public int visitCommentRangeStart(final CommentRangeStart commentRangeStart) {
                indentAndAppendLine("[Comment range start] ID: " + commentRangeStart.getId());
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeEnd node is encountered in the document.
            /// </summary>
            public int visitCommentRangeEnd(final CommentRangeEnd commentRangeEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment range end]");
                mVisitorIsInsideComment = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Comment node is encountered in the document.
            /// </summary>
            public int visitCommentStart(final Comment comment) {
                indentAndAppendLine(String.format("[Comment start] For comment range ID {0}, By {1} on {2}", comment.getId(),
                        comment.getAuthor(), comment.getDateTime()));
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Comment node is ended in the document.
            /// </summary>
            public int visitCommentEnd(final Comment comment) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment end]");
                mVisitorIsInsideComment = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideComment;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitCommentRangeEnd

        public int visitCommentRangeEnd(CommentRangeEnd commentRangeEnd)
                                throws java.lang.Exception
        Called when the end of a commented range of text is encountered.
        Parameters:
        commentRangeEnd - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all comment nodes that it encounters.
        public void commentsToText() throws Exception {
            // Open the document that has comments/comment ranges we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            CommentInfoPrinter visitor = new CommentInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of comments and comment ranges encountered in the document.
        /// </summary>
        public static class CommentInfoPrinter extends DocumentVisitor {
            public CommentInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideComment = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideComment) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeStart node is encountered in the document.
            /// </summary>
            public int visitCommentRangeStart(final CommentRangeStart commentRangeStart) {
                indentAndAppendLine("[Comment range start] ID: " + commentRangeStart.getId());
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeEnd node is encountered in the document.
            /// </summary>
            public int visitCommentRangeEnd(final CommentRangeEnd commentRangeEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment range end]");
                mVisitorIsInsideComment = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Comment node is encountered in the document.
            /// </summary>
            public int visitCommentStart(final Comment comment) {
                indentAndAppendLine(String.format("[Comment start] For comment range ID {0}, By {1} on {2}", comment.getId(),
                        comment.getAuthor(), comment.getDateTime()));
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Comment node is ended in the document.
            /// </summary>
            public int visitCommentEnd(final Comment comment) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment end]");
                mVisitorIsInsideComment = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideComment;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitCommentRangeStart

        public int visitCommentRangeStart(CommentRangeStart commentRangeStart)
                                  throws java.lang.Exception
        Called when the start of a commented range of text is encountered.
        Parameters:
        commentRangeStart - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all comment nodes that it encounters.
        public void commentsToText() throws Exception {
            // Open the document that has comments/comment ranges we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            CommentInfoPrinter visitor = new CommentInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of comments and comment ranges encountered in the document.
        /// </summary>
        public static class CommentInfoPrinter extends DocumentVisitor {
            public CommentInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideComment = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideComment) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeStart node is encountered in the document.
            /// </summary>
            public int visitCommentRangeStart(final CommentRangeStart commentRangeStart) {
                indentAndAppendLine("[Comment range start] ID: " + commentRangeStart.getId());
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeEnd node is encountered in the document.
            /// </summary>
            public int visitCommentRangeEnd(final CommentRangeEnd commentRangeEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment range end]");
                mVisitorIsInsideComment = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Comment node is encountered in the document.
            /// </summary>
            public int visitCommentStart(final Comment comment) {
                indentAndAppendLine(String.format("[Comment start] For comment range ID {0}, By {1} on {2}", comment.getId(),
                        comment.getAuthor(), comment.getDateTime()));
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Comment node is ended in the document.
            /// </summary>
            public int visitCommentEnd(final Comment comment) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment end]");
                mVisitorIsInsideComment = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideComment;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitCommentStart

        public int visitCommentStart(Comment comment)
                             throws java.lang.Exception
        Called when enumeration of a comment text has started.
        Parameters:
        comment - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Traverse a document with a visitor that prints all comment nodes that it encounters.
        public void commentsToText() throws Exception {
            // Open the document that has comments/comment ranges we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            CommentInfoPrinter visitor = new CommentInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of comments and comment ranges encountered in the document.
        /// </summary>
        public static class CommentInfoPrinter extends DocumentVisitor {
            public CommentInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideComment = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideComment) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeStart node is encountered in the document.
            /// </summary>
            public int visitCommentRangeStart(final CommentRangeStart commentRangeStart) {
                indentAndAppendLine("[Comment range start] ID: " + commentRangeStart.getId());
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a CommentRangeEnd node is encountered in the document.
            /// </summary>
            public int visitCommentRangeEnd(final CommentRangeEnd commentRangeEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment range end]");
                mVisitorIsInsideComment = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Comment node is encountered in the document.
            /// </summary>
            public int visitCommentStart(final Comment comment) {
                indentAndAppendLine(String.format("[Comment start] For comment range ID {0}, By {1} on {2}", comment.getId(),
                        comment.getAuthor(), comment.getDateTime()));
                mDocTraversalDepth++;
                mVisitorIsInsideComment = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Comment node is ended in the document.
            /// </summary>
            public int visitCommentEnd(final Comment comment) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Comment end]");
                mVisitorIsInsideComment = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideComment;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitDocumentEnd

        public int visitDocumentEnd(Document doc)
                            throws java.lang.Exception
        Called when enumeration of the document has finished.
        Parameters:
        doc - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitDocumentStart

        public int visitDocumentStart(Document doc)
                              throws java.lang.Exception
        Called when enumeration of the document has started.
        Parameters:
        doc - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitEditableRangeEnd

        public int visitEditableRangeEnd(EditableRangeEnd editableRangeEnd)
                                 throws java.lang.Exception
        Called when an end of an editable range is encountered in the document.
        Parameters:
        editableRangeEnd - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all editable ranges that it encounters.
        public void editableRangeToText() throws Exception {
            // Open the document that has editable ranges we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            EditableRangeInfoPrinter visitor = new EditableRangeInfoPrinter();
        
            // 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);
        
            Paragraph p = new Paragraph(doc);
            p.appendChild(new Run(doc, "Paragraph with editable range text."));
        
            // Once the visiting is complete, we can retrieve the result of the operation,
            // that in this example, has accumulated in the visitor
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about editable ranges encountered in the document.
        /// </summary>
        public static class EditableRangeInfoPrinter extends DocumentVisitor {
            public EditableRangeInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideEditableRange = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they are inside shapes, as they would be in the case of text boxes
                if (mVisitorIsInsideEditableRange) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when an EditableRange node is encountered in the document.
            /// </summary>
            public int visitEditableRangeStart(final EditableRangeStart editableRangeStart) {
                indentAndAppendLine("[EditableRange start] ID: " + editableRangeStart.getId() + " Owner: "
                        + editableRangeStart.getEditableRange().getSingleUser());
                mDocTraversalDepth++;
                mVisitorIsInsideEditableRange = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a EditableRange node is ended.
            /// </summary>
            public int visitEditableRangeEnd(final EditableRangeEnd editableRangeEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[EditableRange end]");
                mVisitorIsInsideEditableRange = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideEditableRange;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitEditableRangeStart

        public int visitEditableRangeStart(EditableRangeStart editableRangeStart)
                                   throws java.lang.Exception
        Called when a start of an editable range is encountered in the document.
        Parameters:
        editableRangeStart - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all editable ranges that it encounters.
        public void editableRangeToText() throws Exception {
            // Open the document that has editable ranges we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            EditableRangeInfoPrinter visitor = new EditableRangeInfoPrinter();
        
            // 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);
        
            Paragraph p = new Paragraph(doc);
            p.appendChild(new Run(doc, "Paragraph with editable range text."));
        
            // Once the visiting is complete, we can retrieve the result of the operation,
            // that in this example, has accumulated in the visitor
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about editable ranges encountered in the document.
        /// </summary>
        public static class EditableRangeInfoPrinter extends DocumentVisitor {
            public EditableRangeInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideEditableRange = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they are inside shapes, as they would be in the case of text boxes
                if (mVisitorIsInsideEditableRange) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when an EditableRange node is encountered in the document.
            /// </summary>
            public int visitEditableRangeStart(final EditableRangeStart editableRangeStart) {
                indentAndAppendLine("[EditableRange start] ID: " + editableRangeStart.getId() + " Owner: "
                        + editableRangeStart.getEditableRange().getSingleUser());
                mDocTraversalDepth++;
                mVisitorIsInsideEditableRange = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a EditableRange node is ended.
            /// </summary>
            public int visitEditableRangeEnd(final EditableRangeEnd editableRangeEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[EditableRange end]");
                mVisitorIsInsideEditableRange = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideEditableRange;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitFieldEnd

        public int visitFieldEnd(FieldEnd fieldEnd)
                         throws java.lang.Exception
        Called when a field ends in the document.

        For more info see visitFieldStart(com.aspose.words.FieldStart)

        Parameters:
        fieldEnd - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all fields that it encounters.
        public void fieldToText() throws Exception {
            // Open the document that has fields that we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            FieldInfoPrinter visitor = new FieldInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about fields encountered in the document.
        /// </summary>
        public static class FieldInfoPrinter extends DocumentVisitor {
            public FieldInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideField = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideField) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldStart node is encountered in the document.
            /// </summary>
            public int visitFieldStart(final FieldStart fieldStart) {
                indentAndAppendLine("[Field start] FieldType: " + fieldStart.getFieldType());
                mDocTraversalDepth++;
                mVisitorIsInsideField = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldEnd node is encountered in the document.
            /// </summary>
            public int visitFieldEnd(final FieldEnd fieldEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Field end]");
                mVisitorIsInsideField = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldSeparator node is encountered in the document.
            /// </summary>
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) {
                indentAndAppendLine("[FieldSeparator]");
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideField;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitFieldSeparator

        public int visitFieldSeparator(FieldSeparator fieldSeparator)
                               throws java.lang.Exception
        Called when a field separator is encountered in the document.

        The field separator separates field code from field value in the document. Note that some fields have only field code and do not have field separator and field value.

        For more info see visitFieldStart(com.aspose.words.FieldStart)

        Parameters:
        fieldSeparator - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all fields that it encounters.
        public void fieldToText() throws Exception {
            // Open the document that has fields that we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            FieldInfoPrinter visitor = new FieldInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about fields encountered in the document.
        /// </summary>
        public static class FieldInfoPrinter extends DocumentVisitor {
            public FieldInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideField = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideField) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldStart node is encountered in the document.
            /// </summary>
            public int visitFieldStart(final FieldStart fieldStart) {
                indentAndAppendLine("[Field start] FieldType: " + fieldStart.getFieldType());
                mDocTraversalDepth++;
                mVisitorIsInsideField = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldEnd node is encountered in the document.
            /// </summary>
            public int visitFieldEnd(final FieldEnd fieldEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Field end]");
                mVisitorIsInsideField = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldSeparator node is encountered in the document.
            /// </summary>
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) {
                indentAndAppendLine("[FieldSeparator]");
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideField;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitFieldStart

        public int visitFieldStart(FieldStart fieldStart)
                           throws java.lang.Exception
        Called when a field starts in the document.

        A field in a Word Word document consists of a field code and field value.

        For example, a field that displays a page number can be represented as follows:

        [FieldStart]PAGE[FieldSeparator]98[FieldEnd]

        The field separator separates field code from field value in the document. Note that some fields have only field code and do not have field separator and field value.

        Fields can be nested.

        Parameters:
        fieldStart - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all fields that it encounters.
        public void fieldToText() throws Exception {
            // Open the document that has fields that we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            FieldInfoPrinter visitor = new FieldInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about fields encountered in the document.
        /// </summary>
        public static class FieldInfoPrinter extends DocumentVisitor {
            public FieldInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideField = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideField) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldStart node is encountered in the document.
            /// </summary>
            public int visitFieldStart(final FieldStart fieldStart) {
                indentAndAppendLine("[Field start] FieldType: " + fieldStart.getFieldType());
                mDocTraversalDepth++;
                mVisitorIsInsideField = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldEnd node is encountered in the document.
            /// </summary>
            public int visitFieldEnd(final FieldEnd fieldEnd) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Field end]");
                mVisitorIsInsideField = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a FieldSeparator node is encountered in the document.
            /// </summary>
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) {
                indentAndAppendLine("[FieldSeparator]");
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideField;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitFootnoteEnd

        public int visitFootnoteEnd(Footnote footnote)
                            throws java.lang.Exception
        Called when enumeration of a footnote or endnote text has ended.
        Parameters:
        footnote - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all footnotes that it encounters.
        public void footnoteToText() throws Exception {
            // Open the document that has footnotes we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            FootnoteInfoPrinter visitor = new FootnoteInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about footnotes encountered in the document.
        /// </summary>
        public static class FootnoteInfoPrinter extends DocumentVisitor {
            public FootnoteInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideFootnote = false;
            }
        
            /// <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 Footnote node is encountered in the document.
            /// </summary>
            public int visitFootnoteStart(final Footnote footnote) {
                indentAndAppendLine("[Footnote start] Type: " + footnote.getFootnoteType());
                mDocTraversalDepth++;
                mVisitorIsInsideFootnote = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Footnote node is ended.
            /// </summary>
            public int visitFootnoteEnd(final Footnote footnote) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Footnote end]");
                mVisitorIsInsideFootnote = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideFootnote) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideFootnote;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitFootnoteStart

        public int visitFootnoteStart(Footnote footnote)
                              throws java.lang.Exception
        Called when enumeration of a footnote or endnote text has started.
        Parameters:
        footnote - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Traverse a document with a visitor that prints all footnotes that it encounters.
        public void footnoteToText() throws Exception {
            // Open the document that has footnotes we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            FootnoteInfoPrinter visitor = new FootnoteInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about footnotes encountered in the document.
        /// </summary>
        public static class FootnoteInfoPrinter extends DocumentVisitor {
            public FootnoteInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideFootnote = false;
            }
        
            /// <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 Footnote node is encountered in the document.
            /// </summary>
            public int visitFootnoteStart(final Footnote footnote) {
                indentAndAppendLine("[Footnote start] Type: " + footnote.getFootnoteType());
                mDocTraversalDepth++;
                mVisitorIsInsideFootnote = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Footnote node is ended.
            /// </summary>
            public int visitFootnoteEnd(final Footnote footnote) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Footnote end]");
                mVisitorIsInsideFootnote = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideFootnote) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideFootnote;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitFormField

        public int visitFormField(FormField formField)
                          throws java.lang.Exception
        Called when a form field is encountered in the document.
        Parameters:
        formField - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }
      • visitGlossaryDocumentEnd

        public int visitGlossaryDocumentEnd(GlossaryDocument glossary)
                                    throws java.lang.Exception
        Called when enumeration of a glossary document has ended.

        Note: A glossary document node and its children are not visited when you execute a Visitor over a Document. If you want to execute a Visitor over a glossary document, you need to call GlossaryDocument.accept(com.aspose.words.DocumentVisitor).

        Parameters:
        glossary - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to use GlossaryDocument and BuildingBlockCollection.
        public void glossaryDocument() throws Exception {
            Document doc = new Document();
        
            GlossaryDocument glossaryDoc = new GlossaryDocument();
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 1"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 2"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 3"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 4"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 5"));
        
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().getCount(), 5);
        
            doc.setGlossaryDocument(glossaryDoc);
        
            // There is a different ways how to get created building blocks
            Assert.assertEquals(glossaryDoc.getFirstBuildingBlock().getName(), "Block 1");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().get(1).getName(), "Block 2");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().toArray()[2].getName(), "Block 3");
            Assert.assertEquals(glossaryDoc.getLastBuildingBlock().getName(), "Block 5");
        
            // Get a block by gallery, category and name
            BuildingBlock block4 =
                    glossaryDoc.getBuildingBlock(BuildingBlockGallery.ALL, "(Empty Category)", "Block 4");
        
            // All GUIDs are the same by default
            Assert.assertEquals(block4.getGuid().toString(), "00000000-0000-0000-0000-000000000000");
        
            // To be able to uniquely identify blocks by GUID, each GUID must be unique
            // We will do that using a custom visitor
            GlossaryDocVisitor visitor = new GlossaryDocVisitor();
            glossaryDoc.accept(visitor);
        
            Assert.assertEquals(visitor.getDictionary().size(), 5);
        
            System.out.println(visitor.getText());
        
            // We can find our new blocks in Microsoft Word via Insert > Quick Parts > Building Blocks Organizer...
            doc.save(getArtifactsDir() + "BuildingBlocks.GlossaryDocument.dotx");
        }
        
        public static BuildingBlock createNewBuildingBlock(final GlossaryDocument glossaryDoc, final String buildingBlockName) {
            BuildingBlock buildingBlock = new BuildingBlock(glossaryDoc);
            buildingBlock.setName(buildingBlockName);
        
            return buildingBlock;
        }
        
        /// <summary>
        /// Simple implementation of giving each building block in a glossary document a unique GUID. Implemented as a Visitor.
        /// </summary>
        public static class GlossaryDocVisitor extends DocumentVisitor {
            public GlossaryDocVisitor() {
                mBlocksByGuid = new HashMap<>();
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public HashMap<UUID, BuildingBlock> getDictionary() {
                return mBlocksByGuid;
            }
        
            public int visitGlossaryDocumentStart(final GlossaryDocument glossary) {
                mBuilder.append("Glossary documnent found!\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGlossaryDocumentEnd(final GlossaryDocument glossary) {
                mBuilder.append("Reached end of glossary!\n");
                mBuilder.append("BuildingBlocks found: " + mBlocksByGuid.size() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockStart(final BuildingBlock block) {
                block.setGuid(UUID.randomUUID());
                mBlocksByGuid.put(block.getGuid(), block);
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockEnd(final BuildingBlock block) {
                mBuilder.append("\tVisited block \"" + block.getName() + "\"" + "\r\n");
                mBuilder.append("\t Type: " + block.getType() + "\r\n");
                mBuilder.append("\t Gallery: " + block.getGallery() + "\r\n");
                mBuilder.append("\t Behavior: " + block.getBehavior() + "\r\n");
                mBuilder.append("\t Description: " + block.getDescription() + "\r\n");
        
                return VisitorAction.CONTINUE;
            }
        
            private HashMap<UUID, BuildingBlock> mBlocksByGuid;
            private StringBuilder mBuilder;
        }
      • visitGlossaryDocumentStart

        public int visitGlossaryDocumentStart(GlossaryDocument glossary)
                                      throws java.lang.Exception
        Called when enumeration of a glossary document has started.

        Note: A glossary document node and its children are not visited when you execute a Visitor over a Document. If you want to execute a Visitor over a glossary document, you need to call GlossaryDocument.accept(com.aspose.words.DocumentVisitor).

        Parameters:
        glossary - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to use GlossaryDocument and BuildingBlockCollection.
        public void glossaryDocument() throws Exception {
            Document doc = new Document();
        
            GlossaryDocument glossaryDoc = new GlossaryDocument();
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 1"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 2"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 3"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 4"));
            glossaryDoc.appendChild(createNewBuildingBlock(glossaryDoc, "Block 5"));
        
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().getCount(), 5);
        
            doc.setGlossaryDocument(glossaryDoc);
        
            // There is a different ways how to get created building blocks
            Assert.assertEquals(glossaryDoc.getFirstBuildingBlock().getName(), "Block 1");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().get(1).getName(), "Block 2");
            Assert.assertEquals(glossaryDoc.getBuildingBlocks().toArray()[2].getName(), "Block 3");
            Assert.assertEquals(glossaryDoc.getLastBuildingBlock().getName(), "Block 5");
        
            // Get a block by gallery, category and name
            BuildingBlock block4 =
                    glossaryDoc.getBuildingBlock(BuildingBlockGallery.ALL, "(Empty Category)", "Block 4");
        
            // All GUIDs are the same by default
            Assert.assertEquals(block4.getGuid().toString(), "00000000-0000-0000-0000-000000000000");
        
            // To be able to uniquely identify blocks by GUID, each GUID must be unique
            // We will do that using a custom visitor
            GlossaryDocVisitor visitor = new GlossaryDocVisitor();
            glossaryDoc.accept(visitor);
        
            Assert.assertEquals(visitor.getDictionary().size(), 5);
        
            System.out.println(visitor.getText());
        
            // We can find our new blocks in Microsoft Word via Insert > Quick Parts > Building Blocks Organizer...
            doc.save(getArtifactsDir() + "BuildingBlocks.GlossaryDocument.dotx");
        }
        
        public static BuildingBlock createNewBuildingBlock(final GlossaryDocument glossaryDoc, final String buildingBlockName) {
            BuildingBlock buildingBlock = new BuildingBlock(glossaryDoc);
            buildingBlock.setName(buildingBlockName);
        
            return buildingBlock;
        }
        
        /// <summary>
        /// Simple implementation of giving each building block in a glossary document a unique GUID. Implemented as a Visitor.
        /// </summary>
        public static class GlossaryDocVisitor extends DocumentVisitor {
            public GlossaryDocVisitor() {
                mBlocksByGuid = new HashMap<>();
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public HashMap<UUID, BuildingBlock> getDictionary() {
                return mBlocksByGuid;
            }
        
            public int visitGlossaryDocumentStart(final GlossaryDocument glossary) {
                mBuilder.append("Glossary documnent found!\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGlossaryDocumentEnd(final GlossaryDocument glossary) {
                mBuilder.append("Reached end of glossary!\n");
                mBuilder.append("BuildingBlocks found: " + mBlocksByGuid.size() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockStart(final BuildingBlock block) {
                block.setGuid(UUID.randomUUID());
                mBlocksByGuid.put(block.getGuid(), block);
                return VisitorAction.CONTINUE;
            }
        
            public int visitBuildingBlockEnd(final BuildingBlock block) {
                mBuilder.append("\tVisited block \"" + block.getName() + "\"" + "\r\n");
                mBuilder.append("\t Type: " + block.getType() + "\r\n");
                mBuilder.append("\t Gallery: " + block.getGallery() + "\r\n");
                mBuilder.append("\t Behavior: " + block.getBehavior() + "\r\n");
                mBuilder.append("\t Description: " + block.getDescription() + "\r\n");
        
                return VisitorAction.CONTINUE;
            }
        
            private HashMap<UUID, BuildingBlock> mBlocksByGuid;
            private StringBuilder mBuilder;
        }
      • visitGroupShapeEnd

        public int visitGroupShapeEnd(GroupShape groupShape)
                              throws java.lang.Exception
        Called when enumeration of a group shape has ended.
        Parameters:
        groupShape - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to create a group of shapes, and let it accept a visitor
        public void groupOfShapes() throws Exception {
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
        
            // If you need to create "NonPrimitive" shapes, like SingleCornerSnipped, TopCornersSnipped, DiagonalCornersSnipped,
            // TopCornersOneRoundedOneSnipped, SingleCornerRounded, TopCornersRounded, DiagonalCornersRounded
            // please use DocumentBuilder.InsertShape methods
            Shape balloon = new Shape(doc, ShapeType.BALLOON);
            balloon.setWidth(200.0);
            balloon.setHeight(200.0);
            balloon.setStrokeColor(Color.RED);
        
            Shape cube = new Shape(doc, ShapeType.CUBE);
            cube.setWidth(100.0);
            cube.setHeight(100.0);
            cube.setStrokeColor(Color.BLUE);
        
            GroupShape group = new GroupShape(doc);
            group.appendChild(balloon);
            group.appendChild(cube);
        
            Assert.assertTrue(group.isGroup());
            builder.insertNode(group);
        
            ShapeInfoPrinter printer = new ShapeInfoPrinter();
            group.accept(printer);
        
            System.out.println(printer.getText());
        }
        
        /// <summary>
        /// Visitor that prints shape group contents information to the console.
        /// </summary>
        public static class ShapeInfoPrinter extends DocumentVisitor {
            public ShapeInfoPrinter() {
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public int visitGroupShapeStart(final GroupShape groupShape) {
                mBuilder.append("Shape group started:\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGroupShapeEnd(final GroupShape groupShape) {
                mBuilder.append("End of shape group\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeStart(final Shape shape) {
                mBuilder.append("\tShape - " + shape.getShapeType() + ":\r\n");
                mBuilder.append("\t\tWidth: " + shape.getWidth() + "\r\n");
                mBuilder.append("\t\tHeight: " + shape.getHeight() + "\r\n");
                mBuilder.append("\t\tStroke color: " + shape.getStroke().getColor() + "\r\n");
                mBuilder.append("\t\tFill color: " + shape.getFill().getColor() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeEnd(final Shape shape) {
                mBuilder.append("\tEnd of shape\r\n");
                return VisitorAction.CONTINUE;
            }
        
            private StringBuilder mBuilder;
        }
      • visitGroupShapeStart

        public int visitGroupShapeStart(GroupShape groupShape)
                                throws java.lang.Exception
        Called when enumeration of a group shape has started.
        Parameters:
        groupShape - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Shows how to create a group of shapes, and let it accept a visitor
        public void groupOfShapes() throws Exception {
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
        
            // If you need to create "NonPrimitive" shapes, like SingleCornerSnipped, TopCornersSnipped, DiagonalCornersSnipped,
            // TopCornersOneRoundedOneSnipped, SingleCornerRounded, TopCornersRounded, DiagonalCornersRounded
            // please use DocumentBuilder.InsertShape methods
            Shape balloon = new Shape(doc, ShapeType.BALLOON);
            balloon.setWidth(200.0);
            balloon.setHeight(200.0);
            balloon.setStrokeColor(Color.RED);
        
            Shape cube = new Shape(doc, ShapeType.CUBE);
            cube.setWidth(100.0);
            cube.setHeight(100.0);
            cube.setStrokeColor(Color.BLUE);
        
            GroupShape group = new GroupShape(doc);
            group.appendChild(balloon);
            group.appendChild(cube);
        
            Assert.assertTrue(group.isGroup());
            builder.insertNode(group);
        
            ShapeInfoPrinter printer = new ShapeInfoPrinter();
            group.accept(printer);
        
            System.out.println(printer.getText());
        }
        
        /// <summary>
        /// Visitor that prints shape group contents information to the console.
        /// </summary>
        public static class ShapeInfoPrinter extends DocumentVisitor {
            public ShapeInfoPrinter() {
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public int visitGroupShapeStart(final GroupShape groupShape) {
                mBuilder.append("Shape group started:\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGroupShapeEnd(final GroupShape groupShape) {
                mBuilder.append("End of shape group\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeStart(final Shape shape) {
                mBuilder.append("\tShape - " + shape.getShapeType() + ":\r\n");
                mBuilder.append("\t\tWidth: " + shape.getWidth() + "\r\n");
                mBuilder.append("\t\tHeight: " + shape.getHeight() + "\r\n");
                mBuilder.append("\t\tStroke color: " + shape.getStroke().getColor() + "\r\n");
                mBuilder.append("\t\tFill color: " + shape.getFill().getColor() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeEnd(final Shape shape) {
                mBuilder.append("\tEnd of shape\r\n");
                return VisitorAction.CONTINUE;
            }
        
            private StringBuilder mBuilder;
        }
      • visitHeaderFooterEnd

        public int visitHeaderFooterEnd(HeaderFooter headerFooter)
                                throws java.lang.Exception
        Called when enumeration of a header or footer in a section has ended.
        Parameters:
        headerFooter - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all header/footer nodes that it encounters.
        public void headerFooterToText() throws Exception {
            // Open the document that has headers and/or footers we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            HeaderFooterInfoPrinter visitor = new HeaderFooterInfoPrinter();
        
            // Accepring 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
            System.out.println(visitor.getText());
        
            // An alternative way of visiting a document's header/footers section-by-section is by accessing the collection
            // We can also turn it into an array
            HeaderFooter[] headerFooters = doc.getFirstSection().getHeadersFooters().toArray();
            Assert.assertEquals(headerFooters.length, 6);
        }
        
        /// <summary>
        /// This Visitor implementation prints information about HeaderFooter nodes encountered in the document.
        /// </summary>
        public static class HeaderFooterInfoPrinter extends DocumentVisitor {
            public HeaderFooterInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideHeaderFooter = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideHeaderFooter) indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a HeaderFooter node is encountered in the document.
            /// </summary>
            public int visitHeaderFooterStart(final HeaderFooter headerFooter) {
                indentAndAppendLine("[HeaderFooter start] HeaderFooterType: " + headerFooter.getHeaderFooterType());
                mDocTraversalDepth++;
                mVisitorIsInsideHeaderFooter = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a HeaderFooter node is ended.
            /// </summary>
            public int visitHeaderFooterEnd(final HeaderFooter headerFooter) {
                mDocTraversalDepth--;
                indentAndAppendLine("[HeaderFooter end]");
                mVisitorIsInsideHeaderFooter = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideHeaderFooter;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitHeaderFooterStart

        public int visitHeaderFooterStart(HeaderFooter headerFooter)
                                  throws java.lang.Exception
        Called when enumeration of a header or footer in a section has started.
        Parameters:
        headerFooter - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all header/footer nodes that it encounters.
        public void headerFooterToText() throws Exception {
            // Open the document that has headers and/or footers we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            HeaderFooterInfoPrinter visitor = new HeaderFooterInfoPrinter();
        
            // Accepring 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
            System.out.println(visitor.getText());
        
            // An alternative way of visiting a document's header/footers section-by-section is by accessing the collection
            // We can also turn it into an array
            HeaderFooter[] headerFooters = doc.getFirstSection().getHeadersFooters().toArray();
            Assert.assertEquals(headerFooters.length, 6);
        }
        
        /// <summary>
        /// This Visitor implementation prints information about HeaderFooter nodes encountered in the document.
        /// </summary>
        public static class HeaderFooterInfoPrinter extends DocumentVisitor {
            public HeaderFooterInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideHeaderFooter = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideHeaderFooter) indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a HeaderFooter node is encountered in the document.
            /// </summary>
            public int visitHeaderFooterStart(final HeaderFooter headerFooter) {
                indentAndAppendLine("[HeaderFooter start] HeaderFooterType: " + headerFooter.getHeaderFooterType());
                mDocTraversalDepth++;
                mVisitorIsInsideHeaderFooter = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a HeaderFooter node is ended.
            /// </summary>
            public int visitHeaderFooterEnd(final HeaderFooter headerFooter) {
                mDocTraversalDepth--;
                indentAndAppendLine("[HeaderFooter end]");
                mVisitorIsInsideHeaderFooter = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideHeaderFooter;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitOfficeMathEnd

        public int visitOfficeMathEnd(OfficeMath officeMath)
                              throws java.lang.Exception
        Called when enumeration of a Office Math object has ended.
        Parameters:
        officeMath - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all offise math nodes that it encounters.
        public void officeMathToText() throws Exception {
            // Open the document that has office math objects we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            OfficeMathInfoPrinter visitor = new OfficeMathInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about office math objects encountered in the document.
        /// </summary>
        public static class OfficeMathInfoPrinter extends DocumentVisitor {
            public OfficeMathInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideOfficeMath = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideOfficeMath) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when an OfficeMath node is encountered in the document.
            /// </summary>
            public int visitOfficeMathStart(final OfficeMath officeMath) {
                indentAndAppendLine("[OfficeMath start] Math object type: " + officeMath.getMathObjectType());
                mDocTraversalDepth++;
                mVisitorIsInsideOfficeMath = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a OfficeMath node is ended.
            /// </summary>
            public int visitOfficeMathEnd(final OfficeMath officeMath) {
                mDocTraversalDepth--;
                indentAndAppendLine("[OfficeMath end]");
                mVisitorIsInsideOfficeMath = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideOfficeMath;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitOfficeMathStart

        public int visitOfficeMathStart(OfficeMath officeMath)
                                throws java.lang.Exception
        Called when enumeration of a Office Math object has started.
        Parameters:
        officeMath - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all offise math nodes that it encounters.
        public void officeMathToText() throws Exception {
            // Open the document that has office math objects we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            OfficeMathInfoPrinter visitor = new OfficeMathInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about office math objects encountered in the document.
        /// </summary>
        public static class OfficeMathInfoPrinter extends DocumentVisitor {
            public OfficeMathInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideOfficeMath = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideOfficeMath) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when an OfficeMath node is encountered in the document.
            /// </summary>
            public int visitOfficeMathStart(final OfficeMath officeMath) {
                indentAndAppendLine("[OfficeMath start] Math object type: " + officeMath.getMathObjectType());
                mDocTraversalDepth++;
                mVisitorIsInsideOfficeMath = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a OfficeMath node is ended.
            /// </summary>
            public int visitOfficeMathEnd(final OfficeMath officeMath) {
                mDocTraversalDepth--;
                indentAndAppendLine("[OfficeMath end]");
                mVisitorIsInsideOfficeMath = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideOfficeMath;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitParagraphEnd

        public int visitParagraphEnd(Paragraph paragraph)
                             throws java.lang.Exception
        Called when enumeration of a paragraph has ended.
        Parameters:
        paragraph - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitParagraphStart

        public int visitParagraphStart(Paragraph paragraph)
                               throws java.lang.Exception
        Called when enumeration of a paragraph has started.
        Parameters:
        paragraph - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitRowEnd

        public int visitRowEnd(Row row)
                       throws java.lang.Exception
        Called when enumeration of a table row has ended.
        Parameters:
        row - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Traverse a document with a visitor that prints all tables that it encounters.
        public void tableToText() throws Exception {
            // Open the document that has tables we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            TableInfoPrinter visitor = new TableInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of all tables encountered in the document.
        /// </summary>
        public static class TableInfoPrinter extends DocumentVisitor {
            public TableInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideTable = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they consist of text from cells
                // So we are only interested in runs that are children of table nodes
                if (mVisitorIsInsideTable) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Table is encountered in the document.
            /// </summary>
            public int visitTableStart(final Table table) {
                int rows = 0;
                int columns = 0;
        
                if (table.getRows().getCount() > 0) {
                    rows = table.getRows().getCount();
                    columns = table.getFirstRow().getCount();
                }
        
                indentAndAppendLine("[Table start] Size: " + rows + "x" + columns);
                mDocTraversalDepth++;
                mVisitorIsInsideTable = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Table node is ended.
            /// </summary>
            public int visitTableEnd(final Table table) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Table end]");
                mVisitorIsInsideTable = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Row node is encountered in the document.
            /// </summary>
            public int visitRowStart(final Row row) {
                indentAndAppendLine("[Row start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Row node is ended.
            /// </summary>
            public int visitRowEnd(final Row row) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Row end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Cell node is encountered in the document.
            /// </summary>
            public int visitCellStart(final Cell cell) {
                Row row = cell.getParentRow();
                Table table = row.getParentTable();
        
                indentAndAppendLine("[Cell start] Row " + (table.indexOf(row) + 1) + ", Col "
                        + (row.indexOf(cell) + 1) + "");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Cell node is ended in the document.
            /// </summary>
            public int visitCellEnd(final Cell cell) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Cell end]");
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideTable;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitRowStart

        public int visitRowStart(Row row)
                         throws java.lang.Exception
        Called when enumeration of a table row has started.
        Parameters:
        row - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all tables that it encounters.
        public void tableToText() throws Exception {
            // Open the document that has tables we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            TableInfoPrinter visitor = new TableInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of all tables encountered in the document.
        /// </summary>
        public static class TableInfoPrinter extends DocumentVisitor {
            public TableInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideTable = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they consist of text from cells
                // So we are only interested in runs that are children of table nodes
                if (mVisitorIsInsideTable) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Table is encountered in the document.
            /// </summary>
            public int visitTableStart(final Table table) {
                int rows = 0;
                int columns = 0;
        
                if (table.getRows().getCount() > 0) {
                    rows = table.getRows().getCount();
                    columns = table.getFirstRow().getCount();
                }
        
                indentAndAppendLine("[Table start] Size: " + rows + "x" + columns);
                mDocTraversalDepth++;
                mVisitorIsInsideTable = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Table node is ended.
            /// </summary>
            public int visitTableEnd(final Table table) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Table end]");
                mVisitorIsInsideTable = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Row node is encountered in the document.
            /// </summary>
            public int visitRowStart(final Row row) {
                indentAndAppendLine("[Row start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Row node is ended.
            /// </summary>
            public int visitRowEnd(final Row row) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Row end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Cell node is encountered in the document.
            /// </summary>
            public int visitCellStart(final Cell cell) {
                Row row = cell.getParentRow();
                Table table = row.getParentTable();
        
                indentAndAppendLine("[Cell start] Row " + (table.indexOf(row) + 1) + ", Col "
                        + (row.indexOf(cell) + 1) + "");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Cell node is ended in the document.
            /// </summary>
            public int visitCellEnd(final Cell cell) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Cell end]");
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideTable;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitRun

        public int visitRun(Run run)
                    throws java.lang.Exception
        Called when a run of text in the is encountered.
        Parameters:
        run - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitSectionEnd

        public int visitSectionEnd(Section section)
                           throws java.lang.Exception
        Called when enumeration of a section has ended.
        Parameters:
        section - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitSectionStart

        public int visitSectionStart(Section section)
                             throws java.lang.Exception
        Called when enumeration of a section has started.
        Parameters:
        section - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitShapeEnd

        public int visitShapeEnd(Shape shape)
                         throws java.lang.Exception
        Called when enumeration of a shape has ended.
        Parameters:
        shape - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Shows how to create a group of shapes, and let it accept a visitor
        public void groupOfShapes() throws Exception {
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
        
            // If you need to create "NonPrimitive" shapes, like SingleCornerSnipped, TopCornersSnipped, DiagonalCornersSnipped,
            // TopCornersOneRoundedOneSnipped, SingleCornerRounded, TopCornersRounded, DiagonalCornersRounded
            // please use DocumentBuilder.InsertShape methods
            Shape balloon = new Shape(doc, ShapeType.BALLOON);
            balloon.setWidth(200.0);
            balloon.setHeight(200.0);
            balloon.setStrokeColor(Color.RED);
        
            Shape cube = new Shape(doc, ShapeType.CUBE);
            cube.setWidth(100.0);
            cube.setHeight(100.0);
            cube.setStrokeColor(Color.BLUE);
        
            GroupShape group = new GroupShape(doc);
            group.appendChild(balloon);
            group.appendChild(cube);
        
            Assert.assertTrue(group.isGroup());
            builder.insertNode(group);
        
            ShapeInfoPrinter printer = new ShapeInfoPrinter();
            group.accept(printer);
        
            System.out.println(printer.getText());
        }
        
        /// <summary>
        /// Visitor that prints shape group contents information to the console.
        /// </summary>
        public static class ShapeInfoPrinter extends DocumentVisitor {
            public ShapeInfoPrinter() {
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public int visitGroupShapeStart(final GroupShape groupShape) {
                mBuilder.append("Shape group started:\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGroupShapeEnd(final GroupShape groupShape) {
                mBuilder.append("End of shape group\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeStart(final Shape shape) {
                mBuilder.append("\tShape - " + shape.getShapeType() + ":\r\n");
                mBuilder.append("\t\tWidth: " + shape.getWidth() + "\r\n");
                mBuilder.append("\t\tHeight: " + shape.getHeight() + "\r\n");
                mBuilder.append("\t\tStroke color: " + shape.getStroke().getColor() + "\r\n");
                mBuilder.append("\t\tFill color: " + shape.getFill().getColor() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeEnd(final Shape shape) {
                mBuilder.append("\tEnd of shape\r\n");
                return VisitorAction.CONTINUE;
            }
        
            private StringBuilder mBuilder;
        }
      • visitShapeStart

        public int visitShapeStart(Shape shape)
                           throws java.lang.Exception
        Called when enumeration of a shape has started.
        Parameters:
        shape - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Shows how to create a group of shapes, and let it accept a visitor
        public void groupOfShapes() throws Exception {
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
        
            // If you need to create "NonPrimitive" shapes, like SingleCornerSnipped, TopCornersSnipped, DiagonalCornersSnipped,
            // TopCornersOneRoundedOneSnipped, SingleCornerRounded, TopCornersRounded, DiagonalCornersRounded
            // please use DocumentBuilder.InsertShape methods
            Shape balloon = new Shape(doc, ShapeType.BALLOON);
            balloon.setWidth(200.0);
            balloon.setHeight(200.0);
            balloon.setStrokeColor(Color.RED);
        
            Shape cube = new Shape(doc, ShapeType.CUBE);
            cube.setWidth(100.0);
            cube.setHeight(100.0);
            cube.setStrokeColor(Color.BLUE);
        
            GroupShape group = new GroupShape(doc);
            group.appendChild(balloon);
            group.appendChild(cube);
        
            Assert.assertTrue(group.isGroup());
            builder.insertNode(group);
        
            ShapeInfoPrinter printer = new ShapeInfoPrinter();
            group.accept(printer);
        
            System.out.println(printer.getText());
        }
        
        /// <summary>
        /// Visitor that prints shape group contents information to the console.
        /// </summary>
        public static class ShapeInfoPrinter extends DocumentVisitor {
            public ShapeInfoPrinter() {
                mBuilder = new StringBuilder();
            }
        
            public String getText() {
                return mBuilder.toString();
            }
        
            public int visitGroupShapeStart(final GroupShape groupShape) {
                mBuilder.append("Shape group started:\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitGroupShapeEnd(final GroupShape groupShape) {
                mBuilder.append("End of shape group\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeStart(final Shape shape) {
                mBuilder.append("\tShape - " + shape.getShapeType() + ":\r\n");
                mBuilder.append("\t\tWidth: " + shape.getWidth() + "\r\n");
                mBuilder.append("\t\tHeight: " + shape.getHeight() + "\r\n");
                mBuilder.append("\t\tStroke color: " + shape.getStroke().getColor() + "\r\n");
                mBuilder.append("\t\tFill color: " + shape.getFill().getColor() + "\r\n");
                return VisitorAction.CONTINUE;
            }
        
            public int visitShapeEnd(final Shape shape) {
                mBuilder.append("\tEnd of shape\r\n");
                return VisitorAction.CONTINUE;
            }
        
            private StringBuilder mBuilder;
        }
      • visitSmartTagEnd

        public int visitSmartTagEnd(SmartTag smartTag)
                            throws java.lang.Exception
        Called when enumeration of a smart tag has ended.
        Parameters:
        smartTag - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all smart tag nodes that it encounters.
        public void smartTagToText() throws Exception {
            // Open the document that has smart tags we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.SmartTag.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            SmartTagInfoPrinter visitor = new SmartTagInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about smart tags encountered in the document.
        /// </summary>
        public static class SmartTagInfoPrinter extends DocumentVisitor {
            public SmartTagInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideSmartTag = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideSmartTag) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SmartTag node is encountered in the document.
            /// </summary>
            public int visitSmartTagStart(final SmartTag smartTag) {
                indentAndAppendLine("[SmartTag start] Name: " + smartTag.getElement());
                mDocTraversalDepth++;
                mVisitorIsInsideSmartTag = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a SmartTag node is ended.
            /// </summary>
            public int visitSmartTagEnd(final SmartTag smartTag) {
                mDocTraversalDepth--;
                indentAndAppendLine("[SmartTag end]");
                mVisitorIsInsideSmartTag = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideSmartTag;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitSmartTagStart

        public int visitSmartTagStart(SmartTag smartTag)
                              throws java.lang.Exception
        Called when enumeration of a smart tag has started.
        Parameters:
        smartTag - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all smart tag nodes that it encounters.
        public void smartTagToText() throws Exception {
            // Open the document that has smart tags we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.SmartTag.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            SmartTagInfoPrinter visitor = new SmartTagInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about smart tags encountered in the document.
        /// </summary>
        public static class SmartTagInfoPrinter extends DocumentVisitor {
            public SmartTagInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideSmartTag = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideSmartTag) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SmartTag node is encountered in the document.
            /// </summary>
            public int visitSmartTagStart(final SmartTag smartTag) {
                indentAndAppendLine("[SmartTag start] Name: " + smartTag.getElement());
                mDocTraversalDepth++;
                mVisitorIsInsideSmartTag = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a SmartTag node is ended.
            /// </summary>
            public int visitSmartTagEnd(final SmartTag smartTag) {
                mDocTraversalDepth--;
                indentAndAppendLine("[SmartTag end]");
                mVisitorIsInsideSmartTag = false;
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideSmartTag;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitSpecialChar

        public int visitSpecialChar(SpecialChar specialChar)
                            throws java.lang.Exception
        Called when a SpecialChar node is encountered in the document. This method is not be called for generic control characters (see ControlChar) that can be present in the document.
        Parameters:
        specialChar - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }
      • visitStructuredDocumentTagEnd

        public int visitStructuredDocumentTagEnd(StructuredDocumentTag sdt)
                                         throws java.lang.Exception
        Called when enumeration of a structured document tag has ended.
        Parameters:
        sdt - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structured document tag nodes that it encounters.
        public void structuredDocumentTagToText() throws Exception {
            // Open the document that has structured document tags we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            StructuredDocumentTagInfoPrinter visitor = new StructuredDocumentTagInfoPrinter();
        
            // Accepring 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about structured document tags encountered in the document.
        /// </summary>
        public static class StructuredDocumentTagInfoPrinter extends DocumentVisitor {
            public StructuredDocumentTagInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideStructuredDocumentTag = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideStructuredDocumentTag) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a StructuredDocumentTag node is encountered in the document.
            /// </summary>
            public int visitStructuredDocumentTagStart(final StructuredDocumentTag sdt) {
                indentAndAppendLine("[StructuredDocumentTag start] Title: " + sdt.getTitle());
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a StructuredDocumentTag node is ended.
            /// </summary>
            public int visitStructuredDocumentTagEnd(final StructuredDocumentTag sdt) {
                mDocTraversalDepth--;
                indentAndAppendLine("[StructuredDocumentTag end]");
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideStructuredDocumentTag;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitStructuredDocumentTagStart

        public int visitStructuredDocumentTagStart(StructuredDocumentTag sdt)
                                           throws java.lang.Exception
        Called when enumeration of a structured document tag has started.
        Parameters:
        sdt - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structured document tag nodes that it encounters.
        public void structuredDocumentTagToText() throws Exception {
            // Open the document that has structured document tags we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            StructuredDocumentTagInfoPrinter visitor = new StructuredDocumentTagInfoPrinter();
        
            // Accepring 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about structured document tags encountered in the document.
        /// </summary>
        public static class StructuredDocumentTagInfoPrinter extends DocumentVisitor {
            public StructuredDocumentTagInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideStructuredDocumentTag = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                if (mVisitorIsInsideStructuredDocumentTag) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a StructuredDocumentTag node is encountered in the document.
            /// </summary>
            public int visitStructuredDocumentTagStart(final StructuredDocumentTag sdt) {
                indentAndAppendLine("[StructuredDocumentTag start] Title: " + sdt.getTitle());
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a StructuredDocumentTag node is ended.
            /// </summary>
            public int visitStructuredDocumentTagEnd(final StructuredDocumentTag sdt) {
                mDocTraversalDepth--;
                indentAndAppendLine("[StructuredDocumentTag end]");
        
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideStructuredDocumentTag;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitSubDocument

        public int visitSubDocument(SubDocument subDocument)
                            throws java.lang.Exception
        Called when a subDocument is encountered.
        Parameters:
        subDocument - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all structure nodes that it encounters.
        public void docStructureToText() throws Exception {
            // Open the document that has nodes we want to print the info of
            Document doc = new Document(getMyDir() + "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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about sections, bodies, paragraphs and runs encountered in the document.
        /// </summary>
        public static class DocStructurePrinter extends 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 int visitDocumentStart(final Document doc) {
                int childNodeCount = doc.getChildNodes(NodeType.ANY, true).getCount();
        
                // 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 int visitDocumentEnd(final 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 int visitSectionStart(final Section section) {
                // Get the index of our section within the document
                NodeCollection docSections = section.getDocument().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 int visitSectionEnd(final Section section) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Section end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Body node is encountered in the document.
            /// </summary>
            public int visitBodyStart(final Body body) {
                int paragraphCount = body.getParagraphs().getCount();
                indentAndAppendLine("[Body start] Paragraphs: " + paragraphCount);
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Body node is ended.
            /// </summary>
            public int visitBodyEnd(final Body body) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Body end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Paragraph node is encountered in the document.
            /// </summary>
            public int visitParagraphStart(final Paragraph paragraph) {
                indentAndAppendLine("[Paragraph start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Paragraph node is ended.
            /// </summary>
            public int visitParagraphEnd(final Paragraph paragraph) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Paragraph end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                indentAndAppendLine("[Run] \"" + run.getText() + "\"");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a SubDocument node is encountered in the document.
            /// </summary>
            public int visitSubDocument(final 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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitTableEnd

        public int visitTableEnd(Table table)
                         throws java.lang.Exception
        Called when enumeration of a table has ended.
        Parameters:
        table - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Implements the Visitor Pattern to remove all content formatted as hidden from the document.
        public void removeHiddenContentFromDocument() throws Exception {
            // Open the document we want to remove hidden content from.
            Document doc = new Document(getMyDir() + "Font.Hidden.doc");
        
            // Create an object that inherits from the DocumentVisitor class.
            RemoveHiddenContentVisitor hiddenContentRemover = new RemoveHiddenContentVisitor();
        
            // 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).
        
            // We can run it over the entire the document like so:
            doc.accept(hiddenContentRemover);
        
            // Or we can run it on only a specific node.
            Paragraph para = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 4, true);
            para.accept(hiddenContentRemover);
        
            // Or over a different type of node like below.
            Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
            table.accept(hiddenContentRemover);
        
            doc.save(getArtifactsDir() + "Font.Hidden.doc");
        
        }
        
        /**
         * This class when executed will remove all hidden content from the Document. Implemented as a Visitor.
         */
        private class RemoveHiddenContentVisitor extends DocumentVisitor {
            /**
             * Called when a FieldStart node is encountered in the document.
             */
            public int visitFieldStart(final FieldStart fieldStart) throws Exception {
                // If this node is hidden, then remove it.
                if (isHidden(fieldStart)) {
                    fieldStart.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldEnd node is encountered in the document.
             */
            public int visitFieldEnd(final FieldEnd fieldEnd) throws Exception {
                if (isHidden(fieldEnd)) {
                    fieldEnd.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FieldSeparator node is encountered in the document.
             */
            public int visitFieldSeparator(final FieldSeparator fieldSeparator) throws Exception {
                if (isHidden(fieldSeparator)) {
                    fieldSeparator.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Run node is encountered in the document.
             */
            public int visitRun(final Run run) throws Exception {
                if (isHidden(run)) {
                    run.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Paragraph node is encountered in the document.
             */
            public int visitParagraphStart(final Paragraph paragraph) throws Exception {
                if (isHidden(paragraph)) {
                    paragraph.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a FormField is encountered in the document.
             */
            public int visitFormField(final FormField field) throws Exception {
                if (isHidden(field)) {
                    field.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a GroupShape is encountered in the document.
             */
            public int visitGroupShapeStart(final GroupShape groupShape) throws Exception {
                if (isHidden(groupShape)) {
                    groupShape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Shape is encountered in the document.
             */
            public int visitShapeStart(final Shape shape) throws Exception {
                if (isHidden(shape)) {
                    shape.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Comment is encountered in the document.
             */
            public int visitCommentStart(final Comment comment) throws Exception {
                if (isHidden(comment)) {
                    comment.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a Footnote is encountered in the document.
             */
            public int visitFootnoteStart(final Footnote footnote) throws Exception {
                if (isHidden(footnote)) {
                    footnote.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Table node is ended in the document.
             */
            public int visitTableEnd(final Table table) {
                // At the moment there is no way to tell if a particular Table/Row/Cell is hidden.
                // Instead, if the content of a table is hidden, then all inline child nodes of the table should be
                // hidden and thus removed by previous visits as well. This will result in the container being empty
                // so if this is the case we know to remove the table node.
                //
                // Note that a table which is not hidden but simply has no content will not be affected by this algorthim,
                // as technically they are not completely empty (for example a properly formed Cell will have at least
                // an empty paragraph in it)
                if (!table.hasChildNodes()) {
                    table.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Cell node is ended in the document.
             */
            public int visitCellEnd(final Cell cell) {
                if (!cell.hasChildNodes() && cell.getParentNode() != null) {
                    cell.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when visiting of a Row node is ended in the document.
             */
            public int visitRowEnd(final Row row) {
                if (!row.hasChildNodes() && row.getParentNode() != null) {
                    row.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Called when a SpecialCharacter is encountered in the document.
             */
            public int visitSpecialChar(final SpecialChar character) throws Exception {
                if (isHidden(character)) {
                    character.remove();
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /**
             * Returns true if the node passed is set as hidden, returns false if it is visible.
             */
            private boolean isHidden(final Node node) {
                if (node instanceof Inline) {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Inline currentNode = (Inline) node;
                    return currentNode.getFont().getHidden();
                } else if (node.getNodeType() == NodeType.PARAGRAPH) {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph) node;
                    return para.getParagraphBreakFont().getHidden();
                } else if (node instanceof ShapeBase) {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase) node;
                    return shape.getFont().getHidden();
                } else if (node instanceof InlineStory) {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory) node;
                    return inlineStory.getFont().getHidden();
                }
        
                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return false;
            }
        }

        Example:

        Traverse a document with a visitor that prints all tables that it encounters.
        public void tableToText() throws Exception {
            // Open the document that has tables we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            TableInfoPrinter visitor = new TableInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of all tables encountered in the document.
        /// </summary>
        public static class TableInfoPrinter extends DocumentVisitor {
            public TableInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideTable = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they consist of text from cells
                // So we are only interested in runs that are children of table nodes
                if (mVisitorIsInsideTable) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Table is encountered in the document.
            /// </summary>
            public int visitTableStart(final Table table) {
                int rows = 0;
                int columns = 0;
        
                if (table.getRows().getCount() > 0) {
                    rows = table.getRows().getCount();
                    columns = table.getFirstRow().getCount();
                }
        
                indentAndAppendLine("[Table start] Size: " + rows + "x" + columns);
                mDocTraversalDepth++;
                mVisitorIsInsideTable = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Table node is ended.
            /// </summary>
            public int visitTableEnd(final Table table) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Table end]");
                mVisitorIsInsideTable = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Row node is encountered in the document.
            /// </summary>
            public int visitRowStart(final Row row) {
                indentAndAppendLine("[Row start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Row node is ended.
            /// </summary>
            public int visitRowEnd(final Row row) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Row end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Cell node is encountered in the document.
            /// </summary>
            public int visitCellStart(final Cell cell) {
                Row row = cell.getParentRow();
                Table table = row.getParentTable();
        
                indentAndAppendLine("[Cell start] Row " + (table.indexOf(row) + 1) + ", Col "
                        + (row.indexOf(cell) + 1) + "");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Cell node is ended in the document.
            /// </summary>
            public int visitCellEnd(final Cell cell) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Cell end]");
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideTable;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }
      • visitTableStart

        public int visitTableStart(Table table)
                           throws java.lang.Exception
        Called when enumeration of a table has started.
        Parameters:
        table - The object that is being visited.
        Returns:
        A VisitorAction value that specifies how to continue the enumeration.

        Example:

        Traverse a document with a visitor that prints all tables that it encounters.
        public void tableToText() throws Exception {
            // Open the document that has tables we want to print the info of
            Document doc = new Document(getMyDir() + "DocumentVisitor.Destination.docx");
        
            // Create an object that inherits from the DocumentVisitor class
            TableInfoPrinter visitor = new TableInfoPrinter();
        
            // 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
            System.out.println(visitor.getText());
        }
        
        /// <summary>
        /// This Visitor implementation prints information about and contents of all tables encountered in the document.
        /// </summary>
        public static class TableInfoPrinter extends DocumentVisitor {
            public TableInfoPrinter() {
                mBuilder = new StringBuilder();
                mVisitorIsInsideTable = false;
            }
        
            /// <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 Run node is encountered in the document.
            /// </summary>
            public int visitRun(final Run run) {
                // We want to print the contents of runs, but only if they consist of text from cells
                // So we are only interested in runs that are children of table nodes
                if (mVisitorIsInsideTable) {
                    indentAndAppendLine("[Run] \"" + run.getText() + "\"");
                }
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Table is encountered in the document.
            /// </summary>
            public int visitTableStart(final Table table) {
                int rows = 0;
                int columns = 0;
        
                if (table.getRows().getCount() > 0) {
                    rows = table.getRows().getCount();
                    columns = table.getFirstRow().getCount();
                }
        
                indentAndAppendLine("[Table start] Size: " + rows + "x" + columns);
                mDocTraversalDepth++;
                mVisitorIsInsideTable = true;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Table node is ended.
            /// </summary>
            public int visitTableEnd(final Table table) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Table end]");
                mVisitorIsInsideTable = false;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Row node is encountered in the document.
            /// </summary>
            public int visitRowStart(final Row row) {
                indentAndAppendLine("[Row start]");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Row node is ended.
            /// </summary>
            public int visitRowEnd(final Row row) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Row end]");
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when a Cell node is encountered in the document.
            /// </summary>
            public int visitCellStart(final Cell cell) {
                Row row = cell.getParentRow();
                Table table = row.getParentTable();
        
                indentAndAppendLine("[Cell start] Row " + (table.indexOf(row) + 1) + ", Col "
                        + (row.indexOf(cell) + 1) + "");
                mDocTraversalDepth++;
        
                return VisitorAction.CONTINUE;
            }
        
            /// <summary>
            /// Called when the visiting of a Cell node is ended in the document.
            /// </summary>
            public int visitCellEnd(final Cell cell) {
                mDocTraversalDepth--;
                indentAndAppendLine("[Cell end]");
                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(final String text) {
                for (int i = 0; i < mDocTraversalDepth; i++) {
                    mBuilder.append("|  ");
                }
        
                mBuilder.append(text + "\r\n");
            }
        
            private boolean mVisitorIsInsideTable;
            private int mDocTraversalDepth;
            private StringBuilder mBuilder;
        }