diff --git a/src/pkg/encoding/xml/example_test.go b/src/pkg/encoding/xml/example_test.go
new file mode 100644
index 00000000000..2f0c1747ced
--- /dev/null
+++ b/src/pkg/encoding/xml/example_test.go
@@ -0,0 +1,43 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xml_test
+
+import (
+ "encoding/xml"
+ "fmt"
+ "os"
+)
+
+//
+//
+// John
+// Doe
+//
+// 42
+// false
+//
+//
+func ExampleMarshalIndent() {
+ type Person struct {
+ XMLName xml.Name `xml:"person"`
+ Id int `xml:"id,attr"`
+ FirstName string `xml:"name>first"`
+ LastName string `xml:"name>last"`
+ Age int `xml:"age"`
+ Height float32 `xml:"height,omitempty"`
+ Married bool
+ Comment string `xml:",comment"`
+ }
+
+ v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
+ v.Comment = " Need more fields. "
+
+ output, err := xml.MarshalIndent(v, "\t", "\t")
+ if err != nil {
+ fmt.Printf("error: %v\n", err)
+ }
+
+ os.Stdout.Write(output)
+}
diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go
index a96c523d553..25d88c4619b 100644
--- a/src/pkg/encoding/xml/marshal.go
+++ b/src/pkg/encoding/xml/marshal.go
@@ -60,32 +60,9 @@ const (
//
// If a field uses a tag "a>b>c", then the element c will be nested inside
// parent elements a and b. Fields that appear next to each other that name
-// the same parent will be enclosed in one XML element. For example:
+// the same parent will be enclosed in one XML element.
//
-// type Result struct {
-// XMLName xml.Name `xml:"result"`
-// Id int `xml:"id,attr"`
-// FirstName string `xml:"person>name>first"`
-// LastName string `xml:"person>name>last"`
-// Age int `xml:"person>age"`
-// Height float `xml:"person>height,omitempty"`
-// Married bool `xml:"person>married"`
-// }
-//
-// xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
-//
-// would be marshalled as:
-//
-//
-//
-//
-// John
-// Doe
-//
-// 42
-// false
-//
-//
+// See MarshalIndent for an example.
//
// Marshal will return an error if asked to marshal a channel, function, or map.
func Marshal(v interface{}) ([]byte, error) {
@@ -96,6 +73,22 @@ func Marshal(v interface{}) ([]byte, error) {
return b.Bytes(), nil
}
+// MarshalIndent works like Marshal, but each XML element begins on a new
+// indented line that starts with prefix and is followed by one or more
+// copies of indent according to the nesting depth.
+func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
+ var b bytes.Buffer
+ enc := NewEncoder(&b)
+ enc.prefix = prefix
+ enc.indent = indent
+ err := enc.marshalValue(reflect.ValueOf(v), nil)
+ enc.Flush()
+ if err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
// An Encoder writes XML data to an output stream.
type Encoder struct {
printer
@@ -103,7 +96,7 @@ type Encoder struct {
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
- return &Encoder{printer{bufio.NewWriter(w)}}
+ return &Encoder{printer{Writer: bufio.NewWriter(w)}}
}
// Encode writes the XML encoding of v to the stream.
@@ -118,8 +111,14 @@ func (enc *Encoder) Encode(v interface{}) error {
type printer struct {
*bufio.Writer
+ indent string
+ prefix string
+ depth int
+ indentedIn bool
}
+// marshalValue writes one or more XML elements representing val.
+// If val was obtained from a struct field, finfo must have its details.
func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
if !val.IsValid() {
return nil
@@ -177,6 +176,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
}
}
+ p.writeIndent(1)
p.WriteByte('<')
p.WriteString(name)
@@ -216,6 +216,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
return err
}
+ p.writeIndent(-1)
p.WriteByte('<')
p.WriteByte('/')
p.WriteString(name)
@@ -294,6 +295,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
if vf.Len() == 0 {
continue
}
+ p.writeIndent(0)
p.WriteString("