Ekstrak Teks dari Dokumen MS Word di Jawa

Ekstraksi teks dari dokumen Word sering dilakukan dalam berbagai skenario. Misalnya untuk menganalisis teks, mengekstrak bagian tertentu dari suatu dokumen dan menggabungkannya menjadi satu dokumen, dan sebagainya. Pada artikel ini, Anda akan belajar cara mengekstrak teks dari dokumen Word secara terprogram di Java. Selain itu, kami akan membahas cara mengekstraksi konten antara elemen tertentu seperti paragraf, tabel, dll. Secara dinamis.

Perpustakaan Java untuk Mengekstrak Teks dari Dokumen Word

Aspose.Words for Java adalah perpustakaan yang kuat yang memungkinkan Anda membuat dokumen MS Word dari awal. Selain itu, ini memungkinkan Anda memanipulasi dokumen Word yang ada untuk enkripsi, konversi, ekstraksi teks, dll. Kami akan menggunakan pustaka ini untuk mengekstrak teks dari dokumen Word DOCX atau DOC. Anda dapat mengunduh JAR API atau menginstalnya menggunakan konfigurasi Maven berikut.

<repository>
    <id>AsposeJavaAPI</id>
    <name>Aspose Java API</name>
    <url>https://repository.aspose.com/repo/</url>
</repository>
<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-words</artifactId>
    <version>22.6</version>
    <type>pom</type>
</dependency>

Ekstraksi Teks di Word DOC/DOCX di Java

Dokumen MS Word terdiri dari berbagai elemen, yang meliputi paragraf, tabel, gambar, dll. Oleh karena itu, persyaratan ekstraksi teks dapat bervariasi dari satu skenario ke skenario lainnya. Misalnya, Anda mungkin perlu mengekstrak teks di antara paragraf, bookmark, komentar, dll.

Setiap jenis elemen dalam Word DOC/DOCX direpresentasikan sebagai node. Oleh karena itu, untuk memproses dokumen, Anda harus bermain dengan node. Jadi mari kita mulai dan lihat cara mengekstrak teks dari dokumen Word dalam berbagai skenario.

Ekstrak Teks dari Word DOC di Java

Pada bagian ini, kita akan menerapkan ekstraktor teks Java untuk dokumen Word dan alur kerja ekstraksi teks adalah sebagai berikut:

  • Pertama, kita akan menentukan node yang ingin kita sertakan dalam proses ekstraksi teks.
  • Kemudian, kami akan mengekstrak konten di antara node yang ditentukan (termasuk atau tidak termasuk node awal dan akhir).
  • Terakhir, kami akan menggunakan tiruan dari node yang diekstrak, misalnya untuk membuat dokumen Word baru yang terdiri dari konten yang diekstrak.

Sekarang mari kita tulis metode bernama extractContent yang akan kita berikan node dan beberapa parameter lain untuk melakukan ekstraksi teks. Metode ini akan mengurai dokumen dan mengkloning node. Berikut ini adalah parameter yang akan kita berikan pada metode ini.

  1. startNode dan endNode masing-masing sebagai titik awal dan akhir untuk ekstraksi konten. Ini bisa berupa node level blok (Paragraph , Tabel) atau level inline (mis. Jalankan, FieldStart, BookmarkStart, dll.).
    1. Untuk melewati bidang, Anda harus melewati objek FieldStart yang sesuai.
    2. Untuk melewati bookmark, simpul BookmarkStart dan BookmarkEnd harus dilewati.
    3. Untuk komentar, node CommentRangeStart dan CommentRangeEnd harus digunakan.
  2. isInclusive menentukan apakah penanda disertakan dalam ekstraksi atau tidak. Jika opsi ini disetel ke false dan node yang sama atau node berurutan dilewatkan, maka daftar kosong akan dikembalikan.

Berikut ini adalah implementasi lengkap dari metode extractContent yang mengekstrak konten antar node yang dilewatkan.

