Freigeben über


Ersetzen von Text in einem Word-Dokument mithilfe von SAX (Simple API for XML)

In diesem Thema wird gezeigt, wie Sie das Open XML SDK verwenden, um Text in einem Word Dokument mithilfe des SAX-Ansatzes (Simple API for XML) durch das Open XML SDK zu suchen und zu ersetzen. Weitere Informationen zur grundlegenden Struktur eines WordprocessingML Dokuments finden Sie unter Struktur eines WordprocessingML-Dokuments.

Gründe für die Verwendung des SAX-Ansatzes

Das Open XML SDK bietet zwei Möglichkeiten zum Analysieren von Office Open XML-Dateien: das Dokumentobjektmodell (DOM) und die Simple API for XML (SAX). Der DOM-Ansatz wurde entwickelt, um das Abfragen und Analysieren von Open XML-Dateien mithilfe von stark typisierten Klassen zu vereinfachen. Der DOM-Ansatz erfordert jedoch das Laden ganzer Open XML-Teile in den Arbeitsspeicher, was bei der Arbeit mit sehr großen Teilen zu einer langsameren Verarbeitung und Zu wenig Arbeitsspeicher führen kann. Der SAX-Ansatz liest den XML-Code in einem Open XML-Teil elementweise ein, ohne den gesamten Teil in den Arbeitsspeicher zu lesen, sodass nicht zwischengespeicherter Vorwärtszugriff auf die XML-Daten ermöglicht wird. Dies macht es zu einer besseren Wahl beim Lesen sehr großer Teile.

Zugreifen auf MainDocumentPart

Der Text eines Word Dokuments wird im MainDocumentPartgespeichert, sodass der erste Schritt zum Suchen und Ersetzen von Text darin besteht, auf die Word Dokument MainDocumentPartzuzugreifen. Dazu verwenden wir zunächst die WordprocessingDocument.Open -Methode, die den Pfad zum Dokument als ersten Parameter übergibt, und einen zweiten Parameter true , um anzugeben, dass die Datei zur Bearbeitung geöffnet wird. Stellen Sie dann sicher, dass nicht MainDocumentPart NULL ist.

