Bookmark is not found in the document

Hi,

I using this code to load bookmark from the document. For some reason the following bookmark is not found (null returned):

Document mDocument = new Aspose.Words.Document(DocFileName);
Bookmark FieldBookmark = mDocument.Range.Bookmarks["START110634388897141927273F"];

Document attached.

Thanks,
Stanislav

Hi Stanislav,

Thanks for your query. I have tested the scenario and have not found the issue with shared Bookmark while using latest version of Aspose.Words for .NET. Please use the latest version of Aspose.Words for .NET and check the attached image file for detail. Please let us know if you have any more queries.

Hi,

Thank you for the answer. I checked the problem again and the scenario when it happens a little bit more complex that i thought from the begginning:

Document mDocument = new Aspose.Words.Document(DocFileName);
Bookmark AddendumApprovedBookmark = mDocument.Range.Bookmarks["START111634388897195832833F"];
AddendumApprovedBookmark.Text = " ";
mDocument.Save(DocFileName);
Bookmark AddendumBookmark = mDocument.Range.Bookmarks["START110634388897141927273F"];

Null will be returned for AddendumBookmark.

Thank you,
Stanislav.

Hi Stanislav,

Thanks for your query. I have worked with your document and have found that the bookmark (START110634388897141927273F) is inside (START111634388897195832833F).

When the following line of code is executed the bookmark (START110634388897141927273F) is set to null because it is inside (START111634388897195832833F). Please see the attached image for detail and let us know if you have any more queries.

AddendumApprovedBookmark.Text = " ";

Hi,

Thank you very much for the answer. This is very strange that AddendumBookmark bookmark is inside of AddendumApprovedBookmark bookmark. Our tool should not allow this situation.

Anyway i need to find a solution for that and i have another question:
I used AddendumApprovedBookmark.Text = " " to clear all bookmark content and to add space into it. Can you suggest another way to clear bookmark content without deleting inner bookmarks?

Thanks,
Stanislav.

Hi Stanislav,

Thanks for your query. Please use the following code snippet for your requirement. Please let us know if you have any more queries.

Document doc = new Document(MyDir + "temp.doc");
Aspose.Words.Bookmark bm = doc.Range.Bookmarks["START111634388897195832833F"];
ArrayList nodes = new ArrayList();
// Extract all nodes between bookmark START111634388897195832833F 
Node bEnd = bm.BookmarkEnd;
Node currentNode = bm.BookmarkStart.NextPreOrder(doc);
while (currentNode != bEnd)
{
    currentNode = currentNode.NextPreOrder(doc);
    nodes.Add(currentNode);
}
foreach (Node node in nodes)
{
    // If inner bookmark found
    if (node.NodeType == NodeType.BookmarkStart)
        break;

    // set text of Run nodes to empty string for Bookmark START111634388897195832833F
    if (node.NodeType == NodeType.Run)
        ((Run)node).Text = " ";
}
doc.Save(MyDir + "AsposeOut.docx");

Hi,

Thank you very much!! I will try this code.

Thanks,
Stanislav.

Hi Stanislav,

Please feel free to ask if you have any question about Aspose.Words, we will be happy to help you.

Hi, I tried this code and unfortunately it does not work.
I am attaching the document. I tried to replace all the content of bookmark START2634865914793021928F to " " using the proposed code and it didn’t work. The table, the image and the numbering remained and were not deleted.
I want to remind that i want to replace all content of bookmark by space (" "), but without deleting internal bookmarks. Can you advice how to fix this code?
Thanks,
Stanislav.

Hi Stanislav,

Thanks for your inquiry. I have modified the code according to your shared document. The bookmark (START2634865914793021928F) contains some other BookmarkStart and BookmarkEnd nodes. Please use following code snippet for your requirement and let us know if you have any more queries.

Document doc = new Document(MyDir + "in.docx");
Aspose.Words.Bookmark bm = doc.Range.Bookmarks["START2634865914793021928F"];
ArrayList nodes = new ArrayList();
Node currentNode = bm.BookmarkStart.NextPreOrder(doc);
bool isRemoving = true;
while (currentNode != null && isRemoving)
{
    if (currentNode.NodeType == NodeType.BookmarkStart)
    {
        currentNode = currentNode.NextPreOrder(doc);
        continue;
    }
    if (currentNode.NodeType == NodeType.BookmarkEnd && currentNode != bm.BookmarkEnd)
    {
        currentNode = currentNode.NextPreOrder(doc);
        continue;
    }
    if (currentNode == bm.BookmarkEnd)
    {
        isRemoving = false;
        continue;
    }
    nodes.Add(currentNode);
    Node nextNode = currentNode.NextPreOrder(doc);
    currentNode = nextNode;
}
foreach (Node node in nodes)
{
    node.Remove();
}
doc.Save(MyDir + "AsposeOut.docx");