// Untuk contoh lengkap dan file data, silakan buka https://github.com/aspose-words/Aspose.Words-for-Java
public static ArrayList extractContent(Node startNode, Node endNode, boolean isInclusive) throws Exception {
    // Pertama periksa apakah node yang diteruskan ke metode ini valid untuk digunakan.
    verifyParameterNodes(startNode, endNode);

    // Buat daftar untuk menyimpan node yang diekstrak.
    ArrayList nodes = new ArrayList();

    // Catat node asli yang diteruskan ke metode ini sehingga kami dapat memisahkan node penanda jika diperlukan.
    Node originalStartNode = startNode;
    Node originalEndNode = endNode;

    // Ekstrak konten berdasarkan node level blok (paragraf dan tabel). Lintasi node induk untuk menemukannya.
    // Kami akan membagi konten node pertama dan terakhir tergantung apakah node penanda 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;
    // Node saat ini yang kami ekstrak dari dokumen.
    Node currNode = startNode;

    // Mulailah mengekstraksi konten. Memproses semua node level blok dan secara khusus membagi node pertama dan terakhir bila diperlukan sehingga pemformatan paragraf dipertahankan.
    // Metodenya sedikit lebih rumit daripada ekstraktor biasa karena kita perlu memperhitungkan faktor dalam mengekstraksi menggunakan node, bidang, bookmark, dll sebaris untuk membuatnya sangat berguna.
    while (isExtracting) {
        // Klon node saat ini dan turunannya untuk mendapatkan salinannya.
        /*System.out.println(currNode.getNodeType());
        if(currNode.getNodeType() == NodeType.EDITABLE_RANGE_START
                || currNode.getNodeType() == NodeType.EDITABLE_RANGE_END)
        {
            currNode = currNode.nextPreOrder(currNode.getDocument());
        }*/
        System.out.println(currNode);
        System.out.println(endNode);

        CompositeNode cloneNode = null;
        ///cloneNode = (CompositeNode) currNode.deepClone(true);

        Node inlineNode = null;
        if(currNode.isComposite())
        {
            cloneNode = (CompositeNode) currNode.deepClone(true);
        }
        else
        {
            if(currNode.getNodeType() == NodeType.BOOKMARK_END)
            {
                Paragraph paragraph = new Paragraph(currNode.getDocument());
                paragraph.getChildNodes().add(currNode.deepClone(true));
                cloneNode = (CompositeNode)paragraph.deepClone(true);
            }
        }

        isEndingNode = currNode.equals(endNode);

        if (isStartingNode || isEndingNode) {
            // Kita perlu memproses setiap penanda secara terpisah, jadi alihkan ke metode terpisah.
            if (isStartingNode) {
                processMarker(cloneNode, nodes, originalStartNode, isInclusive, isStartingNode, isEndingNode);
                isStartingNode = false;
            }

            // Kondisional perlu dipisahkan karena penanda awal dan akhir level blok mungkin node yang sama.
            if (isEndingNode) {
                processMarker(cloneNode, nodes, originalEndNode, isInclusive, isStartingNode, isEndingNode);
                isExtracting = false;
            }
        } else
            // Node bukan penanda awal atau akhir, cukup tambahkan salinan ke daftar.
            nodes.add(cloneNode);

        // Pindah ke node berikutnya dan ekstrak. Jika simpul berikutnya adalah nol, itu berarti sisa konten ditemukan di bagian yang berbeda.
        if (currNode.getNextSibling() == null && isExtracting) {
            // Pindah ke bagian berikutnya.
            Section nextSection = (Section) currNode.getAncestor(NodeType.SECTION).getNextSibling();
            currNode = nextSection.getBody().getFirstChild();
        } else {
            // Pindah ke node berikutnya dalam tubuh.
            currNode = currNode.getNextSibling();
        }
    }

    // Kembalikan node di antara penanda node.
    return nodes;
}

Beberapa metode pembantu juga diperlukan oleh metode extractContent untuk menyelesaikan operasi ekstraksi teks, yang diberikan di bawah ini.

/**
 * Memeriksa parameter input sudah benar dan dapat digunakan. Melempar pengecualian
 * jika ada masalah.
 */
private static void verifyParameterNodes(Node startNode, Node endNode) throws Exception {
	// Urutan pemeriksaan ini dilakukan adalah penting.
	if (startNode == null)
		throw new IllegalArgumentException("Start node cannot be null");
	if (endNode == null)
		throw new IllegalArgumentException("End node cannot be null");

	if (!startNode.getDocument().equals(endNode.getDocument()))
		throw new IllegalArgumentException("Start node and end node must belong to the same document");

	if (startNode.getAncestor(NodeType.BODY) == null || endNode.getAncestor(NodeType.BODY) == null)
		throw new IllegalArgumentException("Start node and end node must be a child or descendant of a body");

	// Periksa simpul akhir setelah simpul awal di pohon DOM
	// Pertama periksa apakah mereka berada di bagian yang berbeda, lalu periksa apakah tidak
	// posisi mereka di tubuh bagian yang sama tempat mereka berada.
	Section startSection = (Section) startNode.getAncestor(NodeType.SECTION);
	Section endSection = (Section) endNode.getAncestor(NodeType.SECTION);

	int startIndex = startSection.getParentNode().indexOf(startSection);
	int endIndex = endSection.getParentNode().indexOf(endSection);

	if (startIndex == endIndex) {
		if (startSection.getBody().indexOf(startNode) > endSection.getBody().indexOf(endNode))
			throw new IllegalArgumentException("The end node must be after the start node in the body");
	} else if (startIndex > endIndex)
		throw new IllegalArgumentException("The section of end node must be after the section start node");
}

/**
 * Memeriksa apakah node yang diteruskan adalah node inline.
 */
private static boolean isInline(Node node) throws Exception {
	// Uji apakah simpul tersebut adalah turunan dari simpul Paragraf atau Tabel dan juga bukan a
	// paragraf atau tabel paragraf di dalam kelas komentar yang merupakan turunan dari
	// pararaf mungkin.
	return ((node.getAncestor(NodeType.PARAGRAPH) != null || node.getAncestor(NodeType.TABLE) != null)
			&& !(node.getNodeType() == NodeType.PARAGRAPH || node.getNodeType() == NodeType.TABLE));
}

/**
 * Menghapus konten sebelum atau sesudah penanda di node yang dikloning tergantung
 * pada jenis penanda.
 */
private static void processMarker(CompositeNode cloneNode, ArrayList nodes, Node node, boolean isInclusive,
		boolean isStartMarker, boolean isEndMarker) throws Exception {
	// Jika kita berurusan dengan node level blok, lihat saja apakah itu harus disertakan
	// dan menambahkannya ke daftar.
	if (!isInline(node)) {
		// Jangan tambahkan node dua kali jika penandanya adalah node yang sama
		if (!(isStartMarker && isEndMarker)) {
			if (isInclusive)
				nodes.add(cloneNode);
		}
		return;
	}

	// Jika marker adalah node FieldStart, periksa apakah akan disertakan atau tidak.
	// Kami berasumsi untuk kesederhanaan bahwa FieldStart dan FieldEnd muncul sama
	// gugus kalimat.
	if (node.getNodeType() == NodeType.FIELD_START) {
		// Jika penanda adalah simpul awal dan tidak disertakan maka lewati ke akhir
		// lapangan.
		// Jika penanda adalah simpul akhir dan akan dimasukkan maka pindah ke akhir
		// bidang sehingga bidang tidak akan dihapus.
		if ((isStartMarker && !isInclusive) || (!isStartMarker && isInclusive)) {
			while (node.getNextSibling() != null && node.getNodeType() != NodeType.FIELD_END)
				node = node.getNextSibling();

		}
	}

	// Jika salah satu penanda adalah bagian dari komentar maka untuk menyertakan komentar itu sendiri kita
	// perlu memindahkan penunjuk ke depan ke Komentar
	// node ditemukan setelah node CommentRangeEnd.
	if (node.getNodeType() == NodeType.COMMENT_RANGE_END) {
		while (node.getNextSibling() != null && node.getNodeType() != NodeType.COMMENT)
			node = node.getNextSibling();

	}

	// Temukan node yang sesuai di node kloning kami berdasarkan indeks dan kembalikan.
	// Jika node awal dan akhir sama, beberapa node anak mungkin sudah memilikinya
	// telah dihapus. Kurangi
	// perbedaan untuk mendapatkan indeks yang tepat.
	int indexDiff = node.getParentNode().getChildNodes().getCount() - cloneNode.getChildNodes().getCount();

	// Node anak dihitung identik.
	if (indexDiff == 0)
		node = cloneNode.getChildNodes().get(node.getParentNode().indexOf(node));
	else
		node = cloneNode.getChildNodes().get(node.getParentNode().indexOf(node) - indexDiff);

	// Hapus node ke/dari penanda.
	boolean isSkip;
	boolean isProcessing = true;
	boolean isRemoving = isStartMarker;
	Node nextNode = cloneNode.getFirstChild();

	while (isProcessing && nextNode != null) {
		Node currentNode = nextNode;
		isSkip = false;

		if (currentNode.equals(node)) {
			if (isStartMarker) {
				isProcessing = false;
				if (isInclusive)
					isRemoving = false;
			} else {
				isRemoving = true;
				if (isInclusive)
					isSkip = true;
			}
		}

		nextNode = nextNode.getNextSibling();
		if (isRemoving && !isSkip)
			currentNode.remove();
	}

	// Setelah memproses node komposit mungkin menjadi kosong. Jika memiliki tidak termasuk
	// dia.
	if (!(isStartMarker && isEndMarker)) {
		if (cloneNode.hasChildNodes())
			nodes.add(cloneNode);
	}
}

