OLD | NEW |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package xml | 5 package xml |
6 | 6 |
7 import ( | 7 import ( |
8 "bufio" | 8 "bufio" |
9 "bytes" | 9 "bytes" |
10 "fmt" | 10 "fmt" |
11 "io" | 11 "io" |
12 "reflect" | 12 "reflect" |
13 "strconv" | 13 "strconv" |
14 "strings" | 14 "strings" |
15 ) | 15 ) |
16 | 16 |
17 const ( | 17 const ( |
18 // A generic XML header suitable for use with the output of Marshal. | 18 // A generic XML header suitable for use with the output of Marshal. |
19 // This is not automatically added to any output of this package, | 19 // This is not automatically added to any output of this package, |
20 // it is provided as a convenience. | 20 // it is provided as a convenience. |
21 Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n" | 21 Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n" |
22 ) | 22 ) |
23 | 23 |
24 // A Marshaler can produce well-formatted XML representing its internal state. | 24 // A Marshaler can produce well-formatted XML representing its internal state. |
25 type Marshaler interface { | 25 type Marshaler interface { |
26 MarshalXML() ([]byte, error) | 26 MarshalXML() ([]byte, error) |
27 } | 27 } |
28 | 28 |
29 type printer struct { | 29 // Marshal returns the XML encoding of v. |
30 » *bufio.Writer | |
31 } | |
32 | |
33 // Marshal writes an XML-formatted representation of v to w. | |
34 // | 30 // |
35 // If v implements Marshaler, then Marshal calls its MarshalXML method. | 31 // If v implements Marshaler, then Marshal calls its MarshalXML method. |
36 // Otherwise, Marshal uses the following procedure to create the XML. | 32 // Otherwise, Marshal uses the following procedure to create the XML. |
37 // | 33 // |
38 // Marshal handles an array or slice by marshalling each of the elements. | 34 // Marshal handles an array or slice by marshalling each of the elements. |
39 // Marshal handles a pointer by marshalling the value it points at or, if the | 35 // Marshal handles a pointer by marshalling the value it points at or, if the |
40 // pointer is nil, by writing nothing. Marshal handles an interface value by | 36 // pointer is nil, by writing nothing. Marshal handles an interface value by |
41 // marshalling the value it contains or, if the interface value is nil, by | 37 // marshalling the value it contains or, if the interface value is nil, by |
42 // writing nothing. Marshal handles all other data by writing one or more XML | 38 // writing nothing. Marshal handles all other data by writing one or more XML |
43 // elements containing the data. | 39 // elements containing the data. |
(...skipping 25 matching lines...) Expand all Loading... |
69 // the same parent will be enclosed in one XML element. For example: | 65 // the same parent will be enclosed in one XML element. For example: |
70 // | 66 // |
71 // type Result struct { | 67 // type Result struct { |
72 // XMLName xml.Name `xml:"result"` | 68 // XMLName xml.Name `xml:"result"` |
73 // Id int `xml:"id,attr"` | 69 // Id int `xml:"id,attr"` |
74 // FirstName string `xml:"person>name>first"` | 70 // FirstName string `xml:"person>name>first"` |
75 // LastName string `xml:"person>name>last"` | 71 // LastName string `xml:"person>name>last"` |
76 // Age int `xml:"person>age"` | 72 // Age int `xml:"person>age"` |
77 // } | 73 // } |
78 // | 74 // |
79 //» xml.Marshal(w, &Result{Id: 13, FirstName: "John", LastName: "Doe", Age:
42}) | 75 //» xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
) |
80 // | 76 // |
81 // would be marshalled as: | 77 // would be marshalled as: |
82 // | 78 // |
83 // <result> | 79 // <result> |
84 // <person id="13"> | 80 // <person id="13"> |
85 // <name> | 81 // <name> |
86 // <first>John</first> | 82 // <first>John</first> |
87 // <last>Doe</last> | 83 // <last>Doe</last> |
88 // </name> | 84 // </name> |
89 // <age>42</age> | 85 // <age>42</age> |
90 // </person> | 86 // </person> |
91 // </result> | 87 // </result> |
92 // | 88 // |
93 // Marshal will return an error if asked to marshal a channel, function, or map. | 89 // Marshal will return an error if asked to marshal a channel, function, or map. |
94 func Marshal(w io.Writer, v interface{}) (err error) { | 90 func Marshal(v interface{}) ([]byte, error) { |
95 » p := &printer{bufio.NewWriter(w)} | 91 » var b bytes.Buffer |
96 » err = p.marshalValue(reflect.ValueOf(v), nil) | 92 » if err := NewEncoder(&b).Encode(v); err != nil { |
97 » p.Flush() | 93 » » return nil, err |
| 94 » } |
| 95 » return b.Bytes(), nil |
| 96 } |
| 97 |
| 98 // An Encoder writes XML data to an output stream. |
| 99 type Encoder struct { |
| 100 » printer |
| 101 } |
| 102 |
| 103 // NewEncoder returns a new encoder that writes to w. |
| 104 func NewEncoder(w io.Writer) *Encoder { |
| 105 » return &Encoder{printer{bufio.NewWriter(w)}} |
| 106 } |
| 107 |
| 108 // Encode writes the XML encoding of v to the stream. |
| 109 // |
| 110 // See the documentation for Marshal for details about the conversion |
| 111 // of Go values to XML. |
| 112 func (enc *Encoder) Encode(v interface{}) error { |
| 113 » err := enc.marshalValue(reflect.ValueOf(v), nil) |
| 114 » enc.Flush() |
98 return err | 115 return err |
99 } | 116 } |
100 | 117 |
| 118 type printer struct { |
| 119 *bufio.Writer |
| 120 } |
| 121 |
101 func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error { | 122 func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error { |
102 if !val.IsValid() { | 123 if !val.IsValid() { |
103 return nil | 124 return nil |
104 } | 125 } |
105 | 126 |
106 kind := val.Kind() | 127 kind := val.Kind() |
107 typ := val.Type() | 128 typ := val.Type() |
108 | 129 |
109 // Try Marshaler | 130 // Try Marshaler |
110 if typ.NumMethod() > 0 { | 131 if typ.NumMethod() > 0 { |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 | 390 |
370 // A MarshalXMLError is returned when Marshal encounters a type | 391 // A MarshalXMLError is returned when Marshal encounters a type |
371 // that cannot be converted into XML. | 392 // that cannot be converted into XML. |
372 type UnsupportedTypeError struct { | 393 type UnsupportedTypeError struct { |
373 Type reflect.Type | 394 Type reflect.Type |
374 } | 395 } |
375 | 396 |
376 func (e *UnsupportedTypeError) Error() string { | 397 func (e *UnsupportedTypeError) Error() string { |
377 return "xml: unsupported type: " + e.Type.String() | 398 return "xml: unsupported type: " + e.Type.String() |
378 } | 399 } |
OLD | NEW |