Hi,

Thanks you fro the answer. Unfortunately this code also makes problems.
After its executing i cant access anymore the START2634865914793021928F bookmark.

Bookmark FieldBookmark = mDocument.Range.Bookmarks["START2634865914793021928F"];
returns null.

Looks like the bookmark was deleted.

Thanks,
Stas.

Hi Stanislav,

Thanks for your inquiry. I have tested the scenario and have not found any issue with Bookmark (START2634865914793021928F) while using latest version of Aspose.Words for .NET. Please use the latest version of Aspose.Words for .NET.

I have attached the output document file for your kind reference.

Hi,

Thanks you for the answer. Please use the following code:

Document mDocument = new Aspose.Words.Document("plstemp2.doc");
Bookmark AddendumBookmark = mDocument.Range.Bookmarks["START2634865914793021928F"];
ClearBookmark(AddendumBookmark, mDocument);
mDocument.Save("plstemp2.doc");
AddendumBookmark = mDocument.Range.Bookmarks["START2634865914793021928F"];
private void ClearBookmark(Bookmark bookmark, Aspose.Words.Document document)
{
    ArrayList nodes = new ArrayList();
    Node currentNode = bookmark.BookmarkStart.NextPreOrder(document);
    bool isRemoving = true;

    while (currentNode != null && isRemoving)
    {
        if (currentNode.NodeType == NodeType.BookmarkStart)
        {
            currentNode = currentNode.NextPreOrder(document);
            continue;
        }

        if (currentNode.NodeType == NodeType.BookmarkEnd && currentNode != bookmark.BookmarkEnd)
        {
            currentNode = currentNode.NextPreOrder(document);
            continue;
        }

        if (currentNode == bookmark.BookmarkEnd)
        {
            isRemoving = false;
            continue;
        }

        nodes.Add(currentNode);
        Node nextNode = currentNode.NextPreOrder(document);
        currentNode = nextNode;
    }

    foreach (Node node in nodes)
    {
        node.Remove();
    }
}

null is returned. I dont want to delete the bookmark itself only to clean it’s content without deleting inner bookmarks.

Thanks,
Stanislav

Hi Stanislav,

Thanks for your inquiry. I have modified the ClearBookmark method. Please see the highlighted section of code. The Bookmark (START2634865914793021928F) has nodes (Paragraphs, Runs, Table, Row, Cell, Shape, Bookmark Start and BookmarkEnd). If you want to remove all nodes, you only need to use node.Remove() method. In your current scenario, I have done the followings in ClearBookmark method:

  1. Set Run.Text as empty string
  2. Remove lists
  3. Remove Tables
  4. Remove Shapes

If your document has some other types of node, you can modified ClearBookmark method according to your requirements. Please let us know if you have any more queries.

private void ClearBookmark(Aspose.Words.Bookmark bookmark, Aspose.Words.Document document)
{
    ArrayList nodes = new ArrayList();
    Node currentNode = bookmark.BookmarkStart.NextPreOrder(document);
    bool isRemoving = true;
    while (currentNode != null && isRemoving)
    {
        if (currentNode.NodeType == NodeType.BookmarkStart)
        {
            currentNode = currentNode.NextPreOrder(document);
            continue;
        }
        if (currentNode.NodeType == NodeType.BookmarkEnd && currentNode != bookmark.BookmarkEnd)
        {
            currentNode = currentNode.NextPreOrder(document);
            continue;
        }
        if (currentNode == bookmark.BookmarkEnd)
        {
            isRemoving = false;
            continue;
        }
        nodes.Add(currentNode);
        Node nextNode = currentNode.NextPreOrder(document);
        currentNode = nextNode;
    }
    foreach (Node node in nodes)
    {
        // Clear text contents
        if (node.NodeType == NodeType.Run)
            ((Run)node).Text = "";
        // Removes bullets and numbering from all paragraphs 
        if (node.NodeType == NodeType.Paragraph)
            if (((Paragraph)node).ListFormat.IsListItem)
            {
                ((Paragraph)node).ListFormat.RemoveNumbers();
            }
        // Remove Shape
        if (node.NodeType == NodeType.Shape)
            node.Remove();
        // Remove table row
        if (node.NodeType == NodeType.Row)
            node.Remove();
    }
}