public static Document generateDocument(Document srcDoc, ArrayList nodes) throws Exception {

	// Buat dokumen kosong.
	Document dstDoc = new Document();
	// Hapus paragraf pertama dari dokumen kosong.
	dstDoc.getFirstSection().getBody().removeAllChildren();

	// Impor setiap node dari daftar ke dalam dokumen baru. Simpan yang asli
	// pemformatan node.
	NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.KEEP_SOURCE_FORMATTING);

	for (Node node : (Iterable<Node>) nodes) {
		Node importNode = importer.importNode(node, true);
		dstDoc.getFirstSection().getBody().appendChild(importNode);
	}

	// Kembalikan dokumen yang dihasilkan.
	return dstDoc;
}

Sekarang kami siap menggunakan metode ini dan mengekstrak teks dari dokumen Word.

Ekstrak Java Teks antar Paragraf dalam Word DOC

Mari kita lihat cara mengekstrak konten di antara dua paragraf dalam dokumen Word DOCX. Berikut ini adalah langkah-langkah untuk melakukan operasi ini di Jawa.

  • Pertama, muat dokumen Word menggunakan kelas Document.
  • Dapatkan referensi paragraf awal dan akhir menjadi dua objek menggunakan metode Document.getFirstSection().getChild(NodeType.PARAGRAPH, int, bool).
  • Panggil metode extractContent(startPara, endPara, true) untuk mengekstrak node menjadi objek.
  • Panggil metode pembantu generateDocument(Document, extractNodes) untuk membuat dokumen yang terdiri dari konten yang diekstraksi.
  • Terakhir, simpan dokumen yang dikembalikan menggunakan metode Document.save(String).

Contoh kode berikut menunjukkan cara mengekstrak teks antara paragraf ke-7 dan ke-11 di Word DOCX di Java.

// Muat dokumen
Document doc = new Document("TestFile.doc");

// Kumpulkan node. Metode GetChild menggunakan indeks berbasis 0
Paragraph startPara = (Paragraph) doc.getFirstSection().getChild(NodeType.PARAGRAPH, 6, true);
Paragraph endPara = (Paragraph) doc.getFirstSection().getChild(NodeType.PARAGRAPH, 10, true);
// Ekstrak konten di antara simpul-simpul ini dalam dokumen. Sertakan ini
// penanda dalam ekstraksi.
ArrayList extractedNodes = extractContent(startPara, endPara, true);

// Masukkan konten ke dalam dokumen baru yang terpisah dan simpan ke disk.
Document dstDoc = generateDocument(doc, extractedNodes);
dstDoc.save("output.doc");

Ekstrak Java Teks dari DOC - Antara Berbagai Jenis Node

Anda juga dapat mengekstraksi konten di antara berbagai jenis node. Untuk demonstrasi, mari ekstrak konten antara paragraf dan tabel dan simpan ke dalam dokumen Word baru. Berikut ini adalah langkah-langkah untuk mengekstrak teks antara node yang berbeda dalam dokumen Word di Jawa.

  • Muat dokumen Word menggunakan kelas Document.
  • Dapatkan referensi node awal dan akhir menjadi dua objek menggunakan metode Document.getFirstSection().getChild(NodeType, int, bool).
  • Panggil metode extractContent(startPara, endPara, true) untuk mengekstrak node menjadi objek.
  • Panggil metode pembantu generateDocument(Document, extractNodes) untuk membuat dokumen yang terdiri dari konten yang diekstraksi.
  • Simpan dokumen yang dikembalikan menggunakan metode Document.save(String).

Contoh kode berikut menunjukkan cara mengekstrak teks antara paragraf dan tabel di DOCX menggunakan Java.

// Muat dokumen
Document doc = new Document("TestFile.doc");

// Dapatkan referensi paragraf awal
Paragraph startPara = (Paragraph) doc.getLastSection().getChild(NodeType.PARAGRAPH, 2, true);
Table endTable = (Table) doc.getLastSection().getChild(NodeType.TABLE, 0, true);

// Ekstrak konten di antara simpul-simpul ini dalam dokumen. Sertakan penanda ini dalam ekstraksi.
ArrayList extractedNodes = extractContent(startPara, endTable, true);

// Mari kita membalikkan larik untuk memasukkan konten kembali ke dalam dokumen dengan lebih mudah.
Collections.reverse(extractedNodes);

while (extractedNodes.size() > 0) {
    // Masukkan simpul terakhir dari daftar terbalik
    endTable.getParentNode().insertAfter((Node) extractedNodes.get(0), endTable);
    // Hapus node ini dari daftar setelah penyisipan.
    extractedNodes.remove(0);
}

// Simpan dokumen yang dihasilkan ke disk.
doc.save("output.doc");

Java Mengekstraksi Teks dari DOCX - Antara Paragraf berdasarkan Gaya

Sekarang mari kita lihat cara mengekstrak konten antar paragraf berdasarkan gaya. Untuk demonstrasi, kita akan mengekstrak konten antara “Heading 1” pertama dan “Heading 3” pertama dalam dokumen Word. Langkah-langkah berikut menunjukkan cara mencapainya di Jawa.

  • Pertama, muat dokumen Word menggunakan kelas Document.
  • Kemudian, ekstrak paragraf menjadi objek menggunakan metode pembantuparagraphsByStyleName(Document, “Heading 1”).
  • Ekstrak paragraf ke objek lain menggunakan metode pembantuparagraphsByStyleName(Document, “Heading 3”).
  • Panggil metode extractContent(startPara, endPara, true) dan teruskan elemen pertama di kedua larik paragraf sebagai parameter pertama dan kedua.
  • Panggil metode pembantu generateDocument(Document, extractNodes) untuk membuat dokumen yang terdiri dari konten yang diekstraksi.
  • Terakhir, simpan dokumen yang dikembalikan menggunakan metode Document.save(String).

Contoh kode berikut menunjukkan cara mengekstrak konten antar paragraf berdasarkan gaya.

// Muat dokumen
Document doc = new Document(dataDir + "TestFile.doc");

// Kumpulkan daftar paragraf menggunakan gaya tajuk masing-masing.
ArrayList parasStyleHeading1 = paragraphsByStyleName(doc, "Heading 1");
ArrayList parasStyleHeading3 = paragraphsByStyleName(doc, "Heading 3");

// Gunakan contoh paragraf pertama dengan gaya tersebut.
Node startPara1 = (Node) parasStyleHeading1.get(0);
Node endPara1 = (Node) parasStyleHeading3.get(0);

// Ekstrak konten di antara simpul-simpul ini dalam dokumen. Jangan sertakan penanda ini dalam ekstraksi.
ArrayList extractedNodes = extractContent(startPara1, endPara1, false);

// Masukkan konten ke dalam dokumen baru yang terpisah dan simpan ke disk.
Document dstDoc = generateDocument(doc, extractedNodes);
dstDoc.save("output.doc");

Ekstraktor Teks Kata Java - Baca Lebih Lanjut

Anda dapat menjelajahi skenario lain untuk mengekstraksi teks dari dokumen Word menggunakan artikel dokumentasi ini.

Java API untuk Mengekstrak Teks dari DOC/DOCX - Dapatkan Lisensi Gratis

Anda bisa mendapatkan lisensi sementara untuk menggunakan Aspose.Words for Java tanpa batasan evaluasi.

Kesimpulan

Pada artikel ini, Anda telah mempelajari cara mengekstrak teks dari MS Word DOC DOCX di Java. Selain itu, Anda telah melihat cara mengekstraksi konten antara jenis node yang serupa atau berbeda dalam dokumen Word secara terprogram. Dengan demikian, Anda dapat membuat ekstraktor teks MS Word Anda sendiri di Java. Selain itu, Anda dapat menjelajahi fitur lain dari Aspose.Words for Java menggunakan dokumentasi. Jika Anda memiliki pertanyaan, jangan ragu untuk memberi tahu kami melalui forum kami.

Lihat juga