Skip to content

Commit c085b35

Browse files
author
jimt
committedNov 25, 2012
Adds optional indented output for the Node.String() and Node.Bytes()
methods. Set the global `IndentPrefix` var to a tab or spaces to enable indented output. The existing API has not been changed. This addresses issue #7.
1 parent 88d4341 commit c085b35

File tree

4 files changed

+92
-17
lines changed

4 files changed

+92
-17
lines changed
 

‎document.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ package xmlx
2929

3030
import (
3131
"bytes"
32-
//"code.google.com/p/go-charset/charset"
3332
"encoding/xml"
3433
"errors"
3534
"fmt"
@@ -206,6 +205,10 @@ func (this *Document) SaveBytes() []byte {
206205
if this.SaveDocType {
207206
b.WriteString(fmt.Sprintf(`<?xml version="%s" encoding="%s" standalone="%s"?>`,
208207
this.Version, this.Encoding, this.StandAlone))
208+
209+
if len(IndentPrefix) > 0 {
210+
b.WriteByte('\n')
211+
}
209212
}
210213

211214
b.Write(this.Root.Bytes())

‎node.go

+37-15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"encoding/xml"
1010
"fmt"
1111
"strconv"
12+
"strings"
1213
)
1314

1415
const (
@@ -19,6 +20,11 @@ const (
1920
NT_ELEMENT
2021
)
2122

23+
// IndentPrefix holds the value for a single identation level, if one
24+
// chooses to want indentation in the node.String() and node.Bytes() output.
25+
// This would normally be set to a single tab, or a number of spaces.
26+
var IndentPrefix = ""
27+
2228
type Attr struct {
2329
Name xml.Name // Attribute namespace and name.
2430
Value string // Attribute value.
@@ -45,7 +51,7 @@ func NewNode(tid byte) *Node {
4551
// This wraps the standard xml.Unmarshal function and supplies this particular
4652
// node as the content to be unmarshalled.
4753
func (this *Node) Unmarshal(obj interface{}) error {
48-
return xml.NewDecoder(bytes.NewBuffer(this.Bytes())).Decode(obj)
54+
return xml.NewDecoder(bytes.NewBuffer(this.bytes(0))).Decode(obj)
4955
}
5056

5157
// Get node value as string
@@ -258,18 +264,20 @@ func rec_SelectNodes(cn *Node, namespace, name string, list *[]*Node, recurse bo
258264
// Note that NT_ROOT is a special-case empty node used as the root for a
259265
// Document. This one has no representation by itself. It merely forwards the
260266
// String() call to it's child nodes.
261-
func (this *Node) Bytes() (b []byte) {
267+
func (this *Node) Bytes() []byte { return this.bytes(0) }
268+
269+
func (this *Node) bytes(indent int) (b []byte) {
262270
switch this.Type {
263271
case NT_PROCINST:
264-
b = this.printProcInst()
272+
b = this.printProcInst(indent)
265273
case NT_COMMENT:
266-
b = this.printComment()
274+
b = this.printComment(indent)
267275
case NT_DIRECTIVE:
268-
b = this.printDirective()
276+
b = this.printDirective(indent)
269277
case NT_ELEMENT:
270-
b = this.printElement()
278+
b = this.printElement(indent)
271279
case NT_ROOT:
272-
b = this.printRoot()
280+
b = this.printRoot(indent)
273281
}
274282
return
275283
}
@@ -279,32 +287,38 @@ func (this *Node) Bytes() (b []byte) {
279287
// Document. This one has no representation by itself. It merely forwards the
280288
// String() call to it's child nodes.
281289
func (this *Node) String() (s string) {
282-
return string(this.Bytes())
290+
return string(this.bytes(0))
283291
}
284292

285-
func (this *Node) printRoot() []byte {
293+
func (this *Node) printRoot(indent int) []byte {
286294
var b bytes.Buffer
287295
for _, v := range this.Children {
288-
b.Write(v.Bytes())
296+
b.Write(v.bytes(indent))
289297
}
290298
return b.Bytes()
291299
}
292300

293-
func (this *Node) printProcInst() []byte {
301+
func (this *Node) printProcInst(indent int) []byte {
294302
return []byte("<?" + this.Target + " " + this.Value + "?>")
295303
}
296304

297-
func (this *Node) printComment() []byte {
305+
func (this *Node) printComment(indent int) []byte {
298306
return []byte("<!-- " + this.Value + " -->")
299307
}
300308

301-
func (this *Node) printDirective() []byte {
309+
func (this *Node) printDirective(indent int) []byte {
302310
return []byte("<!" + this.Value + "!>")
303311
}
304312

305-
func (this *Node) printElement() []byte {
313+
func (this *Node) printElement(indent int) []byte {
306314
var b bytes.Buffer
307315

316+
lineSuffix, linePrefix := "", strings.Repeat(IndentPrefix, indent)
317+
if len(IndentPrefix) > 0 {
318+
lineSuffix = "\n"
319+
}
320+
321+
b.WriteString(linePrefix)
308322
if len(this.Name.Space) > 0 {
309323
b.WriteRune('<')
310324
b.WriteString(this.Name.Space)
@@ -325,16 +339,23 @@ func (this *Node) printElement() []byte {
325339

326340
if len(this.Children) == 0 && len(this.Value) == 0 {
327341
b.WriteString(" />")
342+
b.WriteString(lineSuffix)
328343
return b.Bytes()
329344
}
330345

331346
b.WriteRune('>')
347+
if len(this.Value) == 0 {
348+
b.WriteString(lineSuffix)
349+
}
332350

333351
for _, v := range this.Children {
334-
b.Write(v.Bytes())
352+
b.Write(v.bytes(indent + 1))
335353
}
336354

337355
b.WriteString(this.Value)
356+
if len(this.Value) == 0 {
357+
b.WriteString(linePrefix)
358+
}
338359
if len(this.Name.Space) > 0 {
339360
b.WriteString("</")
340361
b.WriteString(this.Name.Space)
@@ -346,6 +367,7 @@ func (this *Node) printElement() []byte {
346367
b.WriteString(this.Name.Local)
347368
b.WriteRune('>')
348369
}
370+
b.WriteString(lineSuffix)
349371

350372
return b.Bytes()
351373
}

‎test1.xml

+50-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,50 @@
1-
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="0.91"><channel><title>WriteTheWeb</title><link>http://writetheweb.com</link><description>News for web users that write back</description><language>en-us</language><copyright>Copyright 2000, WriteTheWeb team.</copyright><managingEditor>editor@writetheweb.com</managingEditor><webMaster>webmaster@writetheweb.com</webMaster><image><title>WriteTheWeb</title><url>http://writetheweb.com/images/mynetscape88.gif</url><link>http://writetheweb.com</link><width>88</width><height>31</height><description>News for web users that write back</description></image><item><title>Giving the world a pluggable Gnutella</title><link>http://writetheweb.com/read.php?item=24</link><description>WorldOS is a framework on which to build programs that work like Freenet or Gnutella -allowing distributed applications using peer-to-peer routing.</description></item><item><title>Syndication discussions hot up</title><link>http://writetheweb.com/read.php?item=23</link><description>After a period of dormancy, the Syndication mailing list has become active again, with contributions from leaders in traditional media and Web syndication.</description></item><item><title>Personal web server integrates file sharing and messaging</title><link>http://writetheweb.com/read.php?item=22</link><description>The Magi Project is an innovative project to create a combined personal web server and messaging system that enables the sharing and synchronization of information across desktop, laptop and palmtop devices.</description></item><item><title>Syndication and Metadata</title><link>http://writetheweb.com/read.php?item=21</link><description>RSS is probably the best known metadata format around. RDF is probably one of the least understood. In this essay, published on my O'Reilly Network weblog, I argue that the next generation of RSS should be based on RDF.</description></item><item><title>UK bloggers get organised</title><link>http://writetheweb.com/read.php?item=20</link><description>Looks like the weblogs scene is gathering pace beyond the shores of the US. There's now a UK-specific page on weblogs.com, and a mailing list at egroups.</description></item><item><title>Yournamehere.com more important than anything</title><link>http://writetheweb.com/read.php?item=19</link><description>Whatever you're publishing on the web, your site name is the most valuable asset you have, according to Carl Steadman.</description></item></channel></rss>
1+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
2+
<rss version="0.91">
3+
<channel>
4+
<title>WriteTheWeb</title>
5+
<link>http://writetheweb.com</link>
6+
<description>News for web users that write back</description>
7+
<language>en-us</language>
8+
<copyright>Copyright 2000, WriteTheWeb team.</copyright>
9+
<managingEditor>editor@writetheweb.com</managingEditor>
10+
<webMaster>webmaster@writetheweb.com</webMaster>
11+
<image>
12+
<title>WriteTheWeb</title>
13+
<url>http://writetheweb.com/images/mynetscape88.gif</url>
14+
<link>http://writetheweb.com</link>
15+
<width>88</width>
16+
<height>31</height>
17+
<description>News for web users that write back</description>
18+
</image>
19+
<item>
20+
<title>Giving the world a pluggable Gnutella</title>
21+
<link>http://writetheweb.com/read.php?item=24</link>
22+
<description>WorldOS is a framework on which to build programs that work like Freenet or Gnutella -allowing distributed applications using peer-to-peer routing.</description>
23+
</item>
24+
<item>
25+
<title>Syndication discussions hot up</title>
26+
<link>http://writetheweb.com/read.php?item=23</link>
27+
<description>After a period of dormancy, the Syndication mailing list has become active again, with contributions from leaders in traditional media and Web syndication.</description>
28+
</item>
29+
<item>
30+
<title>Personal web server integrates file sharing and messaging</title>
31+
<link>http://writetheweb.com/read.php?item=22</link>
32+
<description>The Magi Project is an innovative project to create a combined personal web server and messaging system that enables the sharing and synchronization of information across desktop, laptop and palmtop devices.</description>
33+
</item>
34+
<item>
35+
<title>Syndication and Metadata</title>
36+
<link>http://writetheweb.com/read.php?item=21</link>
37+
<description>RSS is probably the best known metadata format around. RDF is probably one of the least understood. In this essay, published on my O'Reilly Network weblog, I argue that the next generation of RSS should be based on RDF.</description>
38+
</item>
39+
<item>
40+
<title>UK bloggers get organised</title>
41+
<link>http://writetheweb.com/read.php?item=20</link>
42+
<description>Looks like the weblogs scene is gathering pace beyond the shores of the US. There's now a UK-specific page on weblogs.com, and a mailing list at egroups.</description>
43+
</item>
44+
<item>
45+
<title>Yournamehere.com more important than anything</title>
46+
<link>http://writetheweb.com/read.php?item=19</link>
47+
<description>Whatever you're publishing on the web, your site name is the most valuable asset you have, according to Carl Steadman.</description>
48+
</item>
49+
</channel>
50+
</rss>

‎xmlx_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func TestSave(t *testing.T) {
7474
return
7575
}
7676

77+
IndentPrefix = "\t"
7778
if err := doc.SaveFile("test1.xml"); err != nil {
7879
t.Errorf("SaveFile(): %s", err)
7980
return

0 commit comments

Comments
 (0)
Please sign in to comment.