@@ -50,6 +50,29 @@ type Node struct {
50
50
level int // node level in the tree
51
51
}
52
52
53
+ type outputConfiguration struct {
54
+ printSelf bool
55
+ preserveSpaces bool
56
+ emptyElementTagSupport bool
57
+ }
58
+
59
+ type OutputOption func (* outputConfiguration )
60
+
61
+ // WithOutputSelf configures the Node to print the root node itself
62
+ func WithOutputSelf () OutputOption {
63
+ return func (oc * outputConfiguration ) {
64
+ oc .printSelf = true
65
+ }
66
+ }
67
+
68
+ // WithEmptyTagSupport empty tags should be written as <empty/> and
69
+ // not as <empty></empty>
70
+ func WithEmptyTagSupport () OutputOption {
71
+ return func (oc * outputConfiguration ) {
72
+ oc .emptyElementTagSupport = true
73
+ }
74
+ }
75
+
53
76
// InnerText returns the text between the start and end tags of the object.
54
77
func (n * Node ) InnerText () string {
55
78
var output func (* bytes.Buffer , * Node )
@@ -86,7 +109,7 @@ func calculatePreserveSpaces(n *Node, pastValue bool) bool {
86
109
return pastValue
87
110
}
88
111
89
- func outputXML (buf * bytes.Buffer , n * Node , preserveSpaces bool ) {
112
+ func outputXML (buf * bytes.Buffer , n * Node , preserveSpaces bool , config * outputConfiguration ) {
90
113
preserveSpaces = calculatePreserveSpaces (n , preserveSpaces )
91
114
switch n .Type {
92
115
case TextNode :
@@ -125,10 +148,15 @@ func outputXML(buf *bytes.Buffer, n *Node, preserveSpaces bool) {
125
148
if n .Type == DeclarationNode {
126
149
buf .WriteString ("?>" )
127
150
} else {
128
- buf .WriteString (">" )
151
+ if n .FirstChild != nil || ! config .emptyElementTagSupport {
152
+ buf .WriteString (">" )
153
+ } else {
154
+ buf .WriteString ("/>" )
155
+ return
156
+ }
129
157
}
130
158
for child := n .FirstChild ; child != nil ; child = child .NextSibling {
131
- outputXML (buf , child , preserveSpaces )
159
+ outputXML (buf , child , preserveSpaces , config )
132
160
}
133
161
if n .Type != DeclarationNode {
134
162
if n .Prefix == "" {
@@ -141,13 +169,40 @@ func outputXML(buf *bytes.Buffer, n *Node, preserveSpaces bool) {
141
169
142
170
// OutputXML returns the text that including tags name.
143
171
func (n * Node ) OutputXML (self bool ) string {
172
+
173
+ config := & outputConfiguration {
174
+ printSelf : true ,
175
+ emptyElementTagSupport : false ,
176
+ }
144
177
preserveSpaces := calculatePreserveSpaces (n , false )
145
178
var buf bytes.Buffer
146
179
if self && n .Type != DocumentNode {
147
- outputXML (& buf , n , preserveSpaces )
180
+ outputXML (& buf , n , preserveSpaces , config )
181
+ } else {
182
+ for n := n .FirstChild ; n != nil ; n = n .NextSibling {
183
+ outputXML (& buf , n , preserveSpaces , config )
184
+ }
185
+ }
186
+
187
+ return buf .String ()
188
+ }
189
+
190
+ // OutputXMLWithOptions returns the text that including tags name.
191
+ func (n * Node ) OutputXMLWithOptions (opts ... OutputOption ) string {
192
+
193
+ config := & outputConfiguration {}
194
+ // Set the options
195
+ for _ , opt := range opts {
196
+ opt (config )
197
+ }
198
+
199
+ preserveSpaces := calculatePreserveSpaces (n , false )
200
+ var buf bytes.Buffer
201
+ if config .printSelf && n .Type != DocumentNode {
202
+ outputXML (& buf , n , preserveSpaces , config )
148
203
} else {
149
204
for n := n .FirstChild ; n != nil ; n = n .NextSibling {
150
- outputXML (& buf , n , preserveSpaces )
205
+ outputXML (& buf , n , preserveSpaces , config )
151
206
}
152
207
}
153
208
0 commit comments