Abrufen des Texts der Absätze (C#)Retrieving the Text of the Paragraphs (C#)

Dieses Beispiel baut auf dem vorherigen Beispiel Retrieving the Paragraphs and Their Styles (C#) (Abrufen der Absätze und deren Formate (C#)) auf.This example builds on the previous example, Retrieving the Paragraphs and Their Styles (C#). Dieses neue Beispiel ruft den Text jedes einzelnen Absatzes als Zeichenfolge abThis new example retrieves the text of each paragraph as a string.

Zum Abrufen des Texts fügt dieses Beispiel eine zusätzliche Abfrage hinzu, die die Auflistung der anonymen Typen durchläuft und eine neue Auflistung eines anonymen Typs unter Hinzufügung eines neuen Members, Text, projiziertTo retrieve the text, this example adds an additional query that iterates through the collection of anonymous types and projects a new collection of an anonymous type with the addition of a new member, Text. Mithilfe des Aggregate-Standardabfrageoperators werden mehrere Zeichenfolgen zu einer Zeichenfolge verkettet.It uses the Aggregate standard query operator to concatenate multiple strings into one string.

Dieses Verfahren (erst eine Auflistung eines anonymen Typs projizieren und dann diese Auflistung zum Projizieren einer neuen Auflistung eines anonymen Typs verwenden) ist eine häufig verwendete und sinnvolle Vorgehensweise.This technique (that is, first projecting to a collection of an anonymous type, then using this collection to project to a new collection of an anonymous type) is a common and useful idiom. Diese Abfrage hätte auch ohne Projizieren in den ersten anonymen Typ geschrieben werden können.This query could have been written without projecting to the first anonymous type. Aufgrund der verzögerten Auswertung wird aber nicht allzu viel zusätzliche Rechenleistung beansprucht.However, because of lazy evaluation, doing so does not use much additional processing power. Die Ausdrucksweise erstellt zwar mehr kurzlebige Objekte auf dem Heap, dies führt aber nur zu unerheblichen Leistungseinbußen.The idiom creates more short lived objects on the heap, but this does not substantially degrade performance.

Natürlich wäre es auch möglich, eine einzelne Abfrage zu schreiben, die die Funktionalität zum Abrufen der Absätze, der Formatvorlagen der einzelnen Absätze und des Texts in den Absätzen enthält.Of course, it would be possible to write a single query that contains the functionality to retrieve the paragraphs, the style of each paragraph, and the text of each paragraph. Häufig ist es aber sinnvoll, eine kompliziertere Abfrage in mehrere Abfragen aufzuteilen, weil der resultierende Code dann modularer und einfacher zu verwalten ist.However, it often is useful to break up a more complicated query into multiple queries because the resulting code is more modular and easier to maintain. Wenn Sie einen Teil der Abfrage wiederverwenden müssen und die Abfragen auf diese Weise geschrieben sind, können Sie den entsprechenden Abfrageteil auch einfacher umgestalten.Furthermore, if you need to reuse a portion of the query, it is easier to refactor if the queries are written in this manner.

Diese miteinander verketteten Abfragen verwenden das Verarbeitungsmodell, das im Thema Tutorial: Chaining Queries Together (C#) (Tutorial: Verketten von Abfragen (C#)) ausführlich erläutert wird.These queries, which are chained together, use the processing model that is examined in detail in the topic Tutorial: Chaining Queries Together (C#).

BeispielExample

Dieses Beispiel verarbeitet ein WordprocessingML-Dokument, indem es den Elementknoten, die Namen der Formatvorlagen und den Text der einzelnen Absätze bestimmt.This example processes a WordprocessingML document, determining the element node, the style name, and the text of each paragraph. Das Beispiel baut auf den vorherigen Beispielen dieses Lernprogramms auf.This example builds on the previous examples in this tutorial. Die neue Abfrage wird im Code unten durch entsprechende Kommentare gekennzeichnet.The new query is called out in comments in the code below.

Eine Anleitung zum Erstellen des Quelldokuments für dieses Beispiel finden Sie unter Creating the Source Office Open XML Document (C#) (Erstellen eines Office Open-Quell-XML-Dokuments (C#)).For instructions for creating the source document for this example, see Creating the Source Office Open XML Document (C#).

Dieses Beispiel verwendet Klassen aus der WindowsBase-Assembly.This example uses classes from the WindowsBase assembly. Außerdem werden Typen im System.IO.Packaging-Namespace verwendet.It uses types in the System.IO.Packaging namespace.

const string fileName = "SampleDoc.docx";  

const string documentRelationshipType =  
  "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";  
const string stylesRelationshipType =  
  "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";  
const string wordmlNamespace =  
  "http://schemas.openxmlformats.org/wordprocessingml/2006/main";  
XNamespace w = wordmlNamespace;  

XDocument xDoc = null;  
XDocument styleDoc = null;  

using (Package wdPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read))  
{  
    PackageRelationship docPackageRelationship =  
      wdPackage.GetRelationshipsByType(documentRelationshipType).FirstOrDefault();  
    if (docPackageRelationship != null)  
    {  
        Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative),  
          docPackageRelationship.TargetUri);  
        PackagePart documentPart = wdPackage.GetPart(documentUri);  

        //  Load the document XML in the part into an XDocument instance.  
        xDoc = XDocument.Load(XmlReader.Create(documentPart.GetStream()));  

        //  Find the styles part. There will only be one.  
        PackageRelationship styleRelation =  
          documentPart.GetRelationshipsByType(stylesRelationshipType).FirstOrDefault();  
        if (styleRelation != null)  
        {  
            Uri styleUri = PackUriHelper.ResolvePartUri(documentUri, styleRelation.TargetUri);  
            PackagePart stylePart = wdPackage.GetPart(styleUri);  

            //  Load the style XML in the part into an XDocument instance.  
            styleDoc = XDocument.Load(XmlReader.Create(stylePart.GetStream()));  
        }  
    }  
}  

string defaultStyle =   
    (string)(  
        from style in styleDoc.Root.Elements(w + "style")  
        where (string)style.Attribute(w + "type") == "paragraph"&&  
              (string)style.Attribute(w + "default") == "1"  
              select style  
    ).First().Attribute(w + "styleId");  

// Find all paragraphs in the document.  
var paragraphs =  
    from para in xDoc  
                 .Root  
                 .Element(w + "body")  
                 .Descendants(w + "p")  
    let styleNode = para  
                    .Elements(w + "pPr")  
                    .Elements(w + "pStyle")  
                    .FirstOrDefault()  
    select new  
    {  
        ParagraphNode = para,  
        StyleName = styleNode != null ?  
            (string)styleNode.Attribute(w + "val") :  
            defaultStyle  
    };  

// Following is the new query that retrieves the text of  
// each paragraph.  
var paraWithText =  
    from para in paragraphs  
    select new  
    {  
        ParagraphNode = para.ParagraphNode,  
        StyleName = para.StyleName,  
        Text = para  
               .ParagraphNode  
               .Elements(w + "r")  
               .Elements(w + "t")  
               .Aggregate(  
                   new StringBuilder(),  
                   (s, i) => s.Append((string)i),  
                   s => s.ToString()  
               )  
    };  

foreach (var p in paraWithText)  
    Console.WriteLine("StyleName:{0} >{1}<", p.StyleName, p.Text);  

Dieses Beispiel produziert bei Anwendung auf das in Creating the Source Office Open XML Document (C#) (Erstellen eines Office Open-Quell-XML-Dokuments (C#)) beschriebene Dokument die folgende Ausgabe.This example produces the following output when applied to the document described in Creating the Source Office Open XML Document (C#).

StyleName:Heading1 >Parsing WordprocessingML with LINQ to XML<  
StyleName:Normal ><  
StyleName:Normal >The following example prints to the console.<  
StyleName:Normal ><  
StyleName:Code >using System;<  
StyleName:Code ><  
StyleName:Code >class Program {<  
StyleName:Code >    public static void (string[] args) {<  
StyleName:Code >        Console.WriteLine("Hello World");<  
StyleName:Code >    }<  
StyleName:Code >}<  
StyleName:Normal ><  
StyleName:Normal >This example produces the following output:<  
StyleName:Normal ><  
StyleName:Code >Hello World<  

Nächste SchritteNext Steps

Im nächsten Beispiel wird gezeigt, wie Sie zum Verketten mehrerer Zeichenfolgen zu einer einzelnen Zeichenfolge statt Aggregate eine Erweiterungsmethode verwenden können:The next example shows how to use an extension method, instead of Aggregate, to concatenate multiple strings into a single string.

Siehe auchSee Also

Tutorial: Manipulating Content in a WordprocessingML Document (C#) (Tutorial: Bearbeiten von Inhalten in einem WordprocessingML-Dokument (C#))Tutorial: Manipulating Content in a WordprocessingML Document (C#)
Deferred Execution and Lazy Evaluation in LINQ to XML (C#) (Verzögerte Ausführung und Auswertung in LINQ to XML (C#))Deferred Execution and Lazy Evaluation in LINQ to XML (C#)