Wyodrębnij zawartość pomiędzy węzłami w dokumencie
Podczas pracy z dokumentami ważna jest możliwość łatwego wyodrębnienia treści z określonego zakresu w dokumencie. Treść może jednak składać się ze skomplikowanych elementów, takich jak akapity, tabele, obrazy itp.
Niezależnie od tego, jaka treść ma zostać wyodrębniona, metoda wyodrębnienia tej treści będzie zawsze określona na podstawie tego, które węzły zostaną wybrane, pomiędzy którymi ma zostać wyodrębniona treść. Mogą to być całe treści tekstowe lub proste ciągi tekstowe.
Istnieje wiele możliwych sytuacji, a zatem wiele różnych typów węzłów, które należy wziąć pod uwagę podczas wyodrębniania treści. Na przykład możesz chcieć wyodrębnić zawartość pomiędzy:
- Dwa konkretne akapity
- Określone ciągi tekstu
- Pola różnych typów, takie jak pola scalone
- Zakres początkowy i końcowy zakładki lub komentarza
- Różne teksty zawarte w oddzielnych sekcjach
W niektórych sytuacjach może być nawet konieczne połączenie różnych typów węzłów, na przykład wyodrębnienie treści między akapitem a polem lub między uruchomieniem a zakładką.
W tym artykule przedstawiono implementację kodu służącą do wyodrębniania tekstu między różnymi węzłami, a także przykłady typowych scenariuszy.
Po co wyodrębniać zawartość
Często celem wyodrębnienia treści jest powielenie jej lub osobne zapisanie w nowym dokumencie. Można na przykład wyodrębnić treść i:
- Skopiuj go do osobnego dokumentu
- Konwertuj określoną część dokumentu na plik PDF lub obraz
- Wiele razy powielaj treść dokumentu
- Pracuj z wyodrębnioną treścią oddzielnie od reszty dokumentu
Można to łatwo osiągnąć za pomocą Aspose.Words i poniższej implementacji kodu.
Algorytm wyodrębniania treści
Kod w tej sekcji odnosi się do wszystkich możliwych sytuacji opisanych powyżej za pomocą jednej uogólnionej metody wielokrotnego użytku. Ogólny zarys tej techniki obejmuje:
- Zbierz węzły określające obszar treści, który zostanie wyodrębniony z dokumentu. Pobieraniem tych węzłów zajmuje się użytkownik w swoim kodzie, w zależności od tego, co chce wyodrębnić.
- Przekazanie tych węzłów do metody ExtractContent podanej poniżej. Musisz także przekazać parametr logiczny, który określa, czy te węzły, pełniąc rolę znaczników, powinny zostać uwzględnione w ekstrakcji, czy nie.
- Pobieranie listy sklonowanej zawartości (skopiowanych węzłów) określonej do wyodrębnienia. Możesz wykorzystać tę listę węzłów w dowolny sposób, np. tworząc nowy dokument zawierający tylko wybraną treść.
Jak wyodrębnić zawartość
Aby wyodrębnić treść z dokumentu należy wywołać poniższą metodę ExtractContent i przekazać odpowiednie parametry. Podstawą tej metody jest znajdowanie węzłów na poziomie bloków (akapitów i tabel) i klonowanie ich w celu utworzenia identycznych kopii. Jeśli przekazane węzły znaczników są na poziomie bloków, metoda może po prostu skopiować zawartość na tym poziomie i dodać ją do tablicy.
Jeśli jednak węzły znaczników są wbudowane (potomek akapitu), sytuacja staje się bardziej złożona, ponieważ konieczne jest podzielenie akapitu w węźle wbudowanym, niezależnie od tego, czy jest to bieg, pola zakładek itp. Treść w sklonowanych węzłach nadrzędnych nie obecny pomiędzy znacznikami jest usuwany. Proces ten ma na celu zapewnienie, że węzły wbudowane nadal zachowają formatowanie akapitu nadrzędnego. Metoda przeprowadzi również sprawdzenie węzłów przekazanych jako parametry i zgłosi wyjątek, jeśli którykolwiek z węzłów jest nieprawidłowy. Parametry, które należy przekazać do tej metody to:
- StartNode i EndNode. Pierwsze dwa parametry to węzły, które definiują, gdzie odpowiednio rozpoczyna się i kończy wyodrębnianie treści. Węzły te mogą być zarówno na poziomie blokowym (Paragraph, Table), jak i na poziomie wbudowanym (np. Run, FieldStart, BookmarkStart itp.):
- Aby przekazać pole należy przekazać odpowiadający mu obiekt FieldStart
- Aby przekazać zakładki należy przekazać węzły BookmarkStart i BookmarkEnd
- Do przekazywania komentarzy należy wykorzystać węzły CommentRangeStart i CommentRangeEnd
- IsInclusive. Określa, czy znaczniki są uwzględniane w ekstrakcji, czy nie. Jeśli ta opcja jest ustawiona na false i przekazany zostanie ten sam węzeł lub kolejne węzły, wówczas zwrócona zostanie pusta lista:
- Jeśli przekazany zostanie węzeł FieldStart, opcja ta określa, czy całe pole ma zostać uwzględnione, czy wykluczone
- Jeśli przekazany zostanie węzeł BookmarkStart lub BookmarkEnd, ta opcja określa, czy uwzględniona zostanie zakładka, czy tylko zawartość znajdująca się pomiędzy zakresem zakładek.
- W przypadku przekazania węzła CommentRangeStart lub CommentRangeEnd opcja ta określa, czy ma zostać uwzględniony sam komentarz, czy tylko treść w zakresie komentarza.
Implementację metody ExtractContent można znaleźć w w formacie Aspose.Words GitHub. Ta metoda zostanie omówiona w scenariuszach w tym artykule.
Zdefiniujemy również niestandardową metodę łatwego generowania dokumentu z wyodrębnionych węzłów. Ta metoda jest używana w wielu poniższych scenariuszach i polega po prostu na utworzeniu nowego dokumentu i zaimportowaniu do niego wyodrębnionej zawartości.
Poniższy przykład kodu pokazuje, jak pobrać listę węzłów i wstawić je do nowego dokumentu:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
public static Document GenerateDocument(Document srcDoc, List<Node> nodes) | |
{ | |
Document dstDoc = new Document(); | |
// Remove the first paragraph from the empty document. | |
dstDoc.FirstSection.Body.RemoveAllChildren(); | |
// Import each node from the list into the new document. Keep the original formatting of the node. | |
NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.KeepSourceFormatting); | |
foreach (Node node in nodes) | |
{ | |
Node importNode = importer.ImportNode(node, true); | |
dstDoc.FirstSection.Body.AppendChild(importNode); | |
} | |
return dstDoc; | |
} |
Wyodrębnij treść pomiędzy akapitami
To pokazuje, jak użyć powyższej metody do wyodrębnienia treści pomiędzy określonymi akapitami. W tym przypadku chcemy wyodrębnić treść listu znajdującą się w pierwszej połowie dokumentu. Możemy powiedzieć, że jest to pomiędzy akapitem 7 a 11.
Poniższy kod realizuje to zadanie. Odpowiednie akapity są wyodrębniane z dokumentu metodą GetChild i przekazują określone indeksy. Następnie przekazujemy te węzły do metody ExtractContent i stwierdzamy, że mają one zostać uwzględnione w ekstrakcji. Ta metoda zwróci skopiowaną treść pomiędzy tymi węzłami, która zostanie następnie wstawiona do nowego dokumentu.
Poniższy przykład kodu pokazuje, jak wyodrębnić treść pomiędzy określonymi akapitami przy użyciu powyższej metody ExtractContent
:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
Paragraph startPara = (Paragraph) doc.FirstSection.Body.GetChild(NodeType.Paragraph, 6, true); | |
Paragraph endPara = (Paragraph) doc.FirstSection.Body.GetChild(NodeType.Paragraph, 10, true); | |
// Extract the content between these nodes in the document. Include these markers in the extraction. | |
List<Node> extractedNodes = ExtractContentHelper.ExtractContent(startPara, endPara, true); | |
Document dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodes); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenParagraphs.docx"); |
Wyodrębnij zawartość pomiędzy różnymi typami węzłów
Możemy wyodrębnić treść pomiędzy dowolną kombinacją poziomów blokowych lub węzłów wbudowanych. W poniższym scenariuszu wyodrębnimy zawartość pomiędzy pierwszym akapitem a tabelą w drugiej sekcji włącznie. Węzły znaczników uzyskujemy wywołując metody FirstParagraph i GetChild w drugiej części dokumentu w celu pobrania odpowiednich węzłów Paragraph i Table. Aby uzyskać niewielką odmianę, zduplikujmy treść i wstawmy ją pod oryginałem.
Poniższy przykład kodu pokazuje, jak wyodrębnić zawartość między akapitem a tabelą przy użyciu metody ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
Paragraph startPara = (Paragraph) doc.LastSection.GetChild(NodeType.Paragraph, 2, true); | |
Table endTable = (Table) doc.LastSection.GetChild(NodeType.Table, 0, true); | |
// Extract the content between these nodes in the document. Include these markers in the extraction. | |
List<Node> extractedNodes = ExtractContentHelper.ExtractContent(startPara, endTable, true); | |
// Let's reverse the array to make inserting the content back into the document easier. | |
extractedNodes.Reverse(); | |
foreach (Node extractedNode in extractedNodes) | |
endTable.ParentNode.InsertAfter(extractedNode, endTable); | |
doc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenBlockLevelNodes.docx"); |
Wyodrębnij treść między akapitami na podstawie stylu
Może zaistnieć potrzeba wyodrębnienia treści pomiędzy akapitami o tym samym lub innym stylu, na przykład pomiędzy akapitami oznaczonymi stylami nagłówków. Poniższy kod pokazuje, jak to osiągnąć. Jest to prosty przykład, który wyodrębni zawartość pomiędzy pierwszym wystąpieniem stylów “Nagłówek 1” i “Nagłówek 3” bez wyodrębniania również nagłówków. Aby to zrobić, ustawiamy ostatni parametr na false, co określa, że węzły znaczników nie powinny być uwzględniane.
W prawidłowej implementacji powinno to zostać uruchomione w pętli, aby wyodrębnić zawartość pomiędzy wszystkimi akapitami tych stylów z dokumentu. Wyodrębniona treść jest kopiowana do nowego dokumentu.
Poniższy przykład kodu pokazuje, jak wyodrębnić treść pomiędzy akapitami o określonych stylach przy użyciu metody ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
// Gather a list of the paragraphs using the respective heading styles. | |
List<Paragraph> parasStyleHeading1 = ParagraphsByStyleName(doc, "Heading 1"); | |
List<Paragraph> parasStyleHeading3 = ParagraphsByStyleName(doc, "Heading 3"); | |
// Use the first instance of the paragraphs with those styles. | |
Node startPara = parasStyleHeading1[0]; | |
Node endPara = parasStyleHeading3[0]; | |
// Extract the content between these nodes in the document. Don't include these markers in the extraction. | |
List<Node> extractedNodes = ExtractContentHelper.ExtractContent(startPara, endPara, false); | |
Document dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodes); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenParagraphStyles.docx"); |
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
public List<Paragraph> ParagraphsByStyleName(Document doc, string styleName) | |
{ | |
// Create an array to collect paragraphs of the specified style. | |
List<Paragraph> paragraphsWithStyle = new List<Paragraph>(); | |
NodeCollection paragraphs = doc.GetChildNodes(NodeType.Paragraph, true); | |
// Look through all paragraphs to find those with the specified style. | |
foreach (Paragraph paragraph in paragraphs) | |
{ | |
if (paragraph.ParagraphFormat.Style.Name == styleName) | |
paragraphsWithStyle.Add(paragraph); | |
} | |
return paragraphsWithStyle; | |
} |
Wyodrębnij zawartość pomiędzy określonymi uruchomieniami
Możesz także wyodrębnić zawartość pomiędzy węzłami wbudowanymi, takimi jak Run. Runs z różnych akapitów można przekazywać jako znaczniki. Poniższy kod pokazuje, jak wyodrębnić określony tekst pomiędzy tym samym węzłem Paragraph.
Poniższy przykład kodu pokazuje, jak wyodrębnić treść pomiędzy określonymi ciągami tego samego akapitu przy użyciu metody ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
Paragraph para = (Paragraph) doc.GetChild(NodeType.Paragraph, 7, true); | |
Run startRun = para.Runs[1]; | |
Run endRun = para.Runs[4]; | |
// Extract the content between these nodes in the document. Include these markers in the extraction. | |
List<Node> extractedNodes = ExtractContentHelper.ExtractContent(startRun, endRun, true); | |
foreach (Node extractedNode in extractedNodes) | |
Console.WriteLine(extractedNode.ToString(SaveFormat.Text)); |
Wyodrębnij zawartość za pomocą pola
Aby użyć pola jako znacznika, należy przekazać węzeł FieldStart
. Ostatni parametr metody ExtractContent
określa, czy ma zostać uwzględnione całe pole, czy nie. Wyodrębnijmy treść pomiędzy polem scalania “Imię i nazwisko” a akapitem w dokumencie. Używamy metody MoveToMergeField klasy DocumentBuilder. Spowoduje to zwrócenie węzła FieldStart z przekazanej mu nazwy pola scalania.
W naszym przypadku ustawmy ostatni parametr przekazywany do metody ExtractContent na false, aby wykluczyć pole z ekstrakcji. Wyodrębnioną treść wyrenderujemy do formatu PDF.
Poniższy przykład kodu pokazuje, jak wyodrębnić treść pomiędzy określonym polem a akapitem w dokumencie przy użyciu metody ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
DocumentBuilder builder = new 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("Fullname", false, false); | |
// The builder cursor should be positioned at the start of the field. | |
FieldStart startField = (FieldStart) builder.CurrentNode; | |
Paragraph endPara = (Paragraph) doc.FirstSection.GetChild(NodeType.Paragraph, 5, true); | |
// Extract the content between these nodes in the document. Don't include these markers in the extraction. | |
List<Node> extractedNodes = ExtractContentHelper.ExtractContent(startField, endPara, false); | |
Document dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodes); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentUsingField.docx"); |
Wyodrębnij zawartość z zakładki
W dokumencie treść zdefiniowana w zakładce jest hermetyzowana przez węzły BookmarkStart
i BookmarkEnd. Treść znaleziona pomiędzy tymi dwoma węzłami tworzy zakładkę. Możesz przekazać którykolwiek z tych węzłów jako dowolny znacznik, nawet z różnych zakładek, pod warunkiem, że znacznik początkowy pojawi się przed znacznikiem końcowym w dokumencie. Wyodrębnimy tę treść do nowego dokumentu, korzystając z poniższego kodu. Opcja parametru IsInclusive pokazuje, jak zachować lub odrzucić zakładkę.
Poniższy przykład kodu pokazuje, jak wyodrębnić treść odwołującą się do zakładki przy użyciu metody ExtractContent:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
Bookmark bookmark = doc.Range.Bookmarks["Bookmark1"]; | |
BookmarkStart bookmarkStart = bookmark.BookmarkStart; | |
BookmarkEnd bookmarkEnd = bookmark.BookmarkEnd; | |
// Firstly, extract the content between these nodes, including the bookmark. | |
List<Node> extractedNodesInclusive = ExtractContentHelper.ExtractContent(bookmarkStart, bookmarkEnd, true); | |
Document dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodesInclusive); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenBookmark.IncludingBookmark.docx"); | |
// Secondly, extract the content between these nodes this time without including the bookmark. | |
List<Node> extractedNodesExclusive = ExtractContentHelper.ExtractContent(bookmarkStart, bookmarkEnd, false); | |
dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodesExclusive); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenBookmark.WithoutBookmark.docx"); |
Wyodrębnij treść z komentarza
Komentarz składa się z węzłów CommentRangeStart, CommentRangeEnd i Comment. Wszystkie te węzły są wbudowane. Pierwsze dwa węzły hermetyzują treść dokumentu, do której odwołuje się komentarz, jak widać na zrzucie ekranu poniżej.
Sam węzeł Comment jest plikiem InlineStory, który może zawierać akapity i przebiegi. Reprezentuje treść komentarza widzianą jako dymek komentarza w okienku recenzji. Ponieważ ten węzeł jest wbudowany i jest potomkiem treści, możesz także wyodrębnić treść z wnętrza tej wiadomości.
Komentarz obejmuje nagłówek, pierwszy akapit i tabelę w drugiej sekcji. Wyodrębnijmy ten komentarz do nowego dokumentu. Opcja IsInclusive określa, czy sam komentarz ma zostać zachowany, czy odrzucony.
Poniższy przykład kodu pokazuje, jak to zrobić:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
CommentRangeStart commentStart = (CommentRangeStart) doc.GetChild(NodeType.CommentRangeStart, 0, true); | |
CommentRangeEnd commentEnd = (CommentRangeEnd) doc.GetChild(NodeType.CommentRangeEnd, 0, true); | |
// Firstly, extract the content between these nodes including the comment as well. | |
List<Node> extractedNodesInclusive = ExtractContentHelper.ExtractContent(commentStart, commentEnd, true); | |
Document dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodesInclusive); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenCommentRange.IncludingComment.docx"); | |
// Secondly, extract the content between these nodes without the comment. | |
List<Node> extractedNodesExclusive = ExtractContentHelper.ExtractContent(commentStart, commentEnd, false); | |
dstDoc = ExtractContentHelper.GenerateDocument(doc, extractedNodesExclusive); | |
dstDoc.Save(ArtifactsDir + "ExtractContent.ExtractContentBetweenCommentRange.WithoutComment.docx"); |
Jak wyodrębnić zawartość za pomocą DocumentVisitor
Użyj klasy DocumentVisitor, aby zaimplementować ten scenariusz użycia. Klasa ta odpowiada dobrze znanemu wzorcowi projektowemu Visitor. Dzięki DocumentVisitor , możesz definiować i wykonywać niestandardowe operacje wymagające wyliczenia w drzewie dokumentu.
DocumentVisitor udostępnia zestaw metod VisitXXX, które są wywoływane w przypadku napotkania określonego elementu dokumentu (węzła). Na przykład format VisitParagraphStart jest wywoływany po znalezieniu początku akapitu tekstowego, a format VisitParagraphEnd jest wywoływany po znalezieniu końca akapitu tekstowego. Każda metoda DocumentVisitor.VisitXXX akceptuje odpowiedni obiekt, który napotka, więc możesz go użyć w razie potrzeby (powiedzmy pobrać formatowanie), np. zarówno DocumentVisitor.VisitParagraphStart, jak i DocumentVisitor.VisitParagraphEnd akceptują obiekt Paragraph.
Każda metoda DocumentVisitor.VisitXXX zwraca wartość VisitorAction, która kontroluje wyliczanie węzłów. Można zażądać kontynuacji wyliczania, pominięcia bieżącego węzła (ale kontynuowania wyliczania) lub zatrzymania wyliczania węzłów.
Oto kroki, które należy wykonać, aby programowo określić i wyodrębnić różne części dokumentu:
- Utwórz klasę pochodzącą z DocumentVisitor
- Zastąp i zapewnij implementacje niektórych lub wszystkich metod DocumentVisitor.VisitXXX w celu wykonania niektórych niestandardowych operacji
- Wywołaj Node.Accept na węźle, od którego chcesz rozpocząć wyliczenie, np. jeśli chcesz wyliczyć cały dokument, użyj Document.Accept
DocumentVisitor zapewnia domyślne implementacje wszystkich metod DocumentVisitor.VisitXXX. Ułatwia to tworzenie nowych osób odwiedzających dokument, ponieważ należy zastąpić tylko metody wymagane dla konkretnego odwiedzającego. Nie jest konieczne zastępowanie wszystkich metod odwiedzających.
Poniższy przykład pokazuje, jak użyć wzorca Visitor w celu dodania nowych operacji do modelu obiektowego Aspose.Words. W tym przypadku tworzymy prosty konwerter dokumentów do formatu tekstowego:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Extract content.docx"); | |
ConvertDocToTxt convertToPlainText = new 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. | |
Console.WriteLine(convertToPlainText.GetText()); |
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
/// <summary> | |
/// Simple implementation of saving a document in the plain text format. Implemented as a Visitor. | |
/// </summary> | |
internal class ConvertDocToTxt : DocumentVisitor | |
{ | |
public ConvertDocToTxt() | |
{ | |
mIsSkipText = false; | |
mBuilder = new StringBuilder(); | |
} | |
/// <summary> | |
/// Gets the plain text of the document that was accumulated by the visitor. | |
/// </summary> | |
public string GetText() | |
{ | |
return mBuilder.ToString(); | |
} | |
/// <summary> | |
/// Called when a Run node is encountered in the document. | |
/// </summary> | |
public override VisitorAction VisitRun(Run run) | |
{ | |
AppendText(run.Text); | |
// Let the visitor continue visiting other nodes. | |
return VisitorAction.Continue; | |
} | |
/// <summary> | |
/// Called when a FieldStart node is encountered in the document. | |
/// </summary> | |
public override VisitorAction VisitFieldStart(FieldStart 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> | |
public override VisitorAction VisitFieldSeparator(FieldSeparator 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> | |
public override VisitorAction VisitFieldEnd(FieldEnd 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> | |
public override VisitorAction VisitParagraphEnd(Paragraph paragraph) | |
{ | |
// When outputting to plain text we output Cr+Lf characters. | |
AppendText(ControlChar.CrLf); | |
return VisitorAction.Continue; | |
} | |
public override VisitorAction VisitBodyStart(Body 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("*** Body Started ***\r\n"); | |
return VisitorAction.Continue; | |
} | |
public override VisitorAction VisitBodyEnd(Body body) | |
{ | |
mBuilder.Append("*** Body Ended ***\r\n"); | |
return VisitorAction.Continue; | |
} | |
/// <summary> | |
/// Called when a HeaderFooter node is encountered in the document. | |
/// </summary> | |
public override VisitorAction VisitHeaderFooterStart(HeaderFooter 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; | |
} | |
/// <summary> | |
/// Adds text to the current output. Honors the enabled/disabled output flag. | |
/// </summary> | |
private void AppendText(string text) | |
{ | |
if (!mIsSkipText) | |
mBuilder.Append(text); | |
} | |
private readonly StringBuilder mBuilder; | |
private bool mIsSkipText; | |
} |
Jak wyodrębnić tylko tekst
Sposoby pobierania tekstu z dokumentu to:
- Użyj Document.Save z SaveFormat.Text, aby zapisać jako zwykły tekst w pliku lub strumieniu
- Użyj Node.ToString i przekaż parametr SaveFormat.Text. Wewnętrznie wywołuje to zapis jako tekst w strumieniu pamięci i zwraca wynikowy ciąg
- Użyj Node.GetText, aby pobrać tekst ze wszystkimi znakami kontrolnymi Microsoft Word, w tym kodami pól
- Zaimplementuj niestandardowy DocumentVisitor, aby przeprowadzić niestandardową ekstrakcję
Korzystanie z Node.GetText
i Node.ToString
Dokument programu Word może zawierać znaki sterujące, które oznaczają elementy specjalne, takie jak pole, koniec komórki, koniec sekcji itp. Pełna lista możliwych znaków sterujących programu Word jest zdefiniowana w klasie ControlChar. Metoda Node.GetText zwraca tekst zawierający wszystkie znaki sterujące obecne w węźle.
Wywołanie ToString zwraca tylko reprezentację dokumentu w postaci zwykłego tekstu, bez znaków kontrolnych. Więcej informacji na temat eksportowania jako zwykły tekst można znaleźć w następnej sekcji “Korzystanie z SaveFormat.Text”.
Poniższy przykład kodu pokazuje różnicę pomiędzy wywoływaniem metod GetText i ToString w węźle:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(); | |
DocumentBuilder builder = new DocumentBuilder(doc); | |
builder.InsertField("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. | |
Console.WriteLine("Convert to text result: " + doc.ToString(SaveFormat.Text)); |
Korzystanie z SaveFormat.Text
W tym przykładzie dokument zapisuje się w następujący sposób:
- Filtruje znaki i kody pól, kształty, przypisy dolne, przypisy końcowe i odniesienia do komentarzy
- Zastępuje znaki ControlChar.Cr końca akapitu kombinacjami ControlChar.CrLf
- Używa kodowania UTF8
Poniższy przykład kodu pokazuje, jak zapisać dokument w formacie TXT:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Document.docx"); | |
doc.Save(ArtifactsDir + "BaseConversions.DocxToTxt.txt"); |
Wyodrębnij obrazy z kształtów
Wykonanie niektórych zadań może wymagać wyodrębnienia obrazów dokumentów. Aspose.Words pozwala również to zrobić.
Poniższy przykład kodu pokazuje, jak wyodrębnić obrazy z dokumentu:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Images.docx"); | |
NodeCollection shapes = doc.GetChildNodes(NodeType.Shape, true); | |
int imageIndex = 0; | |
foreach (Shape shape in shapes) | |
{ | |
if (shape.HasImage) | |
{ | |
string imageFileName = | |
$"Image.ExportImages.{imageIndex}_{FileFormatUtil.ImageTypeToExtension(shape.ImageData.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.ImageData.Save(ArtifactsDir + imageFileName); | |
imageIndex++; | |
} | |
} |