search/mag_sel search/close
Aspose::Words::NodeImporter Class Reference

Allows to efficiently perform repeated import of nodes from one document to another.

Aspose.Words provides functionality for easy copying and moving fragments between Microsoft Word documents. This is known as "importing nodes". Before you can insert a fragment from one document into another, you need to "import" it. Importing creates a deep clone of the original node, ready to be inserted into the destination document.

The simplest way to import a node is to use the ImportNode() method provided by the DocumentBase object.

However, when you need to import nodes from one document to another multiple times, it is better to use the NodeImporter class. The NodeImporter class allows to minimize the number of styles and lists created in the destination document.

Copying or moving fragments from one Microsoft Word document to another presents a number of technical challenges for Aspose.Words. In a Word document, styles and list formatting are stored centrally, separately from the text of the document. The paragraphs and runs of text merely reference the styles by internal unique identifiers.

The challenges arise from the fact that styles and lists are different in different documents. For example, to copy a paragraph formatted with the Heading 1 style from one document to another, a number of things must be taken into account: decide whether to copy the Heading 1 style from the source document to the destination document, clone the paragraph, update the cloned paragraph so it refers to the correct Heading 1 style in the destination document. If the style had to be copied, all the styles that it references (based on style and next paragraph style) should be analyzed and possibly copied too and so on. Similar issues exist when copying bulleted or numbered paragraphs because Microsoft Word stores list definitions separately from text.

The NodeImporter class is like a context, that holds the "translation tables" during the import. It correctly translates between styles and lists in the source and destination documents.

See also
Aspose::Words::Document
Aspose::Words::DocumentBase::ImportNode(System::SharedPtr<Aspose::Words::Node>, bool)
Examples

Shows how to insert the contents of one document to a bookmark in another document.

void InsertAtBookmark()
{
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->StartBookmark(u"InsertionPoint");
builder->Write(u"We will insert a document here: ");
builder->EndBookmark(u"InsertionPoint");
auto docToInsert = MakeObject<Document>();
builder = MakeObject<DocumentBuilder>(docToInsert);
builder->Write(u"Hello world!");
docToInsert->Save(ArtifactsDir + u"NodeImporter.InsertAtMergeField.docx");
SharedPtr<Bookmark> bookmark = doc->get_Range()->get_Bookmarks()->idx_get(u"InsertionPoint");
InsertDocument(bookmark->get_BookmarkStart()->get_ParentNode(), docToInsert);
ASSERT_EQ(String(u"We will insert a document here: ") + u"\rHello world!", doc->GetText().Trim());
}
static void InsertDocument(SharedPtr<Node> insertionDestination, SharedPtr<Document> docToInsert)
{
if (insertionDestination->get_NodeType() == NodeType::Paragraph || insertionDestination->get_NodeType() == NodeType::Table)
{
SharedPtr<CompositeNode> destinationParent = insertionDestination->get_ParentNode();
auto importer = MakeObject<NodeImporter>(docToInsert, insertionDestination->get_Document(), ImportFormatMode::KeepSourceFormatting);
// Loop through all block-level nodes in the section's body,
// then clone and insert every node that is not the last empty paragraph of a section.
for (const auto& srcSection : System::IterateOver(docToInsert->get_Sections()->LINQ_OfType<SharedPtr<Section>>()))
{
for (const auto& srcNode : System::IterateOver(srcSection->get_Body()))
{
if (srcNode->get_NodeType() == NodeType::Paragraph)
{
auto para = System::DynamicCast<Paragraph>(srcNode);
if (para->get_IsEndOfSection() && !para->get_HasChildNodes())
{
continue;
}
}
SharedPtr<Node> newNode = importer->ImportNode(srcNode, true);
destinationParent->InsertAfter(newNode, insertionDestination);
insertionDestination = newNode;
}
}
}
else
{
throw System::ArgumentException(u"The destination node should be either a paragraph or table.");
}
}

#include <Aspose.Words.Cpp/NodeImporter.h>

+ Inheritance diagram for Aspose::Words::NodeImporter:

Public Member Functions

 NodeImporter (SharedPtr< DocumentBase > srcDoc, SharedPtr< DocumentBase > dstDoc, ImportFormatMode importFormatMode)
 Initializes a new instance of the NodeImporter class. More...
 
 NodeImporter (SharedPtr< DocumentBase > srcDoc, SharedPtr< DocumentBase > dstDoc, ImportFormatMode importFormatMode, SharedPtr< ImportFormatOptions > importFormatOptions)
 Initializes a new instance of the NodeImporter class. More...
 
virtual const TypeInfoGetType () const override
 
SharedPtr< NodeImportNode (SharedPtr< Node > srcNode, bool isImportChildren)
 Imports a node from one document into another. More...
 
virtual bool Is (const TypeInfo &target) const override
 

Static Public Member Functions

static const TypeInfoType ()
 

Constructor & Destructor Documentation

◆ NodeImporter() [1/2]

