Skip to content

Commit 7927486

Browse files
authored
Merge pull request #286 from ckadluba/refactor-SinkTraits
All unit tests for XmlPropertyFormatter and minor fixes
2 parents ade8a76 + 90fafa6 commit 7927486

File tree

2 files changed

+649
-129
lines changed

2 files changed

+649
-129
lines changed
Lines changed: 132 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
// Copyright 2020 Serilog Contributors
2-
//
3-
// Licensed under the Apache License, Version 2.0 (the "License");
4-
// you may not use this file except in compliance with the License.
5-
// You may obtain a copy of the License at
6-
//
7-
// http://www.apache.org/licenses/LICENSE-2.0
8-
//
9-
// Unless required by applicable law or agreed to in writing, software
10-
// distributed under the License is distributed on an "AS IS" BASIS,
11-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
// See the License for the specific language governing permissions and
13-
// limitations under the License.
14-
151
using System.Globalization;
162
using System.Linq;
173
using System.Text;
@@ -30,169 +16,186 @@ internal class XmlPropertyFormatter : IXmlPropertyFormatter
3016
public string Simplify(LogEventPropertyValue value, ColumnOptions.PropertiesColumnOptions options)
3117
{
3218
if (value is ScalarValue scalar)
19+
{
3320
return SimplifyScalar(scalar.Value);
21+
}
3422

3523
if (value is DictionaryValue dict)
3624
{
37-
var sb = new StringBuilder();
25+
return SimplifyDictionary(options, dict);
26+
}
3827

39-
var isEmpty = true;
28+
if (value is SequenceValue seq)
29+
{
30+
return SimplifySequence(options, seq);
31+
}
4032

41-
foreach (var element in dict.Elements)
42-
{
43-
var itemValue = Simplify(element.Value, options);
44-
if (options.OmitElementIfEmpty && string.IsNullOrEmpty(itemValue))
45-
{
46-
continue;
47-
}
33+
if (value is StructureValue str)
34+
{
35+
return SimplifyStructure(options, str);
36+
}
4837

49-
if (isEmpty)
50-
{
51-
isEmpty = false;
52-
if (!options.OmitDictionaryContainerElement)
53-
{
54-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>", options.DictionaryElementName);
55-
}
56-
}
38+
return null;
39+
}
5740

58-
var key = SimplifyScalar(element.Key.Value);
59-
if (options.UsePropertyKeyAsElementName)
60-
{
61-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", GetValidElementName(key), itemValue);
62-
}
63-
else
64-
{
65-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0} key='{1}'>{2}</{0}>", options.ItemElementName, key, itemValue);
66-
}
67-
}
41+
public string GetValidElementName(string name)
42+
{
43+
if (string.IsNullOrWhiteSpace(name))
44+
{
45+
return "x";
46+
}
6847

69-
if (!isEmpty && !options.OmitDictionaryContainerElement)
70-
{
71-
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", options.DictionaryElementName);
72-
}
48+
var validName = name.Trim();
7349

74-
return sb.ToString();
50+
if (!char.IsLetter(validName[0]) || validName.StartsWith("xml", true, CultureInfo.CurrentCulture))
51+
{
52+
validName = "x" + validName;
7553
}
7654

77-
if (value is SequenceValue seq)
78-
{
79-
var sb = new StringBuilder();
55+
validName = Regex.Replace(validName, @"\s", "_");
56+
57+
return validName;
58+
}
59+
60+
private static string SimplifyScalar(object value)
61+
{
62+
if (value == null) return null;
63+
64+
return new XText(_invalidXMLChars.Replace(value.ToString(), m => "\\u" + ((ushort)m.Value[0]).ToString("x4", CultureInfo.InvariantCulture))).ToString();
65+
}
66+
67+
private string SimplifyDictionary(ColumnOptions.PropertiesColumnOptions options, DictionaryValue dict)
68+
{
69+
var sb = new StringBuilder();
8070

81-
var isEmpty = true;
71+
var isEmpty = true;
8272

83-
foreach (var element in seq.Elements)
73+
foreach (var element in dict.Elements)
74+
{
75+
var itemValue = Simplify(element.Value, options);
76+
if (options.OmitElementIfEmpty && string.IsNullOrEmpty(itemValue))
8477
{
85-
var itemValue = Simplify(element, options);
86-
if (options.OmitElementIfEmpty && string.IsNullOrEmpty(itemValue))
87-
{
88-
continue;
89-
}
78+
continue;
79+
}
9080

91-
if (isEmpty)
81+
if (isEmpty)
82+
{
83+
isEmpty = false;
84+
if (!options.OmitDictionaryContainerElement)
9285
{
93-
isEmpty = false;
94-
if (!options.OmitSequenceContainerElement)
95-
{
96-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>", options.SequenceElementName);
97-
}
86+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>", options.DictionaryElementName);
9887
}
99-
100-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", options.ItemElementName, itemValue);
10188
}
10289

103-
if (!isEmpty && !options.OmitSequenceContainerElement)
90+
var key = SimplifyScalar(element.Key.Value);
91+
if (options.UsePropertyKeyAsElementName)
10492
{
105-
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", options.SequenceElementName);
93+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", GetValidElementName(key), itemValue);
94+
}
95+
else
96+
{
97+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0} key='{1}'>{2}</{0}>", options.ItemElementName, key, itemValue);
10698
}
107-
108-
return sb.ToString();
10999
}
110100

111-
if (value is StructureValue str)
101+
if (!isEmpty && !options.OmitDictionaryContainerElement)
112102
{
113-
var props = str.Properties.ToDictionary(p => p.Name, p => Simplify(p.Value, options));
114-
115-
var sb = new StringBuilder();
103+
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", options.DictionaryElementName);
104+
}
116105

117-
var isEmpty = true;
106+
return sb.ToString();
107+
}
118108

119-
foreach (var element in props)
120-
{
121-
var itemValue = element.Value;
122-
if (options.OmitElementIfEmpty && string.IsNullOrEmpty(itemValue))
123-
{
124-
continue;
125-
}
109+
private string SimplifySequence(ColumnOptions.PropertiesColumnOptions options, SequenceValue seq)
110+
{
111+
var sb = new StringBuilder();
126112

127-
if (isEmpty)
128-
{
129-
isEmpty = false;
130-
if (!options.OmitStructureContainerElement)
131-
{
132-
if (options.UsePropertyKeyAsElementName)
133-
{
134-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>", GetValidElementName(str.TypeTag));
135-
}
136-
else
137-
{
138-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0} type='{1}'>", options.StructureElementName, str.TypeTag);
139-
}
140-
}
141-
}
113+
var isEmpty = true;
142114

143-
if (options.UsePropertyKeyAsElementName)
144-
{
145-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", GetValidElementName(element.Key), itemValue);
146-
}
147-
else
148-
{
149-
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0} key='{1}'>{2}</{0}>", options.PropertyElementName,
150-
element.Key, itemValue);
151-
}
115+
foreach (var element in seq.Elements)
116+
{
117+
var itemValue = Simplify(element, options);
118+
if (options.OmitElementIfEmpty && string.IsNullOrEmpty(itemValue))
119+
{
120+
continue;
152121
}
153122

154-
if (!isEmpty && !options.OmitStructureContainerElement)
123+
if (isEmpty)
155124
{
156-
if (options.UsePropertyKeyAsElementName)
157-
{
158-
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", GetValidElementName(str.TypeTag));
159-
}
160-
else
125+
isEmpty = false;
126+
if (!options.OmitSequenceContainerElement)
161127
{
162-
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", options.StructureElementName);
128+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>", options.SequenceElementName);
163129
}
164130
}
165131

166-
return sb.ToString();
132+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", options.ItemElementName, itemValue);
167133
}
168134

169-
return null;
135+
if (!isEmpty && !options.OmitSequenceContainerElement)
136+
{
137+
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", options.SequenceElementName);
138+
}
139+
140+
return sb.ToString();
170141
}
171142

172-
public string GetValidElementName(string name)
143+
private string SimplifyStructure(ColumnOptions.PropertiesColumnOptions options, StructureValue str)
173144
{
174-
if (string.IsNullOrWhiteSpace(name))
175-
{
176-
return "x";
177-
}
145+
var props = str.Properties.ToDictionary(p => p.Name, p => Simplify(p.Value, options));
178146

179-
var validName = name.Trim();
147+
var sb = new StringBuilder();
180148

181-
if (!char.IsLetter(validName[0]) || validName.StartsWith("xml", true, CultureInfo.CurrentCulture))
149+
var isEmpty = true;
150+
151+
foreach (var element in props)
182152
{
183-
validName = "x" + name;
184-
}
153+
var itemValue = element.Value;
154+
if (options.OmitElementIfEmpty && string.IsNullOrEmpty(itemValue))
155+
{
156+
continue;
157+
}
185158

186-
validName = Regex.Replace(validName, @"\s", "_");
159+
if (isEmpty)
160+
{
161+
isEmpty = false;
162+
if (!options.OmitStructureContainerElement)
163+
{
164+
if (options.UsePropertyKeyAsElementName)
165+
{
166+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>", GetValidElementName(str.TypeTag));
167+
}
168+
else
169+
{
170+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0} type='{1}'>", options.StructureElementName, str.TypeTag);
171+
}
172+
}
173+
}
187174

188-
return validName;
189-
}
175+
if (options.UsePropertyKeyAsElementName)
176+
{
177+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", GetValidElementName(element.Key), itemValue);
178+
}
179+
else
180+
{
181+
sb.AppendFormat(CultureInfo.InvariantCulture, "<{0} key='{1}'>{2}</{0}>", options.PropertyElementName,
182+
element.Key, itemValue);
183+
}
184+
}
190185

191-
private static string SimplifyScalar(object value)
192-
{
193-
if (value == null) return null;
186+
if (!isEmpty && !options.OmitStructureContainerElement)
187+
{
188+
if (options.UsePropertyKeyAsElementName)
189+
{
190+
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", GetValidElementName(str.TypeTag));
191+
}
192+
else
193+
{
194+
sb.AppendFormat(CultureInfo.InvariantCulture, "</{0}>", options.StructureElementName);
195+
}
196+
}
194197

195-
return new XText(_invalidXMLChars.Replace(value.ToString(), m => "\\u" + ((ushort)m.Value[0]).ToString("x4", CultureInfo.InvariantCulture))).ToString();
198+
return sb.ToString();
196199
}
197200
}
198201
}

0 commit comments

Comments
 (0)