@@ -182,64 +182,121 @@ func (n *Node) FullXPath() string {
182
182
return n.xpath(false, false)
183
183
}
184
184
185
- // Dump builds a printable string representation of the node and its children.
186
- func (n *Node) Dump( prefix, indent string, nodeIDs bool) string {
185
+ // WriteTo writes a readable representation of the node and all its children to w .
186
+ func (n *Node) WriteTo(w io.Writer, prefix, indent string, nodeIDs bool) (int, error) {
187
187
if n == nil {
188
- return prefix + "<nil>"
188
+ return w.Write([]byte( prefix + "<nil>"))
189
189
}
190
190
191
191
n.RLock()
192
192
defer n.RUnlock()
193
193
194
- s := n.LocalName
195
- if s == "" {
196
- s = n.NodeName
194
+ var err error
195
+ var nn, c int
196
+
197
+ // prefix
198
+ if c, err = w.Write([]byte(prefix)); err != nil {
199
+ return nn + c, err
197
200
}
201
+ nn += c
198
202
203
+ // node name
204
+ if n.LocalName != "" {
205
+ if c, err = w.Write([]byte(n.LocalName)); err != nil {
206
+ return nn + c, err
207
+ }
208
+ nn += c
209
+ } else {
210
+ if c, err = w.Write([]byte(n.NodeName)); err != nil {
211
+ return nn + c, err
212
+ }
213
+ nn += c
214
+ }
215
+
216
+ // add #id
217
+ var hasID int
199
218
for i := 0; i < len(n.Attributes); i += 2 {
200
219
if strings.ToLower(n.Attributes[i]) == "id" {
201
- s += "#" + n.Attributes[i+1]
220
+ if c, err = w.Write([]byte("#" + n.Attributes[i+1])); err != nil {
221
+ return nn + c, err
222
+ }
223
+ nn += c
224
+ hasID = 2
202
225
break
203
226
}
204
227
}
205
228
229
+ // node type
206
230
if n.NodeType != NodeTypeElement && n.NodeType != NodeTypeText {
207
- s += fmt.Sprintf(" <%s>", n.NodeType)
231
+ if c, err = fmt.Fprintf(w, " <%s>", n.NodeType); err != nil {
232
+ return nn + c, err
233
+ }
234
+ nn += c
208
235
}
209
236
237
+ // node value
210
238
if n.NodeType == NodeTypeText {
211
239
v := n.NodeValue
212
240
if len(v) > 15 {
213
241
v = v[:15] + "..."
214
242
}
215
- s += fmt.Sprintf(" %q", v)
243
+ if c, err = fmt.Fprintf(w, " %q", v); err != nil {
244
+ return nn + c, err
245
+ }
246
+ nn += c
216
247
}
217
248
218
- if n.NodeType == NodeTypeElement && len(n.Attributes) > 0 {
219
- attrs := ""
220
- for i := 0; i < len(n.Attributes); i += 2 {
249
+ // attributes
250
+ if n.NodeType == NodeTypeElement && len(n.Attributes) > hasID {
251
+ if c, err = w.Write([]byte(" [")); err != nil {
252
+ return nn + c, err
253
+ }
254
+ nn += c
255
+ for i, space := 0, ""; i < len(n.Attributes); i += 2 {
221
256
if strings.ToLower(n.Attributes[i]) == "id" {
222
257
continue
223
258
}
224
- if attrs != "" {
225
- attrs += " "
259
+ if c, err = fmt.Fprintf(w, "%s%s=%q", space, n.Attributes[i], n.Attributes[i+1]); err != nil {
260
+ return nn + c, err
261
+ }
262
+ nn += c
263
+ if space == "" {
264
+ space = " "
226
265
}
227
- attrs += fmt.Sprintf("%s=%q", n.Attributes[i], n.Attributes[i+1])
228
266
}
229
- if attrs != "" {
230
- s += " [" + attrs + "]"
267
+ if c, err = w.Write([]byte{']'}); err != nil {
268
+ return nn + c, err
231
269
}
270
+ nn += c
232
271
}
233
272
273
+ // node id
234
274
if nodeIDs {
235
- s += fmt.Sprintf(" (%d)", n.NodeID)
275
+ if c, err = fmt.Fprintf(w, " (%d)", n.NodeID); err != nil {
276
+ return nn + c, err
277
+ }
278
+ nn += c
236
279
}
237
280
281
+ // children
238
282
for i := 0; i < len(n.Children); i++ {
239
- s += "\n" + n.Children[i].Dump(prefix+indent, indent, nodeIDs)
283
+ if c, err = fmt.Fprintln(w); err != nil {
284
+ return nn + c, err
285
+ }
286
+ nn += c
287
+ if c, err = n.Children[i].WriteTo(w, prefix+indent, indent, nodeIDs); err != nil {
288
+ return nn + c, err
289
+ }
290
+ nn += c
240
291
}
292
+ return nn, nil
293
+ }
241
294
242
- return prefix + s
295
+ // Dump builds a printable string representation of the node and its children.
296
+ func (n *Node) Dump(prefix, indent string, nodeIDs bool) string {
297
+ var buf bytes.Buffer
298
+ _, _ = n.WriteTo(&buf, prefix, indent, nodeIDs)
299
+ return buf.String()
243
300
}
244
301
245
302
// NodeState is the state of a DOM node.
0 commit comments