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
-
15
1
using System . Globalization ;
16
2
using System . Linq ;
17
3
using System . Text ;
@@ -30,169 +16,186 @@ internal class XmlPropertyFormatter : IXmlPropertyFormatter
30
16
public string Simplify ( LogEventPropertyValue value , ColumnOptions . PropertiesColumnOptions options )
31
17
{
32
18
if ( value is ScalarValue scalar )
19
+ {
33
20
return SimplifyScalar ( scalar . Value ) ;
21
+ }
34
22
35
23
if ( value is DictionaryValue dict )
36
24
{
37
- var sb = new StringBuilder ( ) ;
25
+ return SimplifyDictionary ( options , dict ) ;
26
+ }
38
27
39
- var isEmpty = true ;
28
+ if ( value is SequenceValue seq )
29
+ {
30
+ return SimplifySequence ( options , seq ) ;
31
+ }
40
32
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
+ }
48
37
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
+ }
57
40
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
+ }
68
47
69
- if ( ! isEmpty && ! options . OmitDictionaryContainerElement )
70
- {
71
- sb . AppendFormat ( CultureInfo . InvariantCulture , "</{0}>" , options . DictionaryElementName ) ;
72
- }
48
+ var validName = name . Trim ( ) ;
73
49
74
- return sb . ToString ( ) ;
50
+ if ( ! char . IsLetter ( validName [ 0 ] ) || validName . StartsWith ( "xml" , true , CultureInfo . CurrentCulture ) )
51
+ {
52
+ validName = "x" + validName ;
75
53
}
76
54
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 ( ) ;
80
70
81
- var isEmpty = true ;
71
+ var isEmpty = true ;
82
72
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 ) )
84
77
{
85
- var itemValue = Simplify ( element , options ) ;
86
- if ( options . OmitElementIfEmpty && string . IsNullOrEmpty ( itemValue ) )
87
- {
88
- continue ;
89
- }
78
+ continue ;
79
+ }
90
80
91
- if ( isEmpty )
81
+ if ( isEmpty )
82
+ {
83
+ isEmpty = false ;
84
+ if ( ! options . OmitDictionaryContainerElement )
92
85
{
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 ) ;
98
87
}
99
-
100
- sb . AppendFormat ( CultureInfo . InvariantCulture , "<{0}>{1}</{0}>" , options . ItemElementName , itemValue ) ;
101
88
}
102
89
103
- if ( ! isEmpty && ! options . OmitSequenceContainerElement )
90
+ var key = SimplifyScalar ( element . Key . Value ) ;
91
+ if ( options . UsePropertyKeyAsElementName )
104
92
{
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 ) ;
106
98
}
107
-
108
- return sb . ToString ( ) ;
109
99
}
110
100
111
- if ( value is StructureValue str )
101
+ if ( ! isEmpty && ! options . OmitDictionaryContainerElement )
112
102
{
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
+ }
116
105
117
- var isEmpty = true ;
106
+ return sb . ToString ( ) ;
107
+ }
118
108
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 ( ) ;
126
112
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 ;
142
114
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 ;
152
121
}
153
122
154
- if ( ! isEmpty && ! options . OmitStructureContainerElement )
123
+ if ( isEmpty )
155
124
{
156
- if ( options . UsePropertyKeyAsElementName )
157
- {
158
- sb . AppendFormat ( CultureInfo . InvariantCulture , "</{0}>" , GetValidElementName ( str . TypeTag ) ) ;
159
- }
160
- else
125
+ isEmpty = false ;
126
+ if ( ! options . OmitSequenceContainerElement )
161
127
{
162
- sb . AppendFormat ( CultureInfo . InvariantCulture , "</ {0}>" , options . StructureElementName ) ;
128
+ sb . AppendFormat ( CultureInfo . InvariantCulture , "<{0}>" , options . SequenceElementName ) ;
163
129
}
164
130
}
165
131
166
- return sb . ToString ( ) ;
132
+ sb . AppendFormat ( CultureInfo . InvariantCulture , "<{0}>{1}</{0}>" , options . ItemElementName , itemValue ) ;
167
133
}
168
134
169
- return null ;
135
+ if ( ! isEmpty && ! options . OmitSequenceContainerElement )
136
+ {
137
+ sb . AppendFormat ( CultureInfo . InvariantCulture , "</{0}>" , options . SequenceElementName ) ;
138
+ }
139
+
140
+ return sb . ToString ( ) ;
170
141
}
171
142
172
- public string GetValidElementName ( string name )
143
+ private string SimplifyStructure ( ColumnOptions . PropertiesColumnOptions options , StructureValue str )
173
144
{
174
- if ( string . IsNullOrWhiteSpace ( name ) )
175
- {
176
- return "x" ;
177
- }
145
+ var props = str . Properties . ToDictionary ( p => p . Name , p => Simplify ( p . Value , options ) ) ;
178
146
179
- var validName = name . Trim ( ) ;
147
+ var sb = new StringBuilder ( ) ;
180
148
181
- if ( ! char . IsLetter ( validName [ 0 ] ) || validName . StartsWith ( "xml" , true , CultureInfo . CurrentCulture ) )
149
+ var isEmpty = true ;
150
+
151
+ foreach ( var element in props )
182
152
{
183
- validName = "x" + name ;
184
- }
153
+ var itemValue = element . Value ;
154
+ if ( options . OmitElementIfEmpty && string . IsNullOrEmpty ( itemValue ) )
155
+ {
156
+ continue ;
157
+ }
185
158
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
+ }
187
174
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
+ }
190
185
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
+ }
194
197
195
- return new XText ( _invalidXMLChars . Replace ( value . ToString ( ) , m => " \\ u" + ( ( ushort ) m . Value [ 0 ] ) . ToString ( "x4" , CultureInfo . InvariantCulture ) ) ) . ToString ( ) ;
198
+ return sb . ToString ( ) ;
196
199
}
197
200
}
198
201
}
0 commit comments