|
6 | 6 | using System.Collections.Generic; |
7 | 7 | using System.IO; |
8 | 8 | using System.Text; |
| 9 | +#if FEATURE_ASYNC_SAX_XML |
| 10 | +using DocumentFormat.OpenXml.Framework; |
| 11 | +using System.Threading.Tasks; |
| 12 | +#endif |
9 | 13 | using System.Xml; |
10 | 14 |
|
11 | 15 | namespace DocumentFormat.OpenXml |
@@ -56,6 +60,36 @@ public OpenXmlPartWriter(OpenXmlPart openXmlPart, Encoding encoding) |
56 | 60 | _xmlWriter = XmlWriter.Create(partStream, settings); |
57 | 61 | } |
58 | 62 |
|
| 63 | + /// <summary> |
| 64 | + /// Initializes a new instance of the OpenXmlPartWriter. |
| 65 | + /// </summary> |
| 66 | + /// <param name="openXmlPart">The OpenXmlPart to be written to.</param> |
| 67 | + /// <param name="settings">The settings for the OpenXmlPartWriter.</param> |
| 68 | + public OpenXmlPartWriter(OpenXmlPart openXmlPart, OpenXmlPartWriterSettings settings) |
| 69 | + { |
| 70 | + if (openXmlPart is null) |
| 71 | + { |
| 72 | + throw new ArgumentNullException(nameof(openXmlPart)); |
| 73 | + } |
| 74 | + |
| 75 | + if (settings is null) |
| 76 | + { |
| 77 | + throw new ArgumentNullException(nameof(settings)); |
| 78 | + } |
| 79 | + |
| 80 | + var partStream = openXmlPart.GetStream(FileMode.Create); |
| 81 | + XmlWriterSettings xmlWriterSettings = new() |
| 82 | + { |
| 83 | + CloseOutput = true, |
| 84 | + Encoding = settings.Encoding, |
| 85 | +#if FEATURE_ASYNC_SAX_XML |
| 86 | + Async = settings.Async, |
| 87 | +#endif |
| 88 | + }; |
| 89 | + |
| 90 | + _xmlWriter = XmlWriter.Create(partStream, xmlWriterSettings); |
| 91 | + } |
| 92 | + |
59 | 93 | /// <summary> |
60 | 94 | /// Initializes a new instance of the OpenXmlPartWriter. |
61 | 95 | /// </summary> |
@@ -91,6 +125,35 @@ public OpenXmlPartWriter(Stream partStream, Encoding encoding) |
91 | 125 | _xmlWriter = XmlWriter.Create(partStream, settings); |
92 | 126 | } |
93 | 127 |
|
| 128 | + /// <summary> |
| 129 | + /// Initializes a new instance of the OpenXmlPartWriter. |
| 130 | + /// </summary> |
| 131 | + /// <param name="partStream">The given part stream.</param> |
| 132 | + /// <param name="settings">The settings for the OpenXmlPartWriter.</param> |
| 133 | + public OpenXmlPartWriter(Stream partStream, OpenXmlPartWriterSettings settings) |
| 134 | + { |
| 135 | + if (partStream is null) |
| 136 | + { |
| 137 | + throw new ArgumentNullException(nameof(partStream)); |
| 138 | + } |
| 139 | + |
| 140 | + if (settings is null) |
| 141 | + { |
| 142 | + throw new ArgumentNullException(nameof(settings)); |
| 143 | + } |
| 144 | + |
| 145 | + XmlWriterSettings xmlWriterSettings = new() |
| 146 | + { |
| 147 | + CloseOutput = settings.CloseOutput, |
| 148 | + Encoding = settings.Encoding, |
| 149 | +#if FEATURE_ASYNC_SAX_XML |
| 150 | + Async = settings.Async, |
| 151 | +#endif |
| 152 | + }; |
| 153 | + |
| 154 | + _xmlWriter = XmlWriter.Create(partStream, xmlWriterSettings); |
| 155 | + } |
| 156 | + |
94 | 157 | #region public OpenXmlWriter methods |
95 | 158 |
|
96 | 159 | /// <summary> |
@@ -365,5 +428,184 @@ public override void Close() |
365 | 428 | } |
366 | 429 |
|
367 | 430 | #endregion |
| 431 | + |
| 432 | + // Async Methods |
| 433 | +#if FEATURE_ASYNC_SAX_XML |
| 434 | + /// <summary> |
| 435 | + /// Asynchronously writes the XML declaration with the version "1.0". |
| 436 | + /// </summary> |
| 437 | + public override Task WriteStartDocumentAsync() |
| 438 | + { |
| 439 | + ThrowIfObjectDisposed(); |
| 440 | + |
| 441 | + return _xmlWriter.WriteStartDocumentAsync(); |
| 442 | + } |
| 443 | + |
| 444 | + /// <summary> |
| 445 | + /// Asynchronously writes the XML declaration with the version "1.0" and the standalone attribute. |
| 446 | + /// </summary> |
| 447 | + /// <param name="standalone">If true, it writes "standalone=yes"; if false, it writes "standalone=no". </param> |
| 448 | + public override Task WriteStartDocumentAsync(bool standalone) |
| 449 | + { |
| 450 | + ThrowIfObjectDisposed(); |
| 451 | + |
| 452 | + return _xmlWriter.WriteStartDocumentAsync(standalone); |
| 453 | + } |
| 454 | + |
| 455 | + /// <summary> |
| 456 | + /// Asynchronously writes out a start tag of the element and all the attributes of the element. |
| 457 | + /// </summary> |
| 458 | + /// <param name="elementObject">The OpenXmlElement object to be written.</param> |
| 459 | + public async override Task WriteStartElementAsync(OpenXmlElement elementObject) |
| 460 | + { |
| 461 | + if (elementObject is null) |
| 462 | + { |
| 463 | + throw new ArgumentNullException(nameof(elementObject)); |
| 464 | + } |
| 465 | + |
| 466 | + if (elementObject is OpenXmlMiscNode) |
| 467 | + { |
| 468 | + throw new ArgumentOutOfRangeException(nameof(elementObject)); |
| 469 | + } |
| 470 | + |
| 471 | + ThrowIfObjectDisposed(); |
| 472 | + |
| 473 | + await _xmlWriter.WriteStartElementAsync(elementObject.Prefix, elementObject.LocalName, elementObject.NamespaceUri).ConfigureAwait(true); |
| 474 | + |
| 475 | + if (elementObject.HasAttributes) |
| 476 | + { |
| 477 | + // write attributes |
| 478 | + foreach (var attribute in elementObject.GetAttributes()) |
| 479 | + { |
| 480 | + await _xmlWriter.WriteAttributeStringAsync(attribute.Prefix, attribute.LocalName, attribute.NamespaceUri, attribute.Value).ConfigureAwait(true); |
| 481 | + } |
| 482 | + } |
| 483 | + |
| 484 | + if (elementObject is OpenXmlLeafTextElement) |
| 485 | + { |
| 486 | + _isLeafTextElementStart = true; |
| 487 | + } |
| 488 | + else |
| 489 | + { |
| 490 | + _isLeafTextElementStart = false; |
| 491 | + } |
| 492 | + } |
| 493 | + |
| 494 | + /// <summary> |
| 495 | + /// Asynchronously writes out a start tag of the element. And write the attributes in attributes. The attributes of the element will be omitted. |
| 496 | + /// </summary> |
| 497 | + /// <param name="elementObject">The OpenXmlElement object to be written.</param> |
| 498 | + /// <param name="attributes">The attributes to be written.</param> |
| 499 | + public override Task WriteStartElementAsync(OpenXmlElement elementObject, IEnumerable<OpenXmlAttribute> attributes) |
| 500 | + { |
| 501 | + if (elementObject is null) |
| 502 | + { |
| 503 | + throw new ArgumentNullException(nameof(elementObject)); |
| 504 | + } |
| 505 | + |
| 506 | + return WriteStartElementAsync(elementObject, attributes, elementObject.NamespaceDeclarations); |
| 507 | + } |
| 508 | + |
| 509 | + /// <summary> |
| 510 | + /// Asynchronously writes out a start tag of the element. And write the attributes in attributes. The attributes of the element will be omitted. |
| 511 | + /// </summary> |
| 512 | + /// <param name="elementObject">The OpenXmlElement object to be written.</param> |
| 513 | + /// <param name="attributes">The attributes to be written.</param> |
| 514 | + /// <param name="namespaceDeclarations">The namespace declarations to be written, can be null if no namespace declarations.</param> |
| 515 | + public async override Task WriteStartElementAsync(OpenXmlElement elementObject, IEnumerable<OpenXmlAttribute> attributes, IEnumerable<KeyValuePair<string, string>> namespaceDeclarations) |
| 516 | + { |
| 517 | + if (elementObject is null) |
| 518 | + { |
| 519 | + throw new ArgumentNullException(nameof(elementObject)); |
| 520 | + } |
| 521 | + |
| 522 | + if (elementObject is OpenXmlMiscNode) |
| 523 | + { |
| 524 | + throw new ArgumentOutOfRangeException(nameof(elementObject)); |
| 525 | + } |
| 526 | + |
| 527 | + ThrowIfObjectDisposed(); |
| 528 | + |
| 529 | + await _xmlWriter.WriteStartElementAsync(elementObject.Prefix, elementObject.LocalName, elementObject.NamespaceUri).ConfigureAwait(true); |
| 530 | + |
| 531 | + if (namespaceDeclarations is not null) |
| 532 | + { |
| 533 | + foreach (var item in namespaceDeclarations) |
| 534 | + { |
| 535 | + await _xmlWriter.WriteAttributeStringAsync(OpenXmlElementContext.XmlnsPrefix, item.Key, OpenXmlElementContext.XmlnsUri, item.Value).ConfigureAwait(true); |
| 536 | + } |
| 537 | + } |
| 538 | + |
| 539 | + if (attributes is not null) |
| 540 | + { |
| 541 | + // write attributes |
| 542 | + foreach (var attribute in attributes) |
| 543 | + { |
| 544 | + await _xmlWriter.WriteAttributeStringAsync(attribute.Prefix, attribute.LocalName, attribute.NamespaceUri, attribute.Value).ConfigureAwait(true); |
| 545 | + } |
| 546 | + } |
| 547 | + |
| 548 | + if (elementObject is OpenXmlLeafTextElement) |
| 549 | + { |
| 550 | + _isLeafTextElementStart = true; |
| 551 | + } |
| 552 | + else |
| 553 | + { |
| 554 | + _isLeafTextElementStart = false; |
| 555 | + } |
| 556 | + } |
| 557 | + |
| 558 | + /// <summary> |
| 559 | + /// Asynchronously closes one element. |
| 560 | + /// </summary> |
| 561 | + public override Task WriteEndElementAsync() |
| 562 | + { |
| 563 | + ThrowIfObjectDisposed(); |
| 564 | + |
| 565 | + _isLeafTextElementStart = false; |
| 566 | + |
| 567 | + return _xmlWriter.WriteEndElementAsync(); |
| 568 | + } |
| 569 | + |
| 570 | + /// <summary> |
| 571 | + /// Asynchronously writes the OpenXmlElement to the writer. |
| 572 | + /// </summary> |
| 573 | + /// <param name="elementObject">The OpenXmlElement object to be written.</param> |
| 574 | + public async override Task WriteElementAsync(OpenXmlElement elementObject) |
| 575 | + { |
| 576 | + if (elementObject is null) |
| 577 | + { |
| 578 | + throw new ArgumentNullException(nameof(elementObject)); |
| 579 | + } |
| 580 | + |
| 581 | + ThrowIfObjectDisposed(); |
| 582 | + |
| 583 | + await WriteStartElementAsync(elementObject).ConfigureAwait(true); |
| 584 | + |
| 585 | + await WriteEndElementAsync().ConfigureAwait(true); |
| 586 | + |
| 587 | + _isLeafTextElementStart = false; |
| 588 | + } |
| 589 | + |
| 590 | + /// <summary> |
| 591 | + /// Asynchronously writes the given text content. |
| 592 | + /// </summary> |
| 593 | + /// <param name="text">The text to be written. </param> |
| 594 | + public override Task WriteStringAsync(string text) |
| 595 | + { |
| 596 | + ThrowIfObjectDisposed(); |
| 597 | + |
| 598 | + if (_isLeafTextElementStart) |
| 599 | + { |
| 600 | + return _xmlWriter.WriteStringAsync(text); |
| 601 | + } |
| 602 | + else |
| 603 | + { |
| 604 | + throw new InvalidOperationException(ExceptionMessages.InvalidWriteStringCall); |
| 605 | + } |
| 606 | + |
| 607 | + // can continue WriteStringAsync(), so don't set _isLeafTextElementStart to false. |
| 608 | + } |
| 609 | +#endif |
368 | 610 | } |
369 | 611 | } |
0 commit comments