-
Notifications
You must be signed in to change notification settings - Fork 586
Expand file tree
/
Copy pathOpenXmlReader.cs
More file actions
325 lines (283 loc) · 12.8 KB
/
OpenXmlReader.cs
File metadata and controls
325 lines (283 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using DocumentFormat.OpenXml.Packaging;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
#if TASKS_SUPPORTED
using System.Threading.Tasks;
#endif
using System.Xml;
namespace DocumentFormat.OpenXml
{
/// <summary>
/// Represents the Open XML reader class.
/// </summary>
public abstract class OpenXmlReader : IDisposable
{
private readonly bool _readMiscNodes;
private bool _disposed;
/// <summary>
/// Initializes a new instance of the OpenXmlReader class.
/// </summary>
protected OpenXmlReader()
{
}
/// <summary>
/// Initializes a new instance of the OpenXmlReader class using the supplied Boolean value.
/// </summary>
/// <param name="readMiscNodes">Specify false to indicate to the reader to skip all miscellaneous nodes. The default value is false.</param>
protected OpenXmlReader(bool readMiscNodes)
{
_readMiscNodes = readMiscNodes;
}
/// <summary>
/// Creates an OpenXmlReader from the specified OpenXmlPart.
/// </summary>
/// <param name="openXmlPart">The OpenXmlPart to read.</param>
/// <returns>The newly created OpenXmlReader.</returns>
public static OpenXmlReader Create(OpenXmlPart openXmlPart) => new OpenXmlPartReader(openXmlPart);
/// <summary>
/// Creates an OpenXmlReader from the specified OpenXmlPart and Boolean values.
/// </summary>
/// <param name="openXmlPart">The OpenXmlPart to read.</param>
/// <param name="readMiscNodes">Specify false to indicate to the reader to skip all miscellaneous nodes. The default value is false.</param>
/// <returns>The newly created OpenXmlReader.</returns>
public static OpenXmlReader Create(OpenXmlPart openXmlPart, bool readMiscNodes) => new OpenXmlPartReader(openXmlPart, readMiscNodes);
/// <summary>
/// Creates an OpenXmlReader from the specified OpenXmlPart and Boolean values.
/// </summary>
/// <param name="openXmlPart">The OpenXmlPart to read.</param>
/// <param name="readMiscNodes">Specify false to indicate to the reader to skip all miscellaneous nodes. The default value is false.</param>
/// <param name="ignoreWhitespace">Specify true to indicate to the reader to ignore insignificant white space. The default value is true.</param>
/// <returns>The newly created OpenXmlReader.</returns>
public static OpenXmlReader Create(OpenXmlPart openXmlPart, bool readMiscNodes, bool ignoreWhitespace) => new OpenXmlPartReader(openXmlPart, readMiscNodes, ignoreWhitespace);
/// <summary>
/// Creates an OpenXmlReader from the OpenXmlElement (travel the DOM tree).
/// </summary>
/// <param name="openXmlElement">The OpenXmlElement to read.</param>
/// <returns>The newly created OpenXmlReader.</returns>
public static OpenXmlReader Create(OpenXmlElement openXmlElement) => new OpenXmlDomReader(openXmlElement);
/// <summary>
/// Creates an OpenXmlReader from the OpenXmlElement (travel the DOM tree).
/// </summary>
/// <param name="openXmlElement">The OpenXmlElement to read.</param>
/// <param name="readMiscNodes">Specify false to indicate to the reader to skip all miscellaneous nodes. The default value is false.</param>
/// <returns>The newly created OpenXmlReader.</returns>
public static OpenXmlReader Create(OpenXmlElement openXmlElement, bool readMiscNodes) => new OpenXmlDomReader(openXmlElement, readMiscNodes);
/// <summary>
/// Gets a value indicating whether the OpenXmlReader will read or skip all miscellaneous nodes.
/// </summary>
public bool ReadMiscNodes
{
get
{
ThrowIfObjectDisposed();
return _readMiscNodes;
}
}
/// <summary>
/// Gets the encoding of the XML file.
/// </summary>
/// <remarks>
/// Returns null if the encoding is not specified in the XML file.
/// </remarks>
public virtual string? Encoding
{
get
{
ThrowIfObjectDisposed();
// default XML encoding is UTF8
return null;
}
}
/// <summary>
/// Gets the standalone property in the XML declaration of the XML stream. The default value is null.
/// </summary>
public virtual bool? StandaloneXml
{
get
{
ThrowIfObjectDisposed();
return null;
}
}
/// <summary>
/// Gets a value indicating whether the current node has any attributes.
/// </summary>
public virtual bool HasAttributes
{
get
{
ThrowIfObjectDisposed();
return Attributes.Count > 0;
}
}
/// <summary>
/// Gets the list of attributes of the current element.
/// </summary>
public abstract ReadOnlyCollection<OpenXmlAttribute> Attributes { get; }
/// <summary>
/// Gets the namespace declarations of the current element.
/// </summary>
public abstract IEnumerable<KeyValuePair<string, string>> NamespaceDeclarations { get; }
/// <summary>
/// Gets the type of the corresponding strongly typed class of the current element.
/// </summary>
public abstract Type ElementType { get; }
/// <summary>
/// Gets a value indicating whether the current node is a miscellaneous XML node (non element).
/// </summary>
/// <remarks><see cref="IsStartElement"/> and <see cref="IsEndElement"/> will be false when <see cref="IsMiscNode"/> is true.</remarks>
public abstract bool IsMiscNode { get; }
/// <summary>
/// Gets a value indicating whether the current node is an element start.
/// </summary>
public abstract bool IsStartElement { get; }
/// <summary>
/// Gets a value indicating whether the current node is an element end.
/// </summary>
public abstract bool IsEndElement { get; }
/// <summary>
/// Gets the depth of the current node in the XML document. The depth of the root element is 0.
/// </summary>
public abstract int Depth { get; }
/// <summary>
/// Gets a value indicating whether the reader is positioned at the end of the stream.
/// </summary>
public abstract bool EOF { get; }
/// <summary>
/// Gets the local name of the current node.
/// </summary>
public abstract string LocalName { get; }
/// <summary>
/// Gets the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned.
/// </summary>
public abstract string NamespaceUri { get; }
/// <summary>
/// Gets the namespace prefix associated with the current node.
/// </summary>
public abstract string Prefix { get; }
/// <summary>
/// Gets the type of the current node in the XML document being read.
/// </summary>
/// <remarks>
/// The <see cref="XmlNodeType"/> indicates the type of the current node, such as
/// <c>Element</c>, <c>Attribute</c>, <c>Text</c>, <c>CDATA</c>, <c>Comment</c>, or others.
/// This property provides information about the structure of the XML document
/// and is useful for determining how to process the current node.
/// </remarks>
public virtual XmlNodeType NodeType { get; }
/// <summary>
/// Gets an instance of <see cref="IXmlLineInfo"/> if available for the current reader.
/// </summary>
/// <returns>An object for obtaining information about line info</returns>
public virtual IXmlLineInfo GetLineInfo() => XmlLineInfo.Empty;
/// <summary>
/// Moves to read the next element.
/// </summary>
/// <returns>Returns true if the next element was read successfully; false if there are no more elements to read. </returns>
public abstract bool Read();
/// <summary>
/// Moves to read the first child element.
/// </summary>
/// <returns>Returns true if the first child element was read successfully; false if there are no child elements to read. </returns>
/// <remarks>This method can only be called on element start. At the current node, the reader will move to the end tag if there is no child element.</remarks>
public abstract bool ReadFirstChild();
/// <summary>
/// Moves to read the next sibling element.
/// </summary>
/// <returns>Returns true if the next sibling element was read successfully; false if there are no more sibling elements to read. </returns>
/// <remarks>At the current node, the reader will move to the end tag of the parent node if there are no more sibling elements.</remarks>
public abstract bool ReadNextSibling();
/// <summary>
/// Skips the child elements of the current node.
/// </summary>
public abstract void Skip();
/// <summary>
/// Loads the element at current cursor.
/// </summary>
/// <returns>The OpenXmlElement that was loaded.</returns>
/// <exception cref="InvalidOperationException">Thrown when the current is the end element.</exception>
/// <remarks>The new current element is the end of the element after LoadCurrentElement().</remarks>
public abstract OpenXmlElement? LoadCurrentElement();
/// <summary>
/// Gets the text of the element if the element is an OpenXmlLeafTextElement. Returns String.Empty for other elements.
/// </summary>
/// <returns>
/// The text of the element if the element is an OpenXmlLeafTextElement. Returns String.Empty for other elements.
/// </returns>
public abstract string GetText();
/// <summary>
/// Closes the reader.
/// </summary>
public abstract void Close();
#if TASKS_SUPPORTED
#region Async methods
/// <summary>
/// Asynchronously reads the next element in the Open XML document.
/// </summary>
/// <returns>
/// A task that represents the asynchronous read operation. The task result is <c>true</c> if the next element
/// was read successfully; <c>false</c> if there are no more elements to read.
/// </returns>
/// <remarks>
/// This method is only available when the build target supports asynchronous SAX XML processing.
/// </remarks>
public virtual Task<bool> ReadAsync()
{
return Task.FromResult(Read());
}
/// <summary>
/// Asynchronously moves the reader to the first child element of the current node.
/// </summary>
/// <returns>
/// A task that represents the asynchronous operation. The task result is <c>true</c> if the first child element
/// was read successfully; <c>false</c> if there are no child elements to read.
/// </returns>
/// <remarks>
/// This method can only be called when the reader is positioned on an element start. If no child elements exist,
/// the reader will move to the end tag of the current element.
/// </remarks>
public virtual Task<bool> ReadFirstChildAsync()
{
return Task.FromResult(ReadFirstChild());
}
#endregion
#endif
/// <summary>
/// Thrown if the object is disposed.
/// </summary>
protected virtual void ThrowIfObjectDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
/// <summary>
/// Closes the reader, and releases all resources.
/// </summary>
/// <param name="disposing">Specify true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
Close();
}
_disposed = true;
}
}
/// <summary>
/// Closes the reader, and releases all resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}