Aspose::Words::NodeImporter::NodeImporter ( System::SharedPtr< Aspose::Words::DocumentBase srcDoc,
System::SharedPtr< Aspose::Words::DocumentBase dstDoc,
Aspose::Words::ImportFormatMode  importFormatMode 
)

Initializes a new instance of the NodeImporter class.

Parameters
srcDocThe source document.
dstDocThe destination document that will be the owner of imported nodes.
importFormatModeSpecifies how to merge style formatting that clashes.
Examples

Shows how to insert the contents of one document to a bookmark in another document.

void InsertAtBookmark()
{
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->StartBookmark(u"InsertionPoint");
builder->Write(u"We will insert a document here: ");
builder->EndBookmark(u"InsertionPoint");
auto docToInsert = MakeObject<Document>();
builder = MakeObject<DocumentBuilder>(docToInsert);
builder->Write(u"Hello world!");
docToInsert->Save(ArtifactsDir + u"NodeImporter.InsertAtMergeField.docx");
SharedPtr<Bookmark> bookmark = doc->get_Range()->get_Bookmarks()->idx_get(u"InsertionPoint");
InsertDocument(bookmark->get_BookmarkStart()->get_ParentNode(), docToInsert);
ASSERT_EQ(String(u"We will insert a document here: ") + u"\rHello world!", doc->GetText().Trim());
}
static void InsertDocument(SharedPtr<Node> insertionDestination, SharedPtr<Document> docToInsert)
{
if (insertionDestination->get_NodeType() == NodeType::Paragraph || insertionDestination->get_NodeType() == NodeType::Table)
{
SharedPtr<CompositeNode> destinationParent = insertionDestination->get_ParentNode();
auto importer = MakeObject<NodeImporter>(docToInsert, insertionDestination->get_Document(), ImportFormatMode::KeepSourceFormatting);
// Loop through all block-level nodes in the section's body,
// then clone and insert every node that is not the last empty paragraph of a section.
for (const auto& srcSection : System::IterateOver(docToInsert->get_Sections()->LINQ_OfType<SharedPtr<Section>>()))
{
for (const auto& srcNode : System::IterateOver(srcSection->get_Body()))
{
if (srcNode->get_NodeType() == NodeType::Paragraph)
{
auto para = System::DynamicCast<Paragraph>(srcNode);
if (para->get_IsEndOfSection() && !para->get_HasChildNodes())
{
continue;
}
}
SharedPtr<Node> newNode = importer->ImportNode(srcNode, true);
destinationParent->InsertAfter(newNode, insertionDestination);
insertionDestination = newNode;
}
}
}
else
{
throw System::ArgumentException(u"The destination node should be either a paragraph or table.");
}
}

◆ NodeImporter() [2/2]

Aspose::Words::NodeImporter::NodeImporter ( System::SharedPtr< Aspose::Words::DocumentBase srcDoc,
System::SharedPtr< Aspose::Words::DocumentBase dstDoc,
Aspose::Words::ImportFormatMode  importFormatMode,
System::SharedPtr< Aspose::Words::ImportFormatOptions importFormatOptions 
)

Initializes a new instance of the NodeImporter class.

Parameters
srcDocThe source document.
dstDocThe destination document that will be the owner of imported nodes.
importFormatModeSpecifies how to merge style formatting that clashes.
importFormatOptionsSpecifies various options to format imported node.
Examples

Shows how resolve a clash when importing documents that have lists with the same list definition identifier.

auto srcDoc = MakeObject<Document>(MyDir + u"List with the same definition identifier - source.docx");
auto dstDoc = MakeObject<Document>(MyDir + u"List with the same definition identifier - destination.docx");
auto importFormatOptions = MakeObject<ImportFormatOptions>();
// Set the "KeepSourceNumbering" property to "true" to apply a different list definition ID
// to identical styles as Aspose.Words imports them into destination documents.
importFormatOptions->set_KeepSourceNumbering(true);
dstDoc->AppendDocument(srcDoc, ImportFormatMode::UseDestinationStyles, importFormatOptions);
dstDoc->UpdateListLabels();

Shows how to resolve list numbering clashes in source and destination documents.

