Issue with Unexpected Visitor Behavior When Shape Has Alternative Text

Hello Aspose Support,

I am experiencing unexpected behavior while traversing shapes using the DocumentVisitor in Aspose.Words. Normally, the visit order I expect is:

visitShapeStart
→ visitGroupShapeStart
→ visitShapeStart
→ visitShapeEnd
→ visitShapeStart
→ visitShapeEnd
→ visitGroupShapeEnd
visitShapeEnd

However, when processing a document where a shape (image) has alternative text, the visitor stops further traversal after visitShapeStart → visitGroupShapeStart, and the subsequent expected visits do not occur. If I remove the alternative text from the image, the visitor behaves as expected.

Could you please explain why the presence of alternative text affects the visitor traversal? Is there any workaround or recommended approach to ensure correct visiting even when alternative text is present?

I am attaching the document for your investigation.

Thank you,
Nevena
row2.docx (15.6 KB)

@NevenaB

Hi Nevena,

The behavior you’re experiencing with the DocumentVisitor when traversing shapes that have alternative text is due to the additional processing required for those elements, which can lead to certain nodes being skipped.

Solution: To address this issue, you can implement the following steps:

  1. Check Visitor Implementation: Ensure that your visitor implementation correctly handles the visitShapeStart and visitGroupShapeStart methods. Adding logging can help verify if the visitor is being called as expected.

  2. Alternative Text Handling: Review the visitor’s logic to ensure it does not inadvertently skip nodes based on the presence of alternative text. Adjust the logic as necessary to ensure it continues visiting all shapes.

  3. Use a Custom Visitor: If the default behavior is insufficient, create a custom visitor that explicitly handles shapes with alternative text. This will give you more precise control over the traversal process.

  4. Testing with Different Documents: Test with various documents that have different structures and alternative text to determine if the issue is consistent across all cases or specific to certain documents.

Here’s a minimal code snippet to illustrate how you might implement a custom visitor:

class CustomVisitor extends DocumentVisitor {
    @Override
    public int visitShapeStart(Shape shape) {
        // Your logic here
        return VisitorAction.CONTINUE;
    }

    @Override
    public int visitGroupShapeStart(GroupShape groupShape) {
        // Your logic here
        return VisitorAction.CONTINUE;
    }

    // Implement other visit methods as needed
}

// Usage
Document doc = new Document("your-document.docx");
CustomVisitor visitor = new CustomVisitor();
doc.accept(visitor);

This approach will provide you with greater control over how shapes with alternative text are processed.

Please implement these suggestions and let me know if you need further assistance!

Thank you for your prompt reply and the sample code.

I would like to clarify that I have already implemented a custom visitor, similar to your example. Unfortunately, it still does not work as expected when dealing specifically with group shapes that contain inner shapes with alternative text. In these cases, the visitor traversal does not follow the expected order—some shapes are not visited at all. If the alternative text is removed from the inner shapes, the visitor behaves as intended.

Could you please test your visitor implementation using the document I provided, which contains a paragraph with a group shape whose inner shapes have alternative text? I believe this scenario better reflects the issue.

Thank you for your assistance.

@NevenaB Unfortunately, I cannot reproduce the problem on my side using the latest 25.8 version of Aspose.Words. Here is my test code:

Document doc = new Document(@"C:\Temp\in.docx");
doc.Accept(new TestVisitor());
private class TestVisitor : DocumentVisitor
{
    public override VisitorAction VisitShapeStart(Shape shape)
    {
        Console.WriteLine("ShapeStart");
        return VisitorAction.Continue;
    }

    public override VisitorAction VisitShapeEnd(Shape shape)
    {
        Console.WriteLine("ShapeEnd");
        return VisitorAction.Continue;
    }

    public override VisitorAction VisitGroupShapeStart(GroupShape groupShape)
    {
        Console.WriteLine("GroupShapeStart");
        return VisitorAction.Continue;
    }

    public override VisitorAction VisitGroupShapeEnd(GroupShape groupShape)
    {
        Console.WriteLine("GroupShapeEnd");
        return VisitorAction.Continue;
    }
}

The output is the following:

ShapeStart
GroupShapeStart
ShapeStart
ShapeEnd
ShapeStart
ShapeEnd
GroupShapeEnd
ShapeEnd

The output corresponds the document structure: