@@ -124,10 +124,12 @@ public class XmlLayout : Layout
124
124
/// <remarks>
125
125
/// Support string-format where {0} means property-key-name
126
126
///
127
- /// Skips closing element tag when having configured <see cref="PropertiesFormatValueAttribute "/>
127
+ /// Skips closing element tag when having configured <see cref="PropertiesNodeValueAttribute "/>
128
128
/// </remarks>
129
129
/// <docgen category='LogEvent Properties XML Options' order='10' />
130
- public string PropertiesFormatElementName { get ; set ; } = "property" ;
130
+ public string PropertiesNodeName { get { return _propertiesNodeName ; } set { _propertiesNodeName = value ; _propertiesNodeNameFormat = value ? . IndexOf ( '{' ) >= 0 ; } }
131
+ private string _propertiesNodeName = "property" ;
132
+ private bool _propertiesNodeNameFormat ;
131
133
132
134
/// <summary>
133
135
/// XML attribute format to use when rendering property-key
@@ -138,7 +140,7 @@ public class XmlLayout : Layout
138
140
/// Replaces newlines with underscore (_)
139
141
/// </remarks>
140
142
/// <docgen category='LogEvent Properties XML Options' order='10' />
141
- public string PropertiesFormatKeyAttribute { get ; set ; } = "key=\" {0}\" " ;
143
+ public string PropertiesNodeKeyAttribute { get ; set ; } = "key=\" {0}\" " ;
142
144
143
145
/// <summary>
144
146
/// XML attribute format to use when rendering property-value
@@ -153,7 +155,7 @@ public class XmlLayout : Layout
153
155
/// Skips closing element tag when using attribute for value
154
156
/// </remarks>
155
157
/// <docgen category='LogEvent Properties XML Options' order='10' />
156
- public string PropertiesFormatValueAttribute { get ; set ; }
158
+ public string PropertiesNodeValueAttribute { get ; set ; }
157
159
158
160
/// <summary>
159
161
/// Initializes a new instance of the <see cref="XmlLayout"/> class.
@@ -219,8 +221,9 @@ protected override void RenderFormattedMessage(LogEventInfo logEvent, StringBuil
219
221
RenderXmlFormattedMessage ( logEvent , target ) ;
220
222
if ( target . Length == orgLength && IncludeEmptyValue && ! string . IsNullOrEmpty ( NodeName ) )
221
223
{
222
- BeginXmlDocument ( target , NodeName ) ;
223
- EndXmlDocument ( target , NodeName ) ;
224
+ target . Append ( '<' ) ;
225
+ target . Append ( NodeName ) ;
226
+ target . Append ( "/>" ) ;
224
227
}
225
228
}
226
229
@@ -252,10 +255,20 @@ private void RenderXmlFormattedMessage(LogEventInfo logEvent, StringBuilder sb)
252
255
}
253
256
if ( sb . Length != orgLength )
254
257
{
255
- sb . Append ( '>' ) ;
256
- if ( IndentXml )
257
- sb . AppendLine ( ) ;
258
+ bool hasNodes = NodeValue != null || Nodes . Count > 0 || IncludeMdc || IncludeMdlc || ( IncludeAllProperties && logEvent . HasProperties ) ;
259
+ if ( ! hasNodes )
260
+ {
261
+ sb . Append ( " />" ) ;
262
+ return ;
263
+ }
264
+ else
265
+ {
266
+ sb . Append ( '>' ) ;
267
+ if ( IndentXml )
268
+ sb . AppendLine ( ) ;
269
+ }
258
270
}
271
+
259
272
if ( NodeValue != null )
260
273
{
261
274
int beforeNodeLength = sb . Length ;
@@ -331,12 +344,12 @@ private void RenderXmlFormattedMessage(LogEventInfo logEvent, StringBuilder sb)
331
344
332
345
private void AppendXmlPropertyValue ( string propName , object propertyValue , StringBuilder sb , bool beginXmlDocument )
333
346
{
334
- if ( string . IsNullOrEmpty ( PropertiesFormatElementName ) )
347
+ if ( string . IsNullOrEmpty ( PropertiesNodeName ) )
335
348
return ; // Not supported
336
349
337
- string xmlKeyString = XmlHelper . XmlConvertToElementName ( propName ? . Trim ( ) , false ) ;
338
- if ( string . IsNullOrEmpty ( xmlKeyString ) )
339
- return ;
350
+ propName = propName ? . Trim ( ) ;
351
+ if ( string . IsNullOrEmpty ( propName ) )
352
+ return ; // Not supported
340
353
341
354
if ( beginXmlDocument && ! string . IsNullOrEmpty ( NodeName ) )
342
355
{
@@ -346,29 +359,42 @@ private void AppendXmlPropertyValue(string propName, object propertyValue, Strin
346
359
if ( IndentXml && ! string . IsNullOrEmpty ( NodeName ) )
347
360
sb . Append ( " " ) ;
348
361
349
- string xmlValueString = XmlHelper . XmlConvertToStringSafe ( propertyValue ) ;
350
-
351
362
sb . Append ( '<' ) ;
352
- sb . AppendFormat ( PropertiesFormatElementName , xmlKeyString ) ;
353
- if ( ! string . IsNullOrEmpty ( PropertiesFormatKeyAttribute ) )
363
+ string propNameElement = null ;
364
+ if ( _propertiesNodeNameFormat )
365
+ {
366
+ propNameElement = XmlHelper . XmlConvertToStringSafe ( propName ) ;
367
+ sb . AppendFormat ( PropertiesNodeName , propNameElement ) ;
368
+ }
369
+ else
354
370
{
371
+ sb . Append ( PropertiesNodeName ) ;
372
+ }
373
+
374
+ if ( ! string . IsNullOrEmpty ( PropertiesNodeKeyAttribute ) )
375
+ {
376
+ string propNameAttribute = ReferenceEquals ( propName , propNameElement ) ? propName : XmlHelper . EscapeXmlString ( propName , true ) ;
355
377
sb . Append ( ' ' ) ;
356
- sb . AppendFormat ( PropertiesFormatKeyAttribute , xmlKeyString ) ;
378
+ sb . AppendFormat ( PropertiesNodeKeyAttribute , propNameAttribute ) ;
357
379
}
358
380
359
- if ( ! string . IsNullOrEmpty ( PropertiesFormatValueAttribute ) )
381
+ string xmlValueString = XmlHelper . XmlConvertToStringSafe ( propertyValue ) ;
382
+ if ( ! string . IsNullOrEmpty ( PropertiesNodeValueAttribute ) )
360
383
{
361
384
xmlValueString = XmlHelper . EscapeXmlString ( xmlValueString , true ) ;
362
385
sb . Append ( ' ' ) ;
363
- sb . AppendFormat ( PropertiesFormatValueAttribute , xmlValueString ) ;
386
+ sb . AppendFormat ( PropertiesNodeValueAttribute , xmlValueString ) ;
364
387
sb . Append ( " />" ) ;
365
388
}
366
389
else
367
390
{
368
391
sb . Append ( '>' ) ;
369
392
XmlHelper . EscapeXmlString ( xmlValueString , false , sb ) ;
370
393
sb . Append ( "</" ) ;
371
- sb . AppendFormat ( PropertiesFormatElementName , xmlKeyString ) ;
394
+ if ( _propertiesNodeNameFormat )
395
+ sb . AppendFormat ( PropertiesNodeName , propNameElement ) ;
396
+ else
397
+ sb . AppendFormat ( PropertiesNodeName , PropertiesNodeName ) ;
372
398
sb . Append ( '>' ) ;
373
399
}
374
400
if ( IndentXml )
0 commit comments