// Open a document with a custom list numbering scheme, and then clone it.
// Since both have the same numbering format, the formats will clash if we import one document into the other.
auto srcDoc = MakeObject<Document>(MyDir + u"Custom list numbering.docx");
SharedPtr<Document> dstDoc = srcDoc->Clone();
// When we import the document's clone into the original and then append it,
// then the two lists with the same list format will join.
// If we set the "KeepSourceNumbering" flag to "false", then the list from the document clone
// that we append to the original will carry on the numbering of the list we append it to.
// This will effectively merge the two lists into one.
// If we set the "KeepSourceNumbering" flag to "true", then the document clone
// list will preserve its original numbering, making the two lists appear as separate lists.
auto importFormatOptions = MakeObject<ImportFormatOptions>();
importFormatOptions->set_KeepSourceNumbering(keepSourceNumbering);
auto importer = MakeObject<NodeImporter>(srcDoc, dstDoc, ImportFormatMode::KeepDifferentStyles, importFormatOptions);
for (const auto& paragraph : System::IterateOver<Paragraph>(srcDoc->get_FirstSection()->get_Body()->get_Paragraphs()))
{
SharedPtr<Node> importedNode = importer->ImportNode(paragraph, true);
dstDoc->get_FirstSection()->get_Body()->AppendChild(importedNode);
}
dstDoc->UpdateListLabels();
if (keepSourceNumbering)
{
ASSERT_EQ(String(u"6. Item 1\r\n") + u"7. Item 2 \r\n" + u"8. Item 3\r\n" + u"9. Item 4\r\n" + u"6. Item 1\r\n" + u"7. Item 2 \r\n" +
u"8. Item 3\r\n" + u"9. Item 4",
dstDoc->get_FirstSection()->get_Body()->ToString(SaveFormat::Text).Trim());
}
else
{
ASSERT_EQ(String(u"6. Item 1\r\n") + u"7. Item 2 \r\n" + u"8. Item 3\r\n" + u"9. Item 4\r\n" + u"10. Item 1\r\n" + u"11. Item 2 \r\n" +
u"12. Item 3\r\n" + u"13. Item 4",
dstDoc->get_FirstSection()->get_Body()->ToString(SaveFormat::Text).Trim());
}

Member Function Documentation

◆ GetType()

virtual const System::TypeInfo& Aspose::Words::NodeImporter::GetType ( ) const
overridevirtual

Reimplemented from System::Object.

◆ ImportNode()

System::SharedPtr<Aspose::Words::Node> Aspose::Words::NodeImporter::ImportNode ( System::SharedPtr< Aspose::Words::Node srcNode,
bool  isImportChildren 
)

Imports a node from one document into another.

Importing a node creates a copy of the source node belonging to the importing document. The returned node has no parent. The source node is not altered or removed from the original document.

Before a node from another document can be inserted into this document, it must be imported. During import, document-specific properties such as references to styles and lists are translated from the original to the importing document. After the node was imported, it can be inserted into the appropriate place in the document using InsertBefore() or InsertAfter().

If the source node already belongs to the destination document, then simply a deep clone of the source node is created.

Parameters
srcNodeThe node to import.
isImportChildrenTrue to import all child nodes recursively; otherwise, false.
Returns
The cloned, imported node. The node belongs to the destination document, but has no parent.
Examples

Shows how to insert the contents of one document to a bookmark in another document.

void InsertAtBookmark()
{
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->StartBookmark(u"InsertionPoint");
builder->Write(u"We will insert a document here: ");
builder->EndBookmark(u"InsertionPoint");
auto docToInsert = MakeObject<Document>();
builder = MakeObject<DocumentBuilder>(docToInsert);
builder->Write(u"Hello world!");
docToInsert->Save(ArtifactsDir + u"NodeImporter.InsertAtMergeField.docx");
SharedPtr<Bookmark> bookmark = doc->get_Range()->get_Bookmarks()->idx_get(u"InsertionPoint");
InsertDocument(bookmark->get_BookmarkStart()->get_ParentNode(), docToInsert);
ASSERT_EQ(String(u"We will insert a document here: ") + u"\rHello world!", doc->GetText().Trim());
}
static void InsertDocument(SharedPtr<Node> insertionDestination, SharedPtr<Document> docToInsert)
{
if (insertionDestination->get_NodeType() == NodeType::Paragraph || insertionDestination->get_NodeType() == NodeType::Table)
{
SharedPtr<CompositeNode> destinationParent = insertionDestination->get_ParentNode();
auto importer = MakeObject<NodeImporter>(docToInsert, insertionDestination->get_Document(), ImportFormatMode::KeepSourceFormatting);
// Loop through all block-level nodes in the section's body,
// then clone and insert every node that is not the last empty paragraph of a section.
for (const auto& srcSection : System::IterateOver(docToInsert->get_Sections()->LINQ_OfType<SharedPtr<Section>>()))
{
for (const auto& srcNode : System::IterateOver(srcSection->get_Body()))
{
if (srcNode->get_NodeType() == NodeType::Paragraph)
{
auto para = System::DynamicCast<Paragraph>(srcNode);
if (para->get_IsEndOfSection() && !para->get_HasChildNodes())
{
continue;
}
}
SharedPtr<Node> newNode = importer->ImportNode(srcNode, true);
destinationParent->InsertAfter(newNode, insertionDestination);
insertionDestination = newNode;
}
}
}
else
{
throw System::ArgumentException(u"The destination node should be either a paragraph or table.");
}
}

◆ Is()

virtual bool Aspose::Words::NodeImporter::Is ( const System::TypeInfo target) const
overridevirtual

Reimplemented from System::Object.

◆ Type()

static const System::TypeInfo& Aspose::Words::NodeImporter::Type ( )
static