Витяг вмісту між вузлами документа
При роботі з документами важливо мати можливість легко витягувати вміст з певного діапазону в документі. Однак вміст може складатися зі складних елементів, таких як абзаци, таблиці, зображення і т. д.
Незалежно від того, який вміст потрібно витягти, метод вилучення цього вмісту завжди визначатиметься тим, які вузли вибрані для отримання вмісту між ними. Це можуть бути цілі текстові фрагменти або прості текстові фрагменти.
Існує багато можливих ситуацій і, отже, багато різних типів вузлів, які слід враховувати при отриманні вмісту. Наприклад, ви можете захотіти витягти вміст між:
- Два конкретні пункти
- Конкретні фрагменти тексту
- Поля різних типів, такі як поля злиття
- Початковий і кінцевий діапазони закладки або коментаря
- Різні тексти, що містяться в окремих розділах
У деяких ситуаціях вам може знадобитися навіть об’єднати різні типи вузлів, наприклад, для вилучення вмісту з абзацу та поля або з запуску та закладки.
У цій статті наводиться реалізація коду для вилучення тексту між різними вузлами, а також приклади поширених сценаріїв.
Навіщо витягувати контент
Часто метою вилучення вмісту є дублювання або збереження його окремо в новому документі. Наприклад, ви можете витягти вміст і:
- Скопіюйте його в окремий документ
- Перетворіть певну частину документа на PDF або зображення
- Повторюйте вміст документа багато разів
- Працюйте з витягнутим вмістом окремо від решти документа
Цього можна легко досягти, використовуючи Aspose.Words та реалізацію коду нижче.
Алгоритм вилучення вмісту
Наведений у цьому розділі код розглядає всі можливі ситуації, описані вище, за допомогою одного узагальненого методу, який можна використовувати повторно. Загалом цей метод включає:
- Збір вузлів, які визначають область вмісту, яка буде витягнута з вашого документа. Пошук цих вузлів здійснюється Користувачем у його коді залежно від того, що він хоче витягти.
- Передаємо ці вузли методу ExtractContent, представленому нижче. Ви також повинні передати логічний параметр, який вказує, чи повинні ці вузли, що діють як маркери, бути включені в Витяг чи ні.
- Отримання списку клонованого вмісту (скопійованих вузлів), вказаного для вилучення. Ви можете використовувати цей список вузлів будь-яким застосовним способом, наприклад, створити новий документ, що містить лише вибраний вміст.
Як витягти контент
Щоб витягти вміст із документа, вам потрібно викликати метод ExtractContent
, описаний нижче, і передати відповідні параметри. В основі цього методу лежить пошук вузлів на рівні блоків (абзаців і таблиць) і їх клонування для створення ідентичних копій. Якщо передані вузли-маркери знаходяться на рівні блоків, то метод може просто скопіювати вміст на цьому рівні і додати його в масив.
Однак, якщо вузли-маркери є вбудованими (дочірніми по відношенню до абзацу), ситуація стає більш складною, оскільки необхідно розділити абзац на вбудованому вузлі, будь то прогін, поля закладок і т.д. вміст в клонованих батьківських вузлах, відсутнє між маркерами, видаляється. Цей процес використовується для забезпечення того, щоб вбудовані вузли зберігали форматування батьківського абзацу. Метод також виконує перевірку вузлів, переданих як параметри, і видає виняток, якщо будь-який з вузлів є недійсним. В цей метод передаються наступні параметри:
-
StartNode і EndNode. Перші два параметри-це вузли, які визначають, де слід починати і закінчувати Витяг вмісту відповідно. Ці вузли можуть бути як на рівні блоків (абзац, таблиця), так і на вбудованому рівні (наприклад, Run, FieldStart, BookmarkStart і т.д.).:
- Щоб передати поле, ви повинні передати відповідний об’єкт FieldStart.
- Щоб передати закладки, необхідно передати вузли BookmarkStart і BookmarkEnd.
- Для передачі коментарів слід використовувати вузли CommentRangeStart і CommentRangeEnd.
-
IsInclusive. Визначає, чи будуть маркери включені в Витяг чи ні. Якщо для цього параметра встановлено значення false і передається один і той же вузол або послідовні вузли, то буде повернуто порожній список:
- Якщо передається вузол FieldStart, то цей параметр визначає, чи слід включати або виключати все поле цілком.
- Якщо передано вузол BookmarkStart або BookmarkEnd, Цей параметр визначає, чи включена закладка або лише вміст між діапазонами закладок.
- Якщо передано вузол CommentRangeStart або CommentRangeEnd, Цей параметр визначає, чи повинен бути включений сам коментар або лише вміст у діапазоні коментарів.
Реалізацію методу ExtractContent ви можете знайти тут. Цей метод буде описаний у сценаріях, описаних у цій статті.
Ми також визначимо метод користувача, який дозволяє легко створювати документ із витягнутих вузлів. Цей метод використовується в багатьох сценаріях, описаних нижче, і просто створює новий документ і імпортує в нього витягнутий вміст.
Наступний приклад коду показує, як взяти список вузлів і вставити їх у новий документ.
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
static SharedPtr<Document> GenerateDocument(SharedPtr<Document> srcDoc, SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> nodes) | |
{ | |
auto dstDoc = MakeObject<Document>(); | |
// Remove the first paragraph from the empty document. | |
dstDoc->get_FirstSection()->get_Body()->RemoveAllChildren(); | |
// Import each node from the list into the new document. Keep the original formatting of the node. | |
auto importer = MakeObject<NodeImporter>(srcDoc, dstDoc, ImportFormatMode::KeepSourceFormatting); | |
for (const auto& node : nodes) | |
{ | |
SharedPtr<Node> importNode = importer->ImportNode(node, true); | |
dstDoc->get_FirstSection()->get_Body()->AppendChild(importNode); | |
} | |
return dstDoc; | |
} |
Витягуйте вміст між абзацами
Це демонструє, як використовувати описаний вище метод для вилучення вмісту між конкретними абзацами. В даному випадку ми хочемо витягти текст листа, знайденого в першій половині документа. Можна сказати, що це між 7-м і 11-м абзацами.
Наведений нижче код виконує це завдання. Відповідні абзаци витягуються з використанням методу GetChild в документі і з передачею зазначених індексів. Потім ми передаємо ці вузли методу ExtractContent і вказуємо, що вони повинні бути включені в Витяг. Цей метод поверне скопійований вміст між цими вузлами, який потім буде вставлений у новий документ.
Наступний приклад коду показує, як витягти вміст між певними абзацами, використовуючи метод ExtractContent
, описаний вище:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
auto startPara = System::ExplicitCast<Paragraph>(doc->get_FirstSection()->get_Body()->GetChild(NodeType::Paragraph, 6, true)); | |
auto endPara = System::ExplicitCast<Paragraph>(doc->get_FirstSection()->get_Body()->GetChild(NodeType::Paragraph, 10, true)); | |
// Extract the content between these nodes in the document. Include these markers in the extraction. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodes = ExtractContentHelper::ExtractContent(startPara, endPara, true); | |
SharedPtr<Document> dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodes); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenParagraphs.docx"); |
Витягувати вміст між різними типами вузлів
Ми можемо витягувати вміст між будь-якими комбінаціями вузлів на рівні блоків або вбудованих вузлів. У наведеному нижче сценарії ми будемо витягувати вміст між першим абзацом та таблицею у другому розділі включно. Ми отримуємо вузли маркерів, викликаючи методи Body.FirstParagraph
та GetChild у другому розділі документа, щоб отримати відповідні вузли абзацу та таблиці. Для невеликої зміни давайте замість цього продублюємо вміст і вставимо його під оригінал.
Наступний приклад коду показує, як витягти вміст з абзацу та таблиці за допомогою методу ExtractContent
:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
auto startPara = System::ExplicitCast<Paragraph>(doc->get_LastSection()->GetChild(NodeType::Paragraph, 2, true)); | |
auto endTable = System::ExplicitCast<Table>(doc->get_LastSection()->GetChild(NodeType::Table, 0, true)); | |
// Extract the content between these nodes in the document. Include these markers in the extraction. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodes = ExtractContentHelper::ExtractContent(startPara, endTable, true); | |
// Let's reverse the array to make inserting the content back into the document easier. | |
extractedNodes->Reverse(); | |
for (SharedPtr<Node> extractedNode : extractedNodes) | |
// Insert the last node from the reversed list. | |
endTable->get_ParentNode()->InsertAfter(extractedNode, endTable); | |
doc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenBlockLevelNodes.docx"); |
Витягуйте вміст з абзаців залежно від стилю
Можливо, вам доведеться витягти вміст з абзаців одного або різних стилів, наприклад, з абзаців, позначених стилями заголовків. Наведений нижче код показує, як цього досягти. Це простий приклад, який дозволяє витягувати вміст між першим екземпляром стилів “Heading 1” та “Header 3” без вилучення заголовків. Для цього ми встановлюємо останньому параметру значення false, яке вказує, що вузли-маркери не повинні включатися.
При правильній реалізації це повинно виконуватися в циклі для вилучення вмісту між усіма абзацами цих стилів з документа. Витягнутий вміст копіюється в новий документ.
Наступний приклад коду показує, як витягувати вміст між абзацами з певними стилями за допомогою методу ExtractContent
:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
// Gather a list of the paragraphs using the respective heading styles. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Paragraph>>> parasStyleHeading1 = ParagraphsByStyleName(doc, u"Heading 1"); | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Paragraph>>> parasStyleHeading3 = ParagraphsByStyleName(doc, u"Heading 3"); | |
// Use the first instance of the paragraphs with those styles. | |
SharedPtr<Node> startPara1 = parasStyleHeading1->idx_get(0); | |
SharedPtr<Node> endPara1 = parasStyleHeading3->idx_get(0); | |
// Extract the content between these nodes in the document. Don't include these markers in the extraction. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodes = ExtractContentHelper::ExtractContent(startPara1, endPara1, false); | |
SharedPtr<Document> dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodes); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenParagraphStyles.docx"); |
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
static SharedPtr<System::Collections::Generic::List<SharedPtr<Paragraph>>> ParagraphsByStyleName(SharedPtr<Document> doc, System::String styleName) | |
{ | |
// Create an array to collect paragraphs of the specified style. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Paragraph>>> paragraphsWithStyle = | |
MakeObject<System::Collections::Generic::List<SharedPtr<Paragraph>>>(); | |
SharedPtr<NodeCollection> paragraphs = doc->GetChildNodes(NodeType::Paragraph, true); | |
// Look through all paragraphs to find those with the specified style. | |
for (const auto& paragraph : System::IterateOver<Paragraph>(paragraphs)) | |
{ | |
if (paragraph->get_ParagraphFormat()->get_Style()->get_Name() == styleName) | |
{ | |
paragraphsWithStyle->Add(paragraph); | |
} | |
} | |
return paragraphsWithStyle; | |
} |
Витягуйте вміст між певними Запусками
Ви також можете витягувати вміст між вбудованими вузлами, такими як Run. Як маркери можна використовувати Runs з різних абзаців. У наведеному нижче коді показано, як витягувати певний текст з одного вузла Paragraph.
Наступний приклад коду показує, як витягувати вміст між конкретними запусками одного абзацу, використовуючи метод ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
auto para = System::ExplicitCast<Paragraph>(doc->GetChild(NodeType::Paragraph, 7, true)); | |
SharedPtr<Run> startRun = para->get_Runs()->idx_get(1); | |
SharedPtr<Run> endRun = para->get_Runs()->idx_get(4); | |
// Extract the content between these nodes in the document. Include these markers in the extraction. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodes = ExtractContentHelper::ExtractContent(startRun, endRun, true); | |
for (SharedPtr<Node> extractedNode : extractedNodes) | |
std::cout << extractedNode->ToString(SaveFormat::Text) << std::endl; |
Витягувати вміст за допомогою поля
Щоб використовувати поле як маркер, необхідно передати вузол FieldStart
. Останній параметр методу ExtractContent
визначає, чи слід включати все поле цілком чи ні. Давайте виділимо вміст між полем злиття “FullName” та абзацом у документі. Ми використовуємо метод MoveToMergeField класу DocumentBuilder. Це поверне вузол FieldStart з переданого йому поля name of merge.
У нашому випадку давайте встановимо для останнього параметра, переданого методу ExtractContent, значення false, щоб виключити поле з вилучення. Ми перетворимо витягнутий вміст у PDF.
Наступний приклад коду показує, як витягти вміст із певного поля та абзацу в документі за допомогою методу ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
auto builder = MakeObject<DocumentBuilder>(doc); | |
// Pass the first boolean parameter to get the DocumentBuilder to move to the FieldStart of the field. | |
// We could also get FieldStarts of a field using GetChildNode method as in the other examples. | |
builder->MoveToMergeField(u"Fullname", false, false); | |
// The builder cursor should be positioned at the start of the field. | |
auto startField = System::ExplicitCast<FieldStart>(builder->get_CurrentNode()); | |
auto endPara = System::ExplicitCast<Paragraph>(doc->get_FirstSection()->GetChild(NodeType::Paragraph, 5, true)); | |
// Extract the content between these nodes in the document. Don't include these markers in the extraction. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodes = ExtractContentHelper::ExtractContent(startField, endPara, false); | |
SharedPtr<Document> dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodes); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentUsingField.docx"); |
Витяг вмісту з закладки
У документі вміст, визначений у закладці, інкапсулюється вузлами BookmarkStart
та BookmarkEnd. Вміст, що знаходиться між цими двома вузлами, становить закладку. Ви можете використовувати будь-який із цих вузлів як будь-який маркер, навіть із різних закладок, за умови, що початковий маркер відображається перед кінцевим маркером у документі. Ми витягнемо цей вміст у новий документ, використовуючи наведений нижче код. Параметр IsInclusive показує, як зберегти або видалити закладку.
Наступний приклад коду показує, як витягти вміст, на який посилається закладка, використовуючи метод ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
SharedPtr<Bookmark> bookmark = doc->get_Range()->get_Bookmarks()->idx_get(u"Bookmark1"); | |
SharedPtr<BookmarkStart> bookmarkStart = bookmark->get_BookmarkStart(); | |
SharedPtr<BookmarkEnd> bookmarkEnd = bookmark->get_BookmarkEnd(); | |
// Firstly, extract the content between these nodes, including the bookmark. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodesInclusive = | |
ExtractContentHelper::ExtractContent(bookmarkStart, bookmarkEnd, true); | |
SharedPtr<Document> dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodesInclusive); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenBookmark.IncludingBookmark.docx"); | |
// Secondly, extract the content between these nodes this time without including the bookmark. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodesExclusive = | |
ExtractContentHelper::ExtractContent(bookmarkStart, bookmarkEnd, false); | |
dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodesExclusive); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenBookmark.WithoutBookmark.docx"); |
Витягувати вміст з коментаря
Коментар складається з вузлів CommentRangeStart, CommentRangeEnd та Comment. Всі ці вузли є вбудованими. Перші два вузли містять вміст документа, на який посилається коментар, як показано на скріншоті нижче.
Вузол Comment сам по собі є вузлом InlineStory, який може містити абзаци та заголовки. Він являє собою повідомлення коментаря, що відображається у вигляді бульбашки коментарів на панелі попереднього перегляду. Оскільки цей вузол є вбудованим і є нащадком тіла, ви також можете витягти вміст із цього повідомлення.
Коментар містить заголовок, перший абзац та таблицю у другому розділі. Давайте перенесемо цей коментар до нового документа. Параметр IsInclusive визначає, чи слід зберігати сам коментар чи видаляти його.
Наступний приклад коду показує, як це зробити:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
auto commentStart = System::ExplicitCast<CommentRangeStart>(doc->GetChild(NodeType::CommentRangeStart, 0, true)); | |
auto commentEnd = System::ExplicitCast<CommentRangeEnd>(doc->GetChild(NodeType::CommentRangeEnd, 0, true)); | |
// Firstly, extract the content between these nodes including the comment as well. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodesInclusive = | |
ExtractContentHelper::ExtractContent(commentStart, commentEnd, true); | |
SharedPtr<Document> dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodesInclusive); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenCommentRange.IncludingComment.docx"); | |
// Secondly, extract the content between these nodes without the comment. | |
SharedPtr<System::Collections::Generic::List<SharedPtr<Node>>> extractedNodesExclusive = | |
ExtractContentHelper::ExtractContent(commentStart, commentEnd, false); | |
dstDoc = ExtractContentHelper::GenerateDocument(doc, extractedNodesExclusive); | |
dstDoc->Save(ArtifactsDir + u"ExtractContent.ExtractContentBetweenCommentRange.WithoutComment.docx"); |
Як витягти вміст за допомогою DocumentVisitor
Використовуйте клас DocumentVisitor для реалізації цього сценарію використання. Цей клас відповідає добре відомому шаблону оформлення відвідувачів. За допомогою DocumentVisitor, ви можете визначати та виконувати спеціальні операції, які потребують переліку в дереві документа.
DocumentVisitor
Кожен метод DocumentVisitor.VisitXXX повертає значення VisitorAction, яке керує перерахуванням вузлів. Ви можете запросити або продовжити перерахування, пропустити поточний вузол (але продовжити перерахування), або зупинити перерахування вузлів.
Ось кроки, які ви повинні виконати, щоб програмно визначити та витягти різні частини документа:
- Створіть клас, похідний від DocumentVisitor
- Перевизначте та надайте реалізації для деяких або всіх методів DocumentVisitor.VisitXXX для виконання деяких операцій користувача
- Викличте
Node.Accept
на вузлі, з якого ви хочете почати перерахування. Наприклад, якщо ви хочете перерахувати весь документ, використовуйтеDocument.Accept
DocumentVisitor
Цей приклад показує, як використовувати шаблон відвідувача для додавання нових операцій до об’єктної моделі Aspose.Words. В даному випадку ми створюємо простий конвертер документів в текстовий формат:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Extract content.docx"); | |
auto convertToPlainText = MakeObject<ExtractContent::ConvertDocToTxt>(); | |
// Note that every node in the object model has the accept method so the visiting | |
// can be executed not only for the whole document, but for any node in the document. | |
doc->Accept(convertToPlainText); | |
// Once the visiting is complete, we can retrieve the result of the operation, | |
// That in this example, has accumulated in the visitor. | |
std::cout << convertToPlainText->GetText() << std::endl; |
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
/// <summary> | |
/// Simple implementation of saving a document in the plain text format. Implemented as a Visitor. | |
/// </summary> | |
class ConvertDocToTxt : public DocumentVisitor | |
{ | |
public: | |
ConvertDocToTxt() : mIsSkipText(false) | |
{ | |
mIsSkipText = false; | |
mBuilder = MakeObject<System::Text::StringBuilder>(); | |
} | |
/// <summary> | |
/// Gets the plain text of the document that was accumulated by the visitor. | |
/// </summary> | |
String GetText() | |
{ | |
return mBuilder->ToString(); | |
} | |
/// <summary> | |
/// Called when a Run node is encountered in the document. | |
/// </summary> | |
VisitorAction VisitRun(SharedPtr<Run> run) override | |
{ | |
AppendText(run->get_Text()); | |
// Let the visitor continue visiting other nodes. | |
return VisitorAction::Continue; | |
} | |
/// <summary> | |
/// Called when a FieldStart node is encountered in the document. | |
/// </summary> | |
VisitorAction VisitFieldStart(SharedPtr<FieldStart> fieldStart) override | |
{ | |
ASPOSE_UNUSED(fieldStart); | |
// In Microsoft Word, a field code (such as "MERGEFIELD FieldName") follows | |
// after a field start character. We want to skip field codes and output field. | |
// Result only, therefore we use a flag to suspend the output while inside a field code. | |
// Note this is a very simplistic implementation and will not work very well. | |
// If you have nested fields in a document. | |
mIsSkipText = true; | |
return VisitorAction::Continue; | |
} | |
/// <summary> | |
/// Called when a FieldSeparator node is encountered in the document. | |
/// </summary> | |
VisitorAction VisitFieldSeparator(SharedPtr<FieldSeparator> fieldSeparator) override | |
{ | |
ASPOSE_UNUSED(fieldSeparator); | |
// Once reached a field separator node, we enable the output because we are | |
// now entering the field result nodes. | |
mIsSkipText = false; | |
return VisitorAction::Continue; | |
} | |
/// <summary> | |
/// Called when a FieldEnd node is encountered in the document. | |
/// </summary> | |
VisitorAction VisitFieldEnd(SharedPtr<FieldEnd> fieldEnd) override | |
{ | |
ASPOSE_UNUSED(fieldEnd); | |
// Make sure we enable the output when reached a field end because some fields | |
// do not have field separator and do not have field result. | |
mIsSkipText = false; | |
return VisitorAction::Continue; | |
} | |
/// <summary> | |
/// Called when visiting of a Paragraph node is ended in the document. | |
/// </summary> | |
VisitorAction VisitParagraphEnd(SharedPtr<Paragraph> paragraph) override | |
{ | |
ASPOSE_UNUSED(paragraph); | |
// When outputting to plain text we output Cr+Lf characters. | |
AppendText(ControlChar::CrLf()); | |
return VisitorAction::Continue; | |
} | |
VisitorAction VisitBodyStart(SharedPtr<Body> body) override | |
{ | |
ASPOSE_UNUSED(body); | |
// We can detect beginning and end of all composite nodes such as Section, Body, | |
// Table, Paragraph etc and provide custom handling for them. | |
mBuilder->Append(u"*** Body Started ***\r\n"); | |
return VisitorAction::Continue; | |
} | |
VisitorAction VisitBodyEnd(SharedPtr<Body> body) override | |
{ | |
ASPOSE_UNUSED(body); | |
mBuilder->Append(u"*** Body Ended ***\r\n"); | |
return VisitorAction::Continue; | |
} | |
/// <summary> | |
/// Called when a HeaderFooter node is encountered in the document. | |
/// </summary> | |
VisitorAction VisitHeaderFooterStart(SharedPtr<HeaderFooter> headerFooter) override | |
{ | |
ASPOSE_UNUSED(headerFooter); | |
// Returning this value from a visitor method causes visiting of this | |
// Node to stop and move on to visiting the next sibling node | |
// The net effect in this example is that the text of headers and footers | |
// Is not included in the resulting output | |
return VisitorAction::SkipThisNode; | |
} | |
private: | |
SharedPtr<System::Text::StringBuilder> mBuilder; | |
bool mIsSkipText; | |
/// <summary> | |
/// Adds text to the current output. Honors the enabled/disabled output flag. | |
/// </summary> | |
void AppendText(String text) | |
{ | |
if (!mIsSkipText) | |
{ | |
mBuilder->Append(text); | |
} | |
} | |
}; |
Як витягти лише текст
Існують наступні способи вилучення тексту з документа:
- Використовуйте Document.Save замість SaveFormat.Text, щоб зберегти як звичайний текст у файл або потік
- Використовуйте Node.ToString і передайте параметр SaveFormat.Text. Внутрішньо це викликає функцію збереження як текст у потоці пам’яті та повертає отриманий рядок
- Використовуйте Node.GetText для вилучення тексту, що містить усі символи управління Microsoft Word, включаючи коди полів
- Реалізуйте користувацький параметр DocumentVisitor для виконання індивідуального вилучення
Використання Node.GetText
та Node.ToString
Документ Word може містити Керуючі символи, які позначають спеціальні елементи, такі як поле, кінець комірки, кінець розділу і т.д. повний список можливих Word керуючих символів визначено в класі ControlChar. Метод Node.GetText повертає текст із усіма контрольними символами, присутніми у вузлі.
Виклик ToString повертає лише текстове представлення документа без контрольних символів.
Наступний приклад коду показує різницю між викликом методів GetText та ToString на вузлі:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(); | |
auto builder = MakeObject<DocumentBuilder>(doc); | |
builder->InsertField(u"MERGEFIELD Field"); | |
// When converted to text it will not retrieve fields code or special characters, | |
// but will still contain some natural formatting characters such as paragraph markers etc. | |
// This is the same as "viewing" the document as if it was opened in a text editor. | |
std::cout << (String(u"ToString() Result: ") + doc->ToString(SaveFormat::Text)) << std::endl; |
Використовуючи SaveFormat.Text
У цьому прикладі документ зберігається наступним чином:
- Відфільтровує символи полів і коди полів, форму, виноски, кінцеві примітки і посилання на коментарі
- Замінює символи кінця абзацу ControlChar.Cr комбінаціями ControlChar.CrLf
- Використовує кодування UTF8
Наступний приклад коду показує, як зберегти документ у форматі TXT:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Document.docx"); | |
doc->Save(ArtifactsDir + u"BaseConversions.DocxToTxt.txt"); |
Витяг зображень з фігур
Для виконання деяких завдань вам може знадобитися витягти зображення з документів. Aspose.Words це також дозволяє це зробити.
Наступний приклад коду показує, як витягувати зображення з документа:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git. | |
auto doc = MakeObject<Document>(MyDir + u"Images.docx"); | |
SharedPtr<NodeCollection> shapes = doc->GetChildNodes(NodeType::Shape, true); | |
int imageIndex = 0; | |
for (const auto& shape : System::IterateOver<Shape>(shapes)) | |
{ | |
if (shape->get_HasImage()) | |
{ | |
String imageFileName = | |
String::Format(u"Image.ExportImages.{0}_{1}", imageIndex, FileFormatUtil::ImageTypeToExtension(shape->get_ImageData()->get_ImageType())); | |
// Note, if you have only an image (not a shape with a text and the image), | |
// you can use shape->GetShapeRenderer()->Save(...) method to save the image. | |
shape->get_ImageData()->Save(ArtifactsDir + imageFileName); | |
imageIndex++; | |
} | |
} |