Hi,

Thank you for the answer. I tested this code and the problem is that although it deletes all visible content but it remains after its execution a lot of empty paragraphs. When i tried to remove all empty paragraphs i probably deleted the inner bookmark. Look like one of the paragraphs contains bookmark and i don’t want to delete it. How can i know when paragraph contains bookmark? What i need is that ClearBookmark will clear all content and all paragraphs but will remain inner bookmarks.

Thanks,
Stanislav.

Hi,

if there are more paragraphs and runs and the content is resetted to an withspace the paragraphs are still be there and would cause blank lines.

And other problem you would have, if the bookmarks are in tables, if you then delete the rows there would also be gone.

Use the iterating code given to collect all inner bookmark starts and ends in the right order. Replace everything inside the outer bookmark by the one space " ". That was the start of the excusion. And the depending on your code insert the bookmark starts and ends before or after the withspace. the best I think would be tho replace the content of the outer bookmark by “” so there is no space and only insert the inner bookmarks

Best Regard,
Babett just an other Aspose User

Hi Stanislav,

Thanks for your inquiry. You can use Paragraph HasChildNodes property to check either Paragraph has bookmark nodes or not. Please find use the following code snippet to remove such Paragraph nodes.

private void ClearBookmark(Aspose.Words.Bookmark bookmark, Aspose.Words.Document document)
{
    ArrayList nodes = new ArrayList();
    Node currentNode = bookmark.BookmarkStart.NextPreOrder(document);
    bool isRemoving = true;
    while (currentNode != null && isRemoving)
    {
        if (currentNode.NodeType == NodeType.BookmarkStart)
        {
            currentNode = currentNode.NextPreOrder(document);
            continue;
        }
        if (currentNode.NodeType == NodeType.BookmarkEnd && currentNode != bookmark.BookmarkEnd)
        {
            currentNode = currentNode.NextPreOrder(document);
            continue;
        }
        if (currentNode == bookmark.BookmarkEnd)
        {
            isRemoving = false;
            continue;
        }
        nodes.Add(currentNode);
        Node nextNode = currentNode.NextPreOrder(document);
        currentNode = nextNode;
    }
    foreach (Node node in nodes)
    {
        // Clear text contents
        if (node.NodeType == NodeType.Run)
            ((Run)node).Text = "";
        // Removes bullets and numbering from all paragraphs
        if (node.NodeType == NodeType.Paragraph)
        {
            if (((Paragraph)node).ListFormat.IsListItem)
            {
                ((Paragraph)node).ListFormat.RemoveNumbers();
            }
        }
        // Remove Shape
        if (node.NodeType == NodeType.Shape)
            node.Remove();
        // Remove table row
        if (node.NodeType == NodeType.Row)
            node.Remove();
    }
    foreach (Node node in nodes)
    {
        if (node.NodeType == NodeType.Paragraph)
        {
            if (((Paragraph)node).HasChildNodes == false)
            {
                ((Paragraph)node).Remove();
            }
        }
    }
}

Hi,

Thank you for the answer. I tried to use the code that you provided with small modification to clear bookmark content without deleting inner bookmarks:

