How to Get Nested Bookmarks of Bookmark using Java

Hello team, we meet again.
How can I get all the child bookmarks in the parent bookmark?
For example:
[ [name] [age] [sex] [address] ]
The result i want:
[name]、 [age]、 [sex]、 [address]
Looking forward to your reply, thanks.
input.docx (11.5 KB)
output.docx (10 KB)

@asukavon

Please note that Bookmark is a “facade” object that encapsulates two nodes BookmarkStart and BookmarkEnd in a document tree and allows to work with a bookmark as a single object. You can find the nested/children bookmarks of bookmark 'person' using the following code example. Hope this helps you.

Document doc = new Document(MyDir + "input.docx");
Document docClone = (Document)doc.Clone(true);

foreach (Bookmark book in docClone.Range.Bookmarks)
{
    book.Text = "";
}

Bookmark bookmark = docClone.Range.Bookmarks["person"];

foreach (Bookmark bm in docClone.Range.Bookmarks)
{
    if (bm.Name == bookmark.Name)
        continue;

    Node currentNode = bm.BookmarkStart.NextPreOrder(doc);
    while (true && currentNode != null)
    {
        if (currentNode.NodeType == NodeType.BookmarkStart)
        {
            Console.WriteLine(((BookmarkStart)currentNode).Name + " is child bookmark of " + bookmark.Name);
            break;
        }

        currentNode = currentNode.NextPreOrder(doc);
    }
}

Thank you for your reply!
Sorry i still can’t get the correct result.
Looking forward to your help again, thanks!

Below is my code imitating you:

    String dataDir ="E:\\lj\\test\\";

    Document doc = new Document(dataDir + "input.docx");
    Document docClone = doc.deepClone();

    for(Bookmark bookmark: docClone.getRange().getBookmarks()){
        bookmark.setText("");
    }

    Bookmark bookmark = docClone.getRange().getBookmarks().get("person");

    for(Bookmark bm: docClone.getRange().getBookmarks()){
        if(bm.getName().equals(bookmark.getName())){
            continue;
        }

        Node currentNode = bm.getBookmarkStart().nextPreOrder(doc);
        while(currentNode != null){
            if(currentNode.getNodeType() == NodeType.BOOKMARK_START){
                System.out.println(((BookmarkStart)currentNode).getName()+ " is child bookmark of " + bookmark.getName());
                break;
            }

            currentNode = currentNode.nextPreOrder(doc);
        }
    }

The result i expected:
name is child bookmark of person
age is child bookmark of person
sex is child bookmark of person
adress is child bookmark of person

Actual result:
list_bookmark is child bookmark of person
child_salao is child bookmark of person
child_boat is child bookmark of person
person is child bookmark of person
age is child bookmark of person
sex is child bookmark of person
adress is child bookmark of person
input.docx (15 KB)

@asukavon

We are working over your query and will get back to you soon.

Understand, wait for your good news :ok_hand:

@asukavon

Perhaps, you are using old version of Aspose.Words. We have tested the scenario using the latest version of Aspose.Words for Java 21.9 and have not found the shared issue. So, please use Aspose.Words for Java 21.9.

Thank you for your recommendation, is there any other solution?
I have used the latest version of the Aspose.Word for Java 21.9, but I cannot get the correct result after changing the test file.
The following is my test document.
test.docx (14 KB)
In addition, If possible our team hopes to develop on the existing version. :rofl:

@asukavon

We suggest you please extract the contents between bookmarks using the code example shared in the following article. The extracted document will contain the nested bookmarks of desired bookmark.

Thank you for your reply, and sorry to interrupt your holiday. :persevere:
I use this method to get the child bookmarks, but our colleagues report that if the nested bookmark exists in the form, the content of the entire form will be extracted, which is not in line with our original intention.
How can I prevent this from happening?

Document doc = new Document("E:\\lj\\test\\input.docx");

Bookmark bookmark = doc.getRange().getBookmarks().get("person");

BookmarkStart bookmarkStart = bookmark.getBookmarkStart();
BookmarkEnd bookmarkEnd = bookmark.getBookmarkEnd();
//extract the content between these nodes including the bookmark.
ArrayList extractedNodesInclusive = extractContent(bookmarkStart, bookmarkEnd, true);
Document dstDoc = generateDocument(doc, extractedNodesInclusive);
dstDoc.save("E:\\lj\\test\\ExtractContent.docx");

The following is my test file.
input.docx (15.5 KB)
ExtractContent.docx (6.5 KB)

@asukavon

Unfortunately, the extractContent method does not work correctly for tables. You just need to iterate over desired BookmarkStart and BookmarkEnd nodes.

Please use following simple code example to get your desired output.

Document doc = new Document(MyDir + "input.doc");
Document docClone = doc.deepClone();

for(Bookmark bookmark: docClone.getRange().getBookmarks()){
    bookmark.setText("");
}

Bookmark bookmark = docClone.getRange().getBookmarks().get("person");

Node currentNode = bookmark.getBookmarkStart().nextPreOrder(doc);
while(currentNode != null && currentNode != bookmark.getBookmarkEnd()){
    if(currentNode.getNodeType() == NodeType.BOOKMARK_START){
        System.out.println(((BookmarkStart)currentNode).getName()+ " is child bookmark of " + bookmark.getName());
    }

    currentNode = currentNode.nextPreOrder(doc);
}

Thank you for your suggestion.
I have solved this problem with your help, appreciate your support. :laughing:

Hello, we meet again.
Before using the method you provided, the problem was solved very concisely, thank you very much.
This time we encountered a more complex table, but we could not get the child bookmarks in the nested bookmarks correctly again.
Below is my code imitating you:

    Document doc = new Document(MyDir + "input.docx");
    Document docClone = doc.deepClone();

    for(Bookmark bookmark: docClone.getRange().getBookmarks()){
        bookmark.setText("");
    }

    Bookmark bookmark = docClone.getRange().getBookmarks().get("person");

    Node currentNode = bookmark.getBookmarkStart().nextPreOrder(doc);
    while(currentNode != null && currentNode != bookmark.getBookmarkEnd()){
        if(currentNode.getNodeType() == NodeType.BOOKMARK_START){
            System.out.println(((BookmarkStart)currentNode).getName()+ " is child bookmark of " + bookmark.getName());
        }

        currentNode = currentNode.nextPreOrder(doc);
    }

}

The result i expected:
a is child bookmark of person
b is child bookmark of person
c is child bookmark of person
d is child bookmark of person
e is child bookmark of person
f is child bookmark of person
g is child bookmark of person
h is child bookmark of person
Actual result:
NULL

The following is my test document.
input.docx (13.3 KB)
How can I solve this problem? Looking forward to your reply, thanks.

@asukavon The following code thrown an exception on my side.

for(Bookmark bookmark: docClone.getRange().getBookmarks()){
    bookmark.setText("");
}

That is expected, because by setting bookmark text to empty string removes all bookmark content including nested bookmarks. You can modify the code like the following to get the expected result:

for(Bookmark bookmark: docClone.getRange().getBookmarks()) {
    if (bookmark.isColumn())
        bookmark.setText("");
}