Skip to content

Commit 42b6770

Browse files
committed
Always write the value XML attributes in properties, even when the value is null
Also make the null text configurable through a new `UseNullText()` method on the options builder. The default null text value is `(null)` in order to match the log4net behavior. Fixes #287
1 parent 83d825c commit 42b6770

14 files changed

+71
-12
lines changed

src/Log4NetTextFormatter.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,11 +406,14 @@ private void WritePropertyElement(XmlWriter writer, string name, LogEventPropert
406406
{
407407
WriteStartElement(writer, "data");
408408
writer.WriteAttributeString("name", name);
409-
var isNullValue = value is ScalarValue { Value: null };
410-
if (!isNullValue)
409+
if (value is not ScalarValue { Value: null })
411410
{
412411
writer.WriteAttributeString("value", RenderValue(value));
413412
}
413+
else if (_options.NullText != null)
414+
{
415+
writer.WriteAttributeString("value", _options.NullText);
416+
}
414417
writer.WriteEndElement();
415418
}
416419

src/Log4NetTextFormatterOptions.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ namespace Serilog.Formatting.Log4Net;
88
/// </summary>
99
internal sealed class Log4NetTextFormatterOptions
1010
{
11-
internal Log4NetTextFormatterOptions(IFormatProvider? formatProvider, CDataMode cDataMode, XmlQualifiedName? xmlNamespace, XmlWriterSettings xmlWriterSettings, PropertyFilter filterProperty, MessageFormatter formatMessage, ExceptionFormatter formatException)
11+
internal Log4NetTextFormatterOptions(IFormatProvider? formatProvider, CDataMode cDataMode, string? nullText, XmlQualifiedName? xmlNamespace, XmlWriterSettings xmlWriterSettings, PropertyFilter filterProperty, MessageFormatter formatMessage, ExceptionFormatter formatException)
1212
{
1313
FormatProvider = formatProvider;
1414
CDataMode = cDataMode;
15+
NullText = nullText;
1516
XmlNamespace = xmlNamespace;
1617
XmlWriterSettings = xmlWriterSettings;
1718
FilterProperty = filterProperty;
@@ -25,6 +26,9 @@ internal Log4NetTextFormatterOptions(IFormatProvider? formatProvider, CDataMode
2526
/// <summary>See <see cref="Log4NetTextFormatterOptionsBuilder.UseCDataMode"/></summary>
2627
internal CDataMode CDataMode { get; }
2728

29+
/// <summary>See <see cref="Log4NetTextFormatterOptionsBuilder.UseNullText"/></summary>
30+
internal string? NullText { get; }
31+
2832
/// <summary>See <see cref="Log4NetTextFormatterOptionsBuilder.UseNoXmlNamespace"/></summary>
2933
internal XmlQualifiedName? XmlNamespace { get; }
3034

src/Log4NetTextFormatterOptionsBuilder.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ internal Log4NetTextFormatterOptionsBuilder()
3131
/// <summary>See <see cref="UseFormatProvider"/></summary>
3232
private IFormatProvider? _formatProvider;
3333

34-
/// <summary> See <see cref="UseCDataMode"/></summary>
34+
/// <summary>See <see cref="UseCDataMode"/></summary>
3535
private CDataMode _cDataMode = CDataMode.Always;
3636

37+
/// <summary>See <see cref="UseNullText"/></summary>
38+
private string? _nullText = "(null)";
39+
3740
/// <summary>See <see cref="UseNoXmlNamespace"/></summary>
3841
private XmlQualifiedName? _xmlNamespace = Log4NetXmlNamespace;
3942

@@ -78,6 +81,23 @@ public Log4NetTextFormatterOptionsBuilder UseCDataMode(CDataMode cDataMode)
7881
return this;
7982
}
8083

84+
/// <summary>
85+
/// Sets how <see langword="null"/> properties are rendered as textual representation inside XML attributes.
86+
/// <para/>
87+
/// The default value is <c>(null)</c>.
88+
/// </summary>
89+
/// <param name="nullText">The text to use to represent <see langword="null"/> properties.</param>
90+
/// <returns>The builder in order to fluently chain all options.</returns>
91+
/// <remarks>
92+
/// Pass <see langword="null"/> for <paramref name="nullText"/> to omit the <c>value</c> attribute, i.e. <code>&lt;log4net:data name="MiddleName" /&gt;</code>
93+
/// Note that this is not strictly compatible with log4net/log4j XML formats and should be used to keep compatibility with Serilog.Formatting.Log4Net 1.3.1 and earlier if needed.
94+
/// </remarks>
95+
public Log4NetTextFormatterOptionsBuilder UseNullText(string? nullText)
96+
{
97+
_nullText = nullText;
98+
return this;
99+
}
100+
81101
/// <summary>
82102
/// Do not use any XML namespace for log4net events.
83103
/// <para/>
@@ -197,7 +217,7 @@ public void UseLog4JCompatibility()
197217
}
198218

199219
internal Log4NetTextFormatterOptions Build()
200-
=> new(_formatProvider, _cDataMode, _xmlNamespace, CreateXmlWriterSettings(_lineEnding, _indentationSettings), _filterProperty, _formatMessage, _formatException);
220+
=> new(_formatProvider, _cDataMode, _nullText, _xmlNamespace, CreateXmlWriterSettings(_lineEnding, _indentationSettings), _filterProperty, _formatMessage, _formatException);
201221

202222
private static XmlWriterSettings CreateXmlWriterSettings(LineEnding lineEnding, IndentationSettings? indentationSettings)
203223
{

tests/Log4NetTextFormatterTest.DefaultMessageFormatter_eventId=1_eventIdName=EventName.verified.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<log4net:data name="Name" value="World" />
44
<log4net:data name="EventId.Id" value="1" />
55
<log4net:data name="EventId.Name" value="EventName" />
6-
<log4net:data name="EventId.More" />
6+
<log4net:data name="EventId.More" value="(null)" />
77
</log4net:properties>
88
<log4net:message><![CDATA[Hello World!]]></log4net:message>
99
</log4net:event>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
2+
<log4net:properties>
3+
<log4net:data name="n/a" value="&lt;null&gt;" />
4+
</log4net:properties>
5+
<log4net:message><![CDATA[Hello from Serilog]]></log4net:message>
6+
</log4net:event>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
2+
<log4net:properties>
3+
<log4net:data name="n/a" value="" />
4+
</log4net:properties>
5+
<log4net:message><![CDATA[Hello from Serilog]]></log4net:message>
6+
</log4net:event>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
2+
<log4net:properties>
3+
<log4net:data name="n/a" value="(null)" />
4+
</log4net:properties>
5+
<log4net:message><![CDATA[Hello from Serilog]]></log4net:message>
6+
</log4net:event>

tests/Log4NetTextFormatterTest.NullProperty.verified.xml renamed to tests/Log4NetTextFormatterTest.NullProperty_nullText=null.verified.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
1+
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
22
<log4net:properties>
33
<log4net:data name="n/a" />
44
</log4net:properties>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
2+
<log4net:properties>
3+
<log4net:data name="n/a" value="🌀" />
4+
</log4net:properties>
5+
<log4net:message><![CDATA[Hello from Serilog]]></log4net:message>
6+
</log4net:event>

tests/Log4NetTextFormatterTest.TwoPropertiesOneNull.verified.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<log4net:event timestamp="2003-01-04T15:09:26.535+01:00" level="INFO" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2/">
22
<log4net:properties>
3-
<log4net:data name="n/a" />
3+
<log4net:data name="n/a" value="(null)" />
44
<log4net:data name="one" value="1" />
55
</log4net:properties>
66
<log4net:message><![CDATA[Hello from Serilog]]></log4net:message>

0 commit comments

Comments
 (0)