private void ClearBookmark(Bookmark bookmarkToClear, List<Bookmark> ignoreBookmarks)
{
    ArrayList nodes = new ArrayList();
    Node currentNode = bookmarkToClear.BookmarkStart.NextPreOrder(mDocument);
    bool isRemoving = true;

    while (currentNode != null && isRemoving)
    {
        if (currentNode.NodeType == NodeType.BookmarkStart && ignoreBookmarks.Count > 0 &&
            ContainsBookmark(ignoreBookmarks, ((BookmarkStart)currentNode).Bookmark))
        {
            Bookmark ignoreBookmark = ((BookmarkStart)currentNode).Bookmark;

            while (currentNode != ignoreBookmark.BookmarkEnd)
            {
                currentNode = currentNode.NextPreOrder(mDocument);
            }

            currentNode = currentNode.NextPreOrder(mDocument);
        }

        if (currentNode == bookmarkToClear.BookmarkEnd)
        {
            isRemoving = false;
            continue;
        }

        nodes.Add(currentNode);
        Node nextNode = currentNode.NextPreOrder(mDocument);
        currentNode = nextNode;
    }

    foreach (Node node in nodes)
    {
        //Removes bullets and numbering from all paragraphs
        if (node.NodeType == NodeType.Paragraph)
        {
            if (((Paragraph)node).ListFormat.IsListItem)
            {
                ((Paragraph)node).ListFormat.RemoveNumbers();
            }
        }
        else
        {
            node.Remove();
        }
    }

    foreach (Node node in nodes)
    {
        if (node.NodeType == NodeType.Paragraph)
        {
            if (ParagraphCanBeRemoved(node))
            {
                ((Paragraph)node).Remove();
            }
        }
    }
}

private bool ParagraphCanBeRemoved(Node paragraph)

{

    Node currentNode = paragraph.NextPreOrder(mDocument);
    while (currentNode != null)
    {
        if (currentNode.NodeType == NodeType.BookmarkStart ||
            currentNode.NodeType == NodeType.BookmarkEnd)
        {
            return false;
        }

        Node nextNode = currentNode.NextPreOrder(mDocument);
        currentNode = nextNode;
    }

    return true;
}

private bool ContainsBookmark(List<Bookmark> bookmarks, Bookmark bookmark)
{
    return (from bk in bookmarks
            where bk.Name == bookmark.Name
            select bk).Count() > 0;
}

Unfortunately looks like this code deletes the BookmarkEnd node of the bookmarks that i wanted to ignore. It cause to the while loop to get to the currentNode is null when calling to ClearBookmar in the second time…

while (currentNode != ignoreBookmark.BookmarkEnd)
{
   currentNode = currentNode.NextPreOrder(mDocument);
}

I am trying to remove only paragraphs without bookmarks that i want to ignore. And i am deleting all other bookmarks before that.

Here the scenario that i use:
I am calling to

Bookmark AddendumApprovedBookmark = mDocument.Range.Bookmarks["START111634388897195832833F"];
Bookmark AddendumBookmark = mDocument.Range.Bookmarks["START110634388897141927273F"];
Bookmark AddendumSignatureBookmark = mDocument.Range.Bookmarks["START112634388897235519825F"];
ClearBookmark(AddendumApprovedBookmark, new List<Bookmark>() { AddendumSignatureBookmark, AddendumBookmark });

then i do some code and calling again to:

ClearBookmark(AddendumApprovedBookmark, new List<Bookmark>() { AddendumSignatureBookmark, AddendumBookmark });

In the second time i am getting exception as currentNode is null as i mentioned before.

I dont really know how i can proceed from here. I am attaching the document.

Thanks,
Stanislav

Hi Stanislav,

Thanks for your inquiry. The code shared in my last post works fine in your scenario. I have used the following code with your document and have not faced any exception. I have attached the output document with this post for your kind reference. Please use the latest version of Aspose.Words for .NET.

Please see the attached image, all three bookmark nodes exits in output document.

Document doc = new Document(MyDir + "temp.doc"); 
doc.Unprotect();
Bookmark AddendumApprovedBookmark = doc.Range.Bookmarks["START111634388897195832833F"];
Bookmark AddendumBookmark = doc.Range.Bookmarks["START110634388897141927273F"];
Bookmark AddendumSignatureBookmark = doc.Range.Bookmarks["START112634388897235519825F"];
ClearBookmark(AddendumApprovedBookmark, doc);
ClearBookmark(AddendumBookmark, doc);
ClearBookmark(AddendumSignatureBookmark, doc);
doc.Save(MyDir + "AsposeOut.doc");

Hi

Thank you for the answer. I described a little bit another scenario. I am talking about calling ClearBookmark twice for the same bookmark when i am ignoring inner bookmarks. Please try to run the modified code exactly as i described it.

I am calling clear twice for AddendumApprovedBookmark bookmark.

ClearBookmark(AddendumApprovedBookmark, new List<Bookmark>() { AddendumSignatureBookmark, AddendumBookmark });
ClearBookmark(AddendumApprovedBookmark, new List<Bookmark>() { AddendumSignatureBookmark, AddendumBookmark });

Thanks,
Stanislav.