// Open the WordprocessingDocument for editing
using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(path, true))
{
    // Access the MainDocumentPart and make sure it is not null
    MainDocumentPart? mainDocumentPart = wordprocessingDocument.MainDocumentPart;

    if (mainDocumentPart is not null)

Erstellen von Memory Stream, OpenXmlReader und OpenXmlWriter

Beim DOM-Ansatz zum Bearbeiten von Dokumenten wird der gesamte Teil in den Arbeitsspeicher eingelesen, sodass wir die stark typisierten Klassen des Open XML SDK verwenden können, um auf die Text Klasse zuzugreifen, um auf den Text des Dokuments zuzugreifen und ihn zu bearbeiten. Der SAX-Ansatz verwendet jedoch die OpenXmlPartReader Klassen und OpenXmlPartWriter , die mit vorwärtsgerichtetem Zugriff auf den Datenstrom eines Teils zugreifen. Dies hat den Vorteil, dass das gesamte Teil nicht in den Arbeitsspeicher geladen werden muss, was schneller ist und weniger Arbeitsspeicher verwendet. Da derselbe Teil jedoch nicht in mehreren Streams gleichzeitig geöffnet werden kann, können wir keine erstellen OpenXmlReader , um einen Teil zu lesen, und ein OpenXmlWriter , um denselben Teil gleichzeitig zu bearbeiten. Die Lösung hierfür besteht darin, einen zusätzlichen Speicherdatenstrom zu erstellen und den aktualisierten Teil in den neuen Speicherdatenstrom zu schreiben und dann den Stream zu verwenden, um den Teil zu aktualisieren, wenn OpenXmlReader und OpenXmlWriter verworfen wurden. Im folgenden Code erstellen wir die MemoryStream , um den aktualisierten Teil zu speichern, und erstellen eine OpenXmlReader für die MainDocumentPart und eine OpenXmlWriter , um in die MemoryStream

// Create a MemoryStream to store the updated MainDocumentPart
using (MemoryStream memoryStream = new MemoryStream())
{
    // Create an OpenXmlReader to read the main document part
    // and an OpenXmlWriter to write to the MemoryStream
    using (OpenXmlReader reader = OpenXmlPartReader.Create(mainDocumentPart))
    using (OpenXmlWriter writer = OpenXmlPartWriter.Create(memoryStream))

Lesen des Teils und Schreiben in die neue Stream

Da wir nun einen OpenXmlReader haben, um den Teil zu lesen, und ein OpenXmlWriter , um in das neue MemoryStream zu schreiben, verwenden wir die Read -Methode, um jedes Element im Teil zu lesen. Wenn jedes Element gelesen wird, überprüfen wir, ob es vom Typ ist, und wenn dies der Wert Text ist, verwenden wir die <xrefDocumentFormat.OpenXml.OpenXmlReader.GetText*-> Methode, um auf den Text zuzugreifen und Replace den Text zu aktualisieren. Wenn es sich nicht um ein Text Element handelt, wird es unverändert in den Stream geschrieben.

Hinweis

In einem Word Dokumenttext in mehrere Text Elemente unterteilt werden kann. Wenn Sie also einen Ausdruck und nicht ein einzelnes Wort ersetzen, empfiehlt es sich, jeweils ein Wort zu ersetzen.

// Write the XML declaration with the version "1.0".
writer.WriteStartDocument();

// Read the elements from the MainDocumentPart
while (reader.Read())
{
    // Check if the element is of type Text
    if (reader.ElementType == typeof(Text))
    {
        // If it is the start of an element write the start element and the updated text
        if (reader.IsStartElement)
        {
            writer.WriteStartElement(reader);

            string text = reader.GetText().Replace(textToReplace, replacementText);

            writer.WriteString(text);

        }
        else
        {
            // Close the element
            writer.WriteEndElement();
        }
    }
    else
    // Write the other XML elements without editing
    {
        if (reader.IsStartElement)
        {
            writer.WriteStartElement(reader);
        }
        else if (reader.IsEndElement)
        {
            writer.WriteEndElement();
        }
    }
}

Schreiben der neuen Stream in MainDocumentPart

Wenn der aktualisierte Teil in den Speicherstream geschrieben wird, besteht der letzte Schritt darin, die Position von MemoryStreamauf 0 festzulegen und die FeedData -Methode zu verwenden, um den MainDocumentPart durch den aktualisierten Stream zu ersetzen.

// Set the MemoryStream's position to 0 and replace the MainDocumentPart
memoryStream.Position = 0;
mainDocumentPart.FeedData(memoryStream);

Beispielcode

Im Folgenden finden Sie den vollständigen Beispielcode zum Ersetzen von Text in einem Word Dokument mithilfe des SAX-Ansatzes (Simple API for XML).

void ReplaceTextWithSAX(string path, string textToReplace, string replacementText)
{
    // Open the WordprocessingDocument for editing
    using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(path, true))
    {
        // Access the MainDocumentPart and make sure it is not null
        MainDocumentPart? mainDocumentPart = wordprocessingDocument.MainDocumentPart;

        if (mainDocumentPart is not null)
        {
            // Create a MemoryStream to store the updated MainDocumentPart
            using (MemoryStream memoryStream = new MemoryStream())
            {
                // Create an OpenXmlReader to read the main document part
                // and an OpenXmlWriter to write to the MemoryStream
                using (OpenXmlReader reader = OpenXmlPartReader.Create(mainDocumentPart))
                using (OpenXmlWriter writer = OpenXmlPartWriter.Create(memoryStream))
                {
                    // Write the XML declaration with the version "1.0".
                    writer.WriteStartDocument();
                    
                    // Read the elements from the MainDocumentPart
                    while (reader.Read())
                    {
                        // Check if the element is of type Text
                        if (reader.ElementType == typeof(Text))
                        {
                            // If it is the start of an element write the start element and the updated text
                            if (reader.IsStartElement)
                            {
                                writer.WriteStartElement(reader);

                                string text = reader.GetText().Replace(textToReplace, replacementText);

                                writer.WriteString(text);

                            }
                            else
                            {
                                // Close the element
                                writer.WriteEndElement();
                            }
                        }
                        else
                        // Write the other XML elements without editing
                        {
                            if (reader.IsStartElement)
                            {
                                writer.WriteStartElement(reader);
                            }
                            else if (reader.IsEndElement)
                            {
                                writer.WriteEndElement();
                            }
                        }
                    }
                }
                // Set the MemoryStream's position to 0 and replace the MainDocumentPart
                memoryStream.Position = 0;
                mainDocumentPart.FeedData(memoryStream);
            }
        }
    }
}