Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo esempio si basa sull'esempio precedente, Recuperare i paragrafi e i relativi stili. Questo nuovo esempio consente di recuperare il testo di ciascun paragrafo sotto forma di stringa.
Per recuperare il testo, nell'esempio viene aggiunta un'ulteriore query che scorre la raccolta di tipi anonimi e proietta una nuova raccolta di un tipo anonimo con l'aggiunta di un nuovo membro Text. Viene usato l'operatore di query standard Aggregate per concatenare più stringhe in un'unica stringa.
Questa tecnica, che prevede dapprima la proiezione di una raccolta di un tipo anonimo e quindi l'uso di questa raccolta per la proiezione in una nuova raccolta di un tipo anonimo, è comune e utile. Sarebbe stato possibile scrivere la query senza la proiezione nel primo tipo anonimo, Tuttavia, a causa della valutazione lazy, tale tecnica non è più onerosa in termini di potenza di elaborazione. La tecnica crea più oggetti temporanei sull'heap, ma senza influire sostanzialmente sulle prestazioni.
Sarebbe naturalmente possibile scrivere una singola query che contiene la funzionalità per recuperare i paragrafi, nonché lo stile e il testo di ogni paragrafo. Tuttavia, è spesso utile suddividere una query più complessa in più query, perché il codice risultante è più modulare e più facilmente gestibile. Se inoltre è necessario riutilizzare parte della query, risulta più agevole effettuare il refactoring se le query sono scritte in questo modo.
Queste query, che vengono concatenate, usano il modello di elaborazione esaminato in dettaglio nell'argomento Esempio di concatenazione di query.
Esempio: Determinare il nodo dell'elemento, il nome dello stile e il testo di ogni paragrafo
Questo esempio elabora un documento WordprocessingML, determinando il nodo dell'elemento, il nome dello stile e il testo di ogni paragrafo. Questo esempio si basa su esempi precedenti di questa esercitazione. La nuova query è indicata nei commenti del codice riportato di seguito.
Per istruzioni per la creazione del documento di origine di questo esempio, vedere Creare il documento Office Open XML di origine.
In questo esempio vengono usate classi dell'assembly WindowsBase e i tipi dello spazio dei nomi System.IO.Packaging.
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);
Imports <xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
Module Module1
' Following function is required because Visual Basic doesn't support short circuit evaluation
Private Function GetStyleOfParagraph(ByVal styleNode As XElement, _
ByVal defaultStyle As String) As String
If (styleNode Is Nothing) Then
Return defaultStyle
Else
Return styleNode.@w:val
End If
End Function
Sub Main()
Dim fileName = "SampleDoc.docx"
Dim documentRelationshipType = _
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Dim stylesRelationshipType = _
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
Dim wordmlNamespace = _
"http://schemas.openxmlformats.org/wordprocessingml/2006/main"
Dim xDoc As XDocument = Nothing
Dim styleDoc As XDocument = Nothing
Using wdPackage As Package = Package.Open(fileName, FileMode.Open, FileAccess.Read)
Dim docPackageRelationship As PackageRelationship = _
wdPackage.GetRelationshipsByType(documentRelationshipType).FirstOrDefault()
If (docPackageRelationship IsNot Nothing) Then
Dim documentUri As Uri = PackUriHelper.ResolvePartUri(New Uri("/", UriKind.Relative), _
docPackageRelationship.TargetUri)
Dim documentPart As PackagePart = 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.
Dim styleRelation As PackageRelationship = _
documentPart.GetRelationshipsByType(stylesRelationshipType).FirstOrDefault()
If (styleRelation IsNot Nothing) Then
Dim styleUri As Uri = _
PackUriHelper.ResolvePartUri(documentUri, styleRelation.TargetUri)
Dim stylePart As PackagePart = wdPackage.GetPart(styleUri)
' Load the style XML in the part into an XDocument instance.
styleDoc = XDocument.Load(XmlReader.Create(stylePart.GetStream()))
End If
End If
End Using
Dim defaultStyle As String = _
( _
From style In styleDoc.Root.<w:style> _
Where style.@w:type = "paragraph" And _
style.@w:default = "1" _
Select style _
).First().@w:styleId
' Find all paragraphs in the document.
Dim paragraphs = _
From para In xDoc.Root.<w:body>...<w:p> _
Let styleNode As XElement = para.<w:pPr>.<w:pStyle>.FirstOrDefault _
Select New With { _
.ParagraphNode = para, _
.StyleName = GetStyleOfParagraph(styleNode, defaultStyle) _
}
' Following is the new query that retrieves the text of
' each paragraph.
Dim paraWithText = _
From para In paragraphs _
Select New With { _
.ParagraphNode = para.ParagraphNode, _
.StyleName = para.StyleName, _
.Text = para.ParagraphNode.<w:r>.<w:t> _
.Aggregate(New StringBuilder(), _
Function(s As StringBuilder, i As String) s.Append(CStr(i)), _
Function(s As StringBuilder) s.ToString) _
}
For Each p In paraWithText
Console.WriteLine("StyleName:{0} >{1}<", p.StyleName, p.Text)
Next
End Sub
End Module
La versione in C# di questo esempio produce l'output seguente:
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<
La versione in Visual Basic di questo esempio produce l'output seguente:
StyleName:Heading1 >Parsing WordprocessingML with LINQ to XML<
StyleName:Normal ><
StyleName:Normal >The following example prints to the console.<
StyleName:Normal ><
StyleName:Code >Imports System<
StyleName:Code ><
StyleName:Code >Class Program<
StyleName:Code > Public Shared Sub Main(ByVal args() As String)<
StyleName:Code > Console.WriteLine("Hello World")<
StyleName:Code > End Sub<
StyleName:Code >End Class<
StyleName:Normal ><
StyleName:Normal >This example produces the following output:<
StyleName:Normal ><
StyleName:Code >Hello World<
L'articolo successivo di questa esercitazione illustra come usare un metodo di estensione, anziché Aggregate per concatenare più stringhe in un'unica stringa: