Free Support Forum -

Bookmark issue in Words 18.9

We have some code that creates a new document from a template containing bookmarks. This worked in Words 17.4, but fails in 18.9 with “java.lang.ClassCastException: com.aspose.words.BookmarkEnd cannot be cast to com.aspose.words.CompositeNode”

The code is based on the method described in

The method is:

   private void writeStandardsSection(Document template, DocumentBuilder builder, List<Map<String, Object>> standards, BufferedImage compliantImage, BufferedImage noncompliantImage) {
          try {
                 Bookmark standardsBookmark = template.getRange().getBookmarks().get("standardsTable");
                 Document standardsTemplate = generateDocumentFromBookmark(template, standardsBookmark);
   private static Document generateDocumentFromBookmark(Document srcDoc, Bookmark bookmark) throws Exception {

          if (bookmark == null) {
                 return null;

          ArrayList<CompositeNode> nodes = extractContent(bookmark.getBookmarkStart(), bookmark.getBookmarkEnd(), true);
   private static ArrayList<CompositeNode> extractContent(Node originalStartNode, Node originalEndNode, boolean isInclusive) throws Exception {

       // Create a list to store the extracted nodes.
       ArrayList<CompositeNode> nodes = new ArrayList<>();

       // Keep a record of the original nodes passed to this method so we can split marker nodes if needed.
       Node startNode = originalStartNode;
       Node endNode = originalEndNode;

       // Extract content based on block level nodes (paragraphs and tables). Traverse through parent nodes to find them.
       // We will split the content of first and last nodes depending if the marker nodes are inline
       while (startNode.getParentNode().getNodeType() != NodeType.BODY)
           startNode = startNode.getParentNode();

       while (endNode.getParentNode().getNodeType() != NodeType.BODY)
           endNode = endNode.getParentNode();

       boolean isExtracting = true;
       boolean isStartingNode = true;
       boolean isEndingNode;
       // The current node we are extracting from the document.
       Node currNode = startNode;

       // Begin extracting content. Process all block level nodes and specifically split the first and last nodes when needed so paragraph formatting is retained.
       // Method is little more complex than a regular extractor as we need to factor in extracting using inline nodes, fields, bookmarks etc as to make it really useful.
       while (isExtracting) {
           // Clone the current node and its children to obtain a copy.
           CompositeNode cloneNode = (CompositeNode) currNode.deepClone(true);
           isEndingNode = currNode.equals(endNode);

           if (isStartingNode || isEndingNode) {
               // We need to process each marker separately so pass it off to a separate method instead.
               if (isStartingNode) {
                   processMarker(cloneNode, nodes, originalStartNode, isInclusive, isStartingNode, isEndingNode);
                   isStartingNode = false;

               // Conditional needs to be separate as the block level start and end markers maybe the same node.
               if (isEndingNode) {
                   processMarker(cloneNode, nodes, originalEndNode, isInclusive, isStartingNode, isEndingNode);
                   isExtracting = false;
           } else
               // Node is not a start or end marker, simply add the copy to the list.

           // Move to the next node and extract it. If next node is null that means the rest of the content is found in a different section.
           if (currNode.getNextSibling() == null && isExtracting) {
               // Move to the next section.
               Section nextSection = (Section) currNode.getAncestor(NodeType.SECTION).getNextSibling();
               currNode = nextSection.getBody().getFirstChild();
           } else {
               // Move to the next node in the body.
               currNode = currNode.getNextSibling();

       // Return the nodes between the node markers.
       return nodes;

We couldn’t find anything in the release notes, so we’re unsure how this should now be done. Does anyone have any suggestions, please?


Thanks for your inquiry. To ensure a timely and accurate response, please attach the following resources here for testing:

  • Your input Word document.
  • Please create a simple Java application ( source code without compilation errors ) that helps us to reproduce your problem on our end and attach it here for testing.

As soon as you get these pieces of information ready, we will start investigation into your issue and provide you more information. Thanks for your cooperation.

PS: To attach these resources, please zip and upload them.

Our code is almost exactly like the example at

But the release notes for 18.9 specifically say “Now code that uses Aspose.Words should consider that not only composite nodes may appear on the block/cell/row level, for example, as children of the Body, Table, Row, Cell nodes.” so presumably that example needs updating for 18.9


Thanks for your inquiry. We suggest you please use LoadOptions.AnnotationsAtBlockLevel property to avoid the shared exception. Please refer to the following article.
Working with Bookmark on Block, Cell, Row Levels

If you still face problem, please share your input document and code example for investigation.