diff --git a/document.go b/document.go
index 1cade3c..b9131f0 100644
--- a/document.go
+++ b/document.go
@@ -29,7 +29,6 @@ package xmlx
import (
"bytes"
- //"code.google.com/p/go-charset/charset"
"encoding/xml"
"errors"
"fmt"
@@ -206,6 +205,10 @@ func (this *Document) SaveBytes() []byte {
if this.SaveDocType {
b.WriteString(fmt.Sprintf(``,
this.Version, this.Encoding, this.StandAlone))
+
+ if len(IndentPrefix) > 0 {
+ b.WriteByte('\n')
+ }
}
b.Write(this.Root.Bytes())
diff --git a/node.go b/node.go
index e20181a..8618804 100644
--- a/node.go
+++ b/node.go
@@ -9,6 +9,7 @@ import (
"encoding/xml"
"fmt"
"strconv"
+ "strings"
)
const (
@@ -19,6 +20,11 @@ const (
NT_ELEMENT
)
+// IndentPrefix holds the value for a single identation level, if one
+// chooses to want indentation in the node.String() and node.Bytes() output.
+// This would normally be set to a single tab, or a number of spaces.
+var IndentPrefix = ""
+
type Attr struct {
Name xml.Name // Attribute namespace and name.
Value string // Attribute value.
@@ -45,7 +51,7 @@ func NewNode(tid byte) *Node {
// This wraps the standard xml.Unmarshal function and supplies this particular
// node as the content to be unmarshalled.
func (this *Node) Unmarshal(obj interface{}) error {
- return xml.NewDecoder(bytes.NewBuffer(this.Bytes())).Decode(obj)
+ return xml.NewDecoder(bytes.NewBuffer(this.bytes(0))).Decode(obj)
}
// Get node value as string
@@ -258,18 +264,20 @@ func rec_SelectNodes(cn *Node, namespace, name string, list *[]*Node, recurse bo
// Note that NT_ROOT is a special-case empty node used as the root for a
// Document. This one has no representation by itself. It merely forwards the
// String() call to it's child nodes.
-func (this *Node) Bytes() (b []byte) {
+func (this *Node) Bytes() []byte { return this.bytes(0) }
+
+func (this *Node) bytes(indent int) (b []byte) {
switch this.Type {
case NT_PROCINST:
- b = this.printProcInst()
+ b = this.printProcInst(indent)
case NT_COMMENT:
- b = this.printComment()
+ b = this.printComment(indent)
case NT_DIRECTIVE:
- b = this.printDirective()
+ b = this.printDirective(indent)
case NT_ELEMENT:
- b = this.printElement()
+ b = this.printElement(indent)
case NT_ROOT:
- b = this.printRoot()
+ b = this.printRoot(indent)
}
return
}
@@ -279,32 +287,38 @@ func (this *Node) Bytes() (b []byte) {
// Document. This one has no representation by itself. It merely forwards the
// String() call to it's child nodes.
func (this *Node) String() (s string) {
- return string(this.Bytes())
+ return string(this.bytes(0))
}
-func (this *Node) printRoot() []byte {
+func (this *Node) printRoot(indent int) []byte {
var b bytes.Buffer
for _, v := range this.Children {
- b.Write(v.Bytes())
+ b.Write(v.bytes(indent))
}
return b.Bytes()
}
-func (this *Node) printProcInst() []byte {
+func (this *Node) printProcInst(indent int) []byte {
return []byte("" + this.Target + " " + this.Value + "?>")
}
-func (this *Node) printComment() []byte {
+func (this *Node) printComment(indent int) []byte {
return []byte("")
}
-func (this *Node) printDirective() []byte {
+func (this *Node) printDirective(indent int) []byte {
return []byte("")
}
-func (this *Node) printElement() []byte {
+func (this *Node) printElement(indent int) []byte {
var b bytes.Buffer
+ lineSuffix, linePrefix := "", strings.Repeat(IndentPrefix, indent)
+ if len(IndentPrefix) > 0 {
+ lineSuffix = "\n"
+ }
+
+ b.WriteString(linePrefix)
if len(this.Name.Space) > 0 {
b.WriteRune('<')
b.WriteString(this.Name.Space)
@@ -325,16 +339,23 @@ func (this *Node) printElement() []byte {
if len(this.Children) == 0 && len(this.Value) == 0 {
b.WriteString(" />")
+ b.WriteString(lineSuffix)
return b.Bytes()
}
b.WriteRune('>')
+ if len(this.Value) == 0 {
+ b.WriteString(lineSuffix)
+ }
for _, v := range this.Children {
- b.Write(v.Bytes())
+ b.Write(v.bytes(indent + 1))
}
b.WriteString(this.Value)
+ if len(this.Value) == 0 {
+ b.WriteString(linePrefix)
+ }
if len(this.Name.Space) > 0 {
b.WriteString("")
b.WriteString(this.Name.Space)
@@ -346,6 +367,7 @@ func (this *Node) printElement() []byte {
b.WriteString(this.Name.Local)
b.WriteRune('>')
}
+ b.WriteString(lineSuffix)
return b.Bytes()
}
diff --git a/test1.xml b/test1.xml
index db44efa..1a59ac9 100644
--- a/test1.xml
+++ b/test1.xml
@@ -1 +1,50 @@
-WriteTheWebhttp://writetheweb.comNews for web users that write backen-usCopyright 2000, WriteTheWeb team.editor@writetheweb.comwebmaster@writetheweb.comWriteTheWebhttp://writetheweb.com/images/mynetscape88.gifhttp://writetheweb.com8831News for web users that write backGiving the world a pluggable Gnutellahttp://writetheweb.com/read.php?item=24WorldOS is a framework on which to build programs that work like Freenet or Gnutella -allowing distributed applications using peer-to-peer routing.Syndication discussions hot uphttp://writetheweb.com/read.php?item=23After a period of dormancy, the Syndication mailing list has become active again, with contributions from leaders in traditional media and Web syndication.Personal web server integrates file sharing and messaginghttp://writetheweb.com/read.php?item=22The 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.Syndication and Metadatahttp://writetheweb.com/read.php?item=21RSS 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.UK bloggers get organisedhttp://writetheweb.com/read.php?item=20Looks 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.Yournamehere.com more important than anythinghttp://writetheweb.com/read.php?item=19Whatever you're publishing on the web, your site name is the most valuable asset you have, according to Carl Steadman.
\ No newline at end of file
+
+
+
+ WriteTheWeb
+ http://writetheweb.com
+ News for web users that write back
+ en-us
+ Copyright 2000, WriteTheWeb team.
+ editor@writetheweb.com
+ webmaster@writetheweb.com
+
+ WriteTheWeb
+ http://writetheweb.com/images/mynetscape88.gif
+ http://writetheweb.com
+ 88
+ 31
+ News for web users that write back
+
+
+ Giving the world a pluggable Gnutella
+ http://writetheweb.com/read.php?item=24
+ WorldOS is a framework on which to build programs that work like Freenet or Gnutella -allowing distributed applications using peer-to-peer routing.
+
+
+ Syndication discussions hot up
+ http://writetheweb.com/read.php?item=23
+ After a period of dormancy, the Syndication mailing list has become active again, with contributions from leaders in traditional media and Web syndication.
+
+
+ Personal web server integrates file sharing and messaging
+ http://writetheweb.com/read.php?item=22
+ 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.
+
+
+ Syndication and Metadata
+ http://writetheweb.com/read.php?item=21
+ 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.
+
+
+ UK bloggers get organised
+ http://writetheweb.com/read.php?item=20
+ 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.
+
+
+ Yournamehere.com more important than anything
+ http://writetheweb.com/read.php?item=19
+ Whatever you're publishing on the web, your site name is the most valuable asset you have, according to Carl Steadman.
+
+
+
diff --git a/xmlx_test.go b/xmlx_test.go
index 8a3414a..97fe4de 100644
--- a/xmlx_test.go
+++ b/xmlx_test.go
@@ -74,6 +74,7 @@ func TestSave(t *testing.T) {
return
}
+ IndentPrefix = "\t"
if err := doc.SaveFile("test1.xml"); err != nil {
t.Errorf("SaveFile(): %s", err)
return