Abrufen der Absätze und ihrer Stile (C#)Retrieving the Paragraphs and Their Styles (C#)

In diesem Beispiel schreiben wir eine Abfrage, die die Absatzknoten aus einem WordprocessingML-Dokument abruft.In this example, we write a query that retrieves the paragraph nodes from a WordprocessingML document. Außerdem ermittelt es für jeden Absatz die verwendete Formatvorlage.It also identifies the style of each paragraph.

Diese Abfrage baut auf der Abfrage im vorherigen Beispiel auf, Finding the Default Paragraph Style (C#) (Suchen der standardmäßigen Absatzformatvorlage (C#)), in der die Standardformatvorlage aus der Liste der Formatvorlagen abgerufen wird.This query builds on the query in the previous example, Finding the Default Paragraph Style (C#), which retrieves the default style from the list of styles. Diese Information wird benötigt, damit die Abfrage die Formatvorlagen der Absätze abrufen kann, für die keine Formatvorlage explizit festgelegt ist.This information is required so that the query can identify the style of paragraphs that do not have a style explicitly set. Absatzformatvorlagen werden über das w:pPr-Element festgelegt. Wenn ein Absatz dieses Element nicht enthält, wird er mit der Standardformatvorlage formatiert.Paragraph styles are set through the w:pPr element; if a paragraph does not contain this element, it is formatted with the default style.

In diesem Thema wird die Bedeutung einiger Teile der Abfrage erläutert, bevor die Abfrage im Kontext eines vollständigen, funktionstüchtigen Beispiels gezeigt wird.This topic explains the significance of some pieces of the query, then shows the query as part of a complete, working example.

BeispielExample

Die Abfrage verwendet zum Abrufen aller in einem Dokument vorhandenen Absätze und der zugehörigen Formatvorlagen die folgende Quelle:The source of the query to retrieve all the paragraphs in a document and their styles is as follows:

xDoc.Root.Element(w + "body").Descendants(w + "p")  

Dieser Ausdruck ähnelt der Quelle der Abfrage im vorherigen Beispiel, Finding the Default Paragraph Style (C#), (Suchen der standardmäßigen Absatzformatvorlage (C#)).This expression is similar to the source of the query in the previous example, Finding the Default Paragraph Style (C#). Der Hauptunterschied besteht darin, dass der Ausdruck anstelle der Descendants-Achse die Elements-Achse verwendet.The main difference is that it uses the Descendants axis instead of the Elements axis. Die Abfrage verwendet die Descendants-Achse, weil in Dokumenten mit Abschnitten die Absätze nicht die direkten untergeordneten Elemente des Textkörpers sind. Die Absätze befinden sich zwei Ebenen weiter unten in der Hierarchie.The query uses the Descendants axis because in documents that have sections, the paragraphs will not be the direct children of the body element; rather, the paragraphs will be two levels down in the hierarchy. Durch die Verwendung der Descendants-Achse funktioniert der Code unabhängig davon, ob das Dokument Abschnitte verwendet.By using the Descendants axis, the code will work of whether or not the document uses sections.

BeispielExample

Die Abfrage verwendet eine let-Klausel, um das Element zu bestimmen, das den Formatvorlagenknoten enthält.The query uses a let clause to determine the element that contains the style node. Wenn es kein Element gibt, wird styleNode auf null gesetzt.If there is no element, then styleNode is set to null:

let styleNode = para.Elements(w + "pPr").Elements(w + "pStyle").FirstOrDefault()  

Die let-Klausel verwendet zuerst die Elements-Achse, um nach allen Elementen mit dem Namen pPr zu suchen, und sucht dann mit der Elements-Erweiterungsmethode nach allen untergeordneten Elementen mit dem Namen pStyle. Schließlich verwendet sie den FirstOrDefault-Standardabfrageoperator, um die Auflistung in ein Singleton umzuwandeln.The let clause first uses the Elements axis to find all elements named pPr, then uses the Elements extension method to find all child elements named pStyle, and finally uses the FirstOrDefault standard query operator to convert the collection to a singleton. Wenn die Auflistung leer ist, wird styleNode auf null gesetzt.If the collection is empty, styleNode is set to null. Dies ist eine sinnvolle Vorgehensweise, um nach dem pStyle-Nachfolgerknoten zu suchen.This is a useful idiom to look for the pStyle descendant node. Beachten Sie dabei: Wenn der untergeordnete pPr-Knoten nicht existiert, löst der Code keine Ausnahme aus, sondern styleNode wird auf null gesetzt, was dem erwünschten Verhalten dieser let-Klausel entspricht.Note that if the pPr child node does not exist, the code does nor fail by throwing an exception; instead, styleNode is set to null, which is the desired behavior of this let clause.

Die Abfrage projiziert eine Auflistung eines anonymen Typs mit zwei Membern, StyleName und ParagraphNode.The query projects a collection of an anonymous type with two members, StyleName and ParagraphNode.

BeispielExample

Dieses Beispiel verarbeitet ein WordprocessingML-Dokument, indem es die Absatzknoten aus einem WordprocessingML-Dokument abruft.This example processes a WordprocessingML document, retrieving the paragraph nodes from a WordprocessingML document. Außerdem ermittelt es für jeden Absatz die verwendete Formatvorlage.It also identifies the style 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#)).You can find instructions for creating the source document for this example in Creating the Source Office Open XML Document (C#).

Dieses Beispiel verwendet Klassen aus der WindowsBase-Assembly.This example uses classes found in 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");  

// Following is the new query that finds all paragraphs in the  
// document and their styles.  
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  
    };  

foreach (var p in paragraphs)  
    Console.WriteLine("StyleName:{0}", p.StyleName);  

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  
StyleName:Normal  
StyleName:Normal  
StyleName:Normal  
StyleName:Code  
StyleName:Code  
StyleName:Code  
StyleName:Code  
StyleName:Code  
StyleName:Code  
StyleName:Code  
StyleName:Normal  
StyleName:Normal  
StyleName:Normal  
StyleName:Code  

Nächste SchritteNext Steps

Im nächsten Thema, Abrufen des Texts der Absätze (C#), erstellen Sie eine Abfrage zum Abrufen des Texts der Absätze.In the next topic, Retrieving the Text of the Paragraphs (C#), you'll create a query to retrieve the text of paragraphs.

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#)