Blog Map
[Table of Contents] [Next Topic] [Blog Map] This blog is inactive. New blog: EricWhite.com/blog
It would be useful to refactor this example to clean up the code that determines the style of the paragraph. We can make a function that has no side effects that returns the style name:
Public Function GetParagraphStyle(para As XElement) As String Dim w As XNamespace = _ "http://schemas.openxmlformats.org/wordprocessingml/2006/main" Return CStr(para.Elements(w + "pPr") _ .Elements(w + "pStyle") _ .Attributes(w + "val") _ .FirstOrDefault())End Function
Now, the query is as follows:
Dim paragraphs = _ mainPartDoc.Root _ .Element(w + "body") _ .Descendants(w + "p") _ .Select(Function(p) _ New With { _ .ParagraphNode = p, _ .Style = GetParagraphStyle(p) _ } _ )
We can rewrite the version that uses a query expression:
Dim paragraphs = _ From p In mainPartDoc.Root _ .Element(w + "body") _ .Descendants(w + "p") _ Let style = GetParagraphStyle(p) _ Select New With { _ .ParagraphNode = p, _ .Style = style _ }
This is easier to read.
Because we wrote the GetParagraphStyle function without side effects, we were free to use it without worrying about how it would impact the execution of our query.
The entire example follows.
Imports System.IOImports System.XmlImports DocumentFormat.OpenXml.Packaging Module Module1 <System.Runtime.CompilerServices.Extension()> _ Public Function GetPath(ByVal el As XElement) As String Return el _ .AncestorsAndSelf _ .InDocumentOrder _ .Aggregate("", Function(seed, i) seed & "/" & i.Name.LocalName) End Function Public Function LoadXDocument(ByVal part As OpenXmlPart) _ As XDocument Using streamReader As StreamReader = New StreamReader(part.GetStream()) Using xmlReader As XmlReader = xmlReader.Create(streamReader) Return XDocument.Load(xmlReader) End Using End Using End Function Public Function GetParagraphStyle(ByVal para As XElement) As String Dim w As XNamespace = _ "http://schemas.openxmlformats.org/wordprocessingml/2006/main" Return CStr(para.Elements(w + "pPr") _ .Elements(w + "pStyle") _ .Attributes(w + "val") _ .FirstOrDefault()) End Function Sub Main() Dim w As XNamespace = _ "http://schemas.openxmlformats.org/wordprocessingml/2006/main" Dim filename As String = "SampleDoc.docx" Using wordDoc As WordprocessingDocument = _ WordprocessingDocument.Open(filename, True) Dim mainPart As MainDocumentPart = _ wordDoc.MainDocumentPart Dim mainPartDoc As XDocument = LoadXDocument(mainPart) Dim paragraphs = _ mainPartDoc.Root _ .Element(w + "body") _ .Descendants(w + "p") _ .Select(Function(p) _ New With { _ .ParagraphNode = p, _ .Style = GetParagraphStyle(p) _ } _ ) For Each p In paragraphs Dim s As String If Not p.Style Is Nothing Then s = p.Style.PadRight(12) Else s = "".PadRight(12) End If Console.WriteLine("{0} {1}", s, _ p.ParagraphNode.GetPath()) Next End Using End SubEnd Module
[Table of Contents] [Next Topic] [Blog Map]