@@ -59,19 +59,27 @@ public void Serialize(
5959
6060 writeComments ( rootComments ? . CommentsBefore , writer ) ;
6161
62+ var deferredWriter = new DeferredXmlWriter ( writer ) ;
63+
6264 // Wrap the instance with a named element if either a root name is given,
6365 // or we are serializing a datatype (=a subtree).
6466 if ( rootName is not null )
65- writer . WriteStartElement ( rootName , XmlNs . FHIR ) ;
66- else if ( instance is not Resource )
67- writer . WriteStartElement ( instance . TypeName , XmlNs . FHIR ) ;
68-
69- serializeInternal ( instance , writer , filter ) ;
70-
71- if ( rootName is not null ) writer . WriteEndElement ( ) ;
67+ {
68+ using var root = deferredWriter . BeginElement ( rootName , XmlNs . FHIR , required : true ) ;
69+ serializeInternal ( instance , deferredWriter , filter ) ;
70+ }
71+ else if ( instance is Resource )
72+ {
73+ serializeInternal ( instance , deferredWriter , filter , required : true ) ;
74+ }
75+ else
76+ {
77+ using var root = deferredWriter . BeginElement ( instance . TypeName , XmlNs . FHIR , required : true ) ;
78+ serializeInternal ( instance , deferredWriter , filter ) ;
79+ }
7280
73- // Only write these once the root element is actually closed - for a datatype without a root name
74- // the wrapping element above is left open for WriteEndDocument() to close .
81+ // Document-end comments belong after the root element and are only defined for resources
82+ // and explicitly named subtree documents .
7583 if ( rootName is not null || instance is Resource )
7684 writeComments ( rootComments ? . DocumentEndComments , writer ) ;
7785
@@ -80,27 +88,36 @@ public void Serialize(
8088
8189 private void serializeInternal (
8290 Base element ,
83- XmlWriter writer ,
84- SerializationFilter ? filter )
91+ DeferredXmlWriter writer ,
92+ SerializationFilter ? filter ,
93+ bool required = false )
8594 {
86- if ( element is Resource r )
87- writer . WriteStartElement ( r . TypeName , XmlNs . FHIR ) ;
88-
8995 // Only throw if we don't have a mapping where we are expected to: when this is a subclass of Base.
9096 if ( Inspector . FindOrImportClassMapping ( element ) is not { } mapping )
9197 throw new InvalidOperationException ( $ "Encountered type { element . GetType ( ) } , which is a support POCO for FHIR, but does not " +
9298 $ "have sufficient metadata to be used by the serializer.") ;
9399
100+ if ( element is Resource r )
101+ {
102+ using var resource = writer . BeginElement ( r . TypeName , XmlNs . FHIR , required ) ;
103+ serializeObject ( element , writer , filter , mapping ) ;
104+ }
105+ else
106+ {
107+ serializeObject ( element , writer , filter , mapping ) ;
108+ }
109+ }
110+
111+ private void serializeObject ( Base element , DeferredXmlWriter writer , SerializationFilter ? filter , ClassMapping mapping )
112+ {
94113 filter ? . EnterObject ( element , mapping ) ;
95114
96115 serializeElement ( element , writer , filter , mapping ) ;
97116
98117 filter ? . LeaveObject ( element , mapping ) ;
99-
100- if ( element is Resource ) writer . WriteEndElement ( ) ;
101118 }
102119
103- private void serializeElement ( Base element , XmlWriter writer , SerializationFilter ? filter , ClassMapping ? mapping )
120+ private void serializeElement ( Base element , DeferredXmlWriter writer , SerializationFilter ? filter , ClassMapping mapping )
104121 {
105122 static int attributeSorter ( PropertyMapping ? mapping , Base ? value )
106123 {
@@ -153,7 +170,7 @@ static int attributeSorter(PropertyMapping? mapping, Base? value)
153170
154171 // Comments that were the last content of this element in the source data. Written after the children,
155172 // so they end up just before the closing tag written by our caller.
156- writeComments ( element . Annotation < SourceComments > ( ) ? . ClosingComments , writer ) ;
173+ writer . WriteClosingComments ( element . Annotation < SourceComments > ( ) ? . ClosingComments ) ;
157174 }
158175
159176 /// <summary>
@@ -183,29 +200,28 @@ private static string addSuffixToElementName(string elementName, object? element
183200 }
184201
185202
186- private void serializeMemberValue ( string elementName , object ? value , XmlWriter writer , SerializationFilter ? filter )
203+ private void serializeMemberValue ( string elementName , object ? value , DeferredXmlWriter writer , SerializationFilter ? filter )
187204 {
188205 try
189206 {
190-
191- switch ( value )
192- {
193- case null :
194- break ; // In error situations there may be a null in a list, just don't serialize it.
195- case XHtml xhtml :
196- writeComments ( xhtml . Annotation < SourceComments > ( ) ? . CommentsBefore , writer ) ;
197- writer . WriteRaw ( xhtml . Value ?? "" ) ;
198- break ;
199- case Base complex :
200- writeComments ( complex . Annotation < SourceComments > ( ) ? . CommentsBefore , writer ) ;
201- writer . WriteStartElement ( elementName , XmlNs . FHIR ) ;
202- serializeInternal ( complex , writer , filter ) ;
203- writer . WriteEndElement ( ) ;
204- break ;
205- default :
206- SerializePrimitiveValue ( elementName , value , writer ) ;
207- break ;
208- }
207+ switch ( value )
208+ {
209+ case null :
210+ break ; // In error situations there may be a null in a list, just don't serialize it.
211+ case XHtml xhtml :
212+ writer . WriteRaw ( xhtml . Value ?? "" , xhtml . Annotation < SourceComments > ( ) ? . CommentsBefore ) ;
213+ break ;
214+ case Base complex :
215+ using ( writer . BeginElement ( elementName , XmlNs . FHIR ,
216+ commentsBefore : complex . Annotation < SourceComments > ( ) ? . CommentsBefore ) )
217+ {
218+ serializeInternal ( complex , writer , filter ) ;
219+ }
220+ break ;
221+ default :
222+ SerializePrimitiveValue ( elementName , value , writer . PrepareAttribute ( ) ) ;
223+ break ;
224+ }
209225 }
210226 catch ( Exception e )
211227 {
@@ -242,4 +258,4 @@ protected virtual void SerializePrimitiveValue(string elementName, object value,
242258}
243259
244260[ Obsolete ( "This class has been replaced by the equivalent BaseFhirXmlSerializer class." ) ]
245- public class BaseFhirXmlPocoSerializer ( ModelInspector inspector ) : BaseFhirXmlSerializer ( inspector ) ;
261+ public class BaseFhirXmlPocoSerializer ( ModelInspector inspector ) : BaseFhirXmlSerializer ( inspector ) ;
0 commit comments