golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/webdav/internal/xml/marshal.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package xml
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"encoding"
    11  	"fmt"
    12  	"io"
    13  	"reflect"
    14  	"strconv"
    15  	"strings"
    16  )
    17  
    18  const (
    19  	// A generic XML header suitable for use with the output of Marshal.
    20  	// This is not automatically added to any output of this package,
    21  	// it is provided as a convenience.
    22  	Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
    23  )
    24  
    25  // Marshal returns the XML encoding of v.
    26  //
    27  // Marshal handles an array or slice by marshalling each of the elements.
    28  // Marshal handles a pointer by marshalling the value it points at or, if the
    29  // pointer is nil, by writing nothing. Marshal handles an interface value by
    30  // marshalling the value it contains or, if the interface value is nil, by
    31  // writing nothing. Marshal handles all other data by writing one or more XML
    32  // elements containing the data.
    33  //
    34  // The name for the XML elements is taken from, in order of preference:
    35  //   - the tag on the XMLName field, if the data is a struct
    36  //   - the value of the XMLName field of type xml.Name
    37  //   - the tag of the struct field used to obtain the data
    38  //   - the name of the struct field used to obtain the data
    39  //   - the name of the marshalled type
    40  //
    41  // The XML element for a struct contains marshalled elements for each of the
    42  // exported fields of the struct, with these exceptions:
    43  //   - the XMLName field, described above, is omitted.
    44  //   - a field with tag "-" is omitted.
    45  //   - a field with tag "name,attr" becomes an attribute with
    46  //     the given name in the XML element.
    47  //   - a field with tag ",attr" becomes an attribute with the
    48  //     field name in the XML element.
    49  //   - a field with tag ",chardata" is written as character data,
    50  //     not as an XML element.
    51  //   - a field with tag ",innerxml" is written verbatim, not subject
    52  //     to the usual marshalling procedure.
    53  //   - a field with tag ",comment" is written as an XML comment, not
    54  //     subject to the usual marshalling procedure. It must not contain
    55  //     the "--" string within it.
    56  //   - a field with a tag including the "omitempty" option is omitted
    57  //     if the field value is empty. The empty values are false, 0, any
    58  //     nil pointer or interface value, and any array, slice, map, or
    59  //     string of length zero.
    60  //   - an anonymous struct field is handled as if the fields of its
    61  //     value were part of the outer struct.
    62  //
    63  // If a field uses a tag "a>b>c", then the element c will be nested inside
    64  // parent elements a and b. Fields that appear next to each other that name
    65  // the same parent will be enclosed in one XML element.
    66  //
    67  // See MarshalIndent for an example.
    68  //
    69  // Marshal will return an error if asked to marshal a channel, function, or map.
    70  func Marshal(v interface{}) ([]byte, error) {
    71  	var b bytes.Buffer
    72  	if err := NewEncoder(&b).Encode(v); err != nil {
    73  		return nil, err
    74  	}
    75  	return b.Bytes(), nil
    76  }
    77  
    78  // Marshaler is the interface implemented by objects that can marshal
    79  // themselves into valid XML elements.
    80  //
    81  // MarshalXML encodes the receiver as zero or more XML elements.
    82  // By convention, arrays or slices are typically encoded as a sequence
    83  // of elements, one per entry.
    84  // Using start as the element tag is not required, but doing so
    85  // will enable Unmarshal to match the XML elements to the correct
    86  // struct field.
    87  // One common implementation strategy is to construct a separate
    88  // value with a layout corresponding to the desired XML and then
    89  // to encode it using e.EncodeElement.
    90  // Another common strategy is to use repeated calls to e.EncodeToken
    91  // to generate the XML output one token at a time.
    92  // The sequence of encoded tokens must make up zero or more valid
    93  // XML elements.
    94  type Marshaler interface {
    95  	MarshalXML(e *Encoder, start StartElement) error
    96  }
    97  
    98  // MarshalerAttr is the interface implemented by objects that can marshal
    99  // themselves into valid XML attributes.
   100  //
   101  // MarshalXMLAttr returns an XML attribute with the encoded value of the receiver.
   102  // Using name as the attribute name is not required, but doing so
   103  // will enable Unmarshal to match the attribute to the correct
   104  // struct field.
   105  // If MarshalXMLAttr returns the zero attribute Attr{}, no attribute
   106  // will be generated in the output.
   107  // MarshalXMLAttr is used only for struct fields with the
   108  // "attr" option in the field tag.
   109  type MarshalerAttr interface {
   110  	MarshalXMLAttr(name Name) (Attr, error)
   111  }
   112  
   113  // MarshalIndent works like Marshal, but each XML element begins on a new
   114  // indented line that starts with prefix and is followed by one or more
   115  // copies of indent according to the nesting depth.
   116  func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
   117  	var b bytes.Buffer
   118  	enc := NewEncoder(&b)
   119  	enc.Indent(prefix, indent)
   120  	if err := enc.Encode(v); err != nil {
   121  		return nil, err
   122  	}
   123  	return b.Bytes(), nil
   124  }
   125  
   126  // An Encoder writes XML data to an output stream.
   127  type Encoder struct {
   128  	p printer
   129  }
   130  
   131  // NewEncoder returns a new encoder that writes to w.
   132  func NewEncoder(w io.Writer) *Encoder {
   133  	e := &Encoder{printer{Writer: bufio.NewWriter(w)}}
   134  	e.p.encoder = e
   135  	return e
   136  }
   137  
   138  // Indent sets the encoder to generate XML in which each element
   139  // begins on a new indented line that starts with prefix and is followed by
   140  // one or more copies of indent according to the nesting depth.
   141  func (enc *Encoder) Indent(prefix, indent string) {
   142  	enc.p.prefix = prefix
   143  	enc.p.indent = indent
   144  }
   145  
   146  // Encode writes the XML encoding of v to the stream.
   147  //
   148  // See the documentation for Marshal for details about the conversion
   149  // of Go values to XML.
   150  //
   151  // Encode calls Flush before returning.
   152  func (enc *Encoder) Encode(v interface{}) error {
   153  	err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	return enc.p.Flush()
   158  }
   159  
   160  // EncodeElement writes the XML encoding of v to the stream,
   161  // using start as the outermost tag in the encoding.
   162  //
   163  // See the documentation for Marshal for details about the conversion
   164  // of Go values to XML.
   165  //
   166  // EncodeElement calls Flush before returning.
   167  func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
   168  	err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start)
   169  	if err != nil {
   170  		return err
   171  	}
   172  	return enc.p.Flush()
   173  }
   174  
   175  var (
   176  	begComment   = []byte("<!--")
   177  	endComment   = []byte("-->")
   178  	endProcInst  = []byte("?>")
   179  	endDirective = []byte(">")
   180  )
   181  
   182  // EncodeToken writes the given XML token to the stream.
   183  // It returns an error if StartElement and EndElement tokens are not
   184  // properly matched.
   185  //
   186  // EncodeToken does not call Flush, because usually it is part of a
   187  // larger operation such as Encode or EncodeElement (or a custom
   188  // Marshaler's MarshalXML invoked during those), and those will call
   189  // Flush when finished. Callers that create an Encoder and then invoke
   190  // EncodeToken directly, without using Encode or EncodeElement, need to
   191  // call Flush when finished to ensure that the XML is written to the
   192  // underlying writer.
   193  //
   194  // EncodeToken allows writing a ProcInst with Target set to "xml" only
   195  // as the first token in the stream.
   196  //
   197  // When encoding a StartElement holding an XML namespace prefix
   198  // declaration for a prefix that is not already declared, contained
   199  // elements (including the StartElement itself) will use the declared
   200  // prefix when encoding names with matching namespace URIs.
   201  func (enc *Encoder) EncodeToken(t Token) error {
   202  
   203  	p := &enc.p
   204  	switch t := t.(type) {
   205  	case StartElement:
   206  		if err := p.writeStart(&t); err != nil {
   207  			return err
   208  		}
   209  	case EndElement:
   210  		if err := p.writeEnd(t.Name); err != nil {
   211  			return err
   212  		}
   213  	case CharData:
   214  		escapeText(p, t, false)
   215  	case Comment:
   216  		if bytes.Contains(t, endComment) {
   217  			return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
   218  		}
   219  		p.WriteString("<!--")
   220  		p.Write(t)
   221  		p.WriteString("-->")
   222  		return p.cachedWriteError()
   223  	case ProcInst:
   224  		// First token to be encoded which is also a ProcInst with target of xml
   225  		// is the xml declaration. The only ProcInst where target of xml is allowed.
   226  		if t.Target == "xml" && p.Buffered() != 0 {
   227  			return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded")
   228  		}
   229  		if !isNameString(t.Target) {
   230  			return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target")
   231  		}
   232  		if bytes.Contains(t.Inst, endProcInst) {
   233  			return fmt.Errorf("xml: EncodeToken of ProcInst containing ?> marker")
   234  		}
   235  		p.WriteString("<?")
   236  		p.WriteString(t.Target)
   237  		if len(t.Inst) > 0 {
   238  			p.WriteByte(' ')
   239  			p.Write(t.Inst)
   240  		}
   241  		p.WriteString("?>")
   242  	case Directive:
   243  		if !isValidDirective(t) {
   244  			return fmt.Errorf("xml: EncodeToken of Directive containing wrong < or > markers")
   245  		}
   246  		p.WriteString("<!")
   247  		p.Write(t)
   248  		p.WriteString(">")
   249  	default:
   250  		return fmt.Errorf("xml: EncodeToken of invalid token type")
   251  
   252  	}
   253  	return p.cachedWriteError()
   254  }
   255  
   256  // isValidDirective reports whether dir is a valid directive text,
   257  // meaning angle brackets are matched, ignoring comments and strings.
   258  func isValidDirective(dir Directive) bool {
   259  	var (
   260  		depth     int
   261  		inquote   uint8
   262  		incomment bool
   263  	)
   264  	for i, c := range dir {
   265  		switch {
   266  		case incomment:
   267  			if c == '>' {
   268  				if n := 1 + i - len(endComment); n >= 0 && bytes.Equal(dir[n:i+1], endComment) {
   269  					incomment = false
   270  				}
   271  			}
   272  			// Just ignore anything in comment
   273  		case inquote != 0:
   274  			if c == inquote {
   275  				inquote = 0
   276  			}
   277  			// Just ignore anything within quotes
   278  		case c == '\'' || c == '"':
   279  			inquote = c
   280  		case c == '<':
   281  			if i+len(begComment) < len(dir) && bytes.Equal(dir[i:i+len(begComment)], begComment) {
   282  				incomment = true
   283  			} else {
   284  				depth++
   285  			}
   286  		case c == '>':
   287  			if depth == 0 {
   288  				return false
   289  			}
   290  			depth--
   291  		}
   292  	}
   293  	return depth == 0 && inquote == 0 && !incomment
   294  }
   295  
   296  // Flush flushes any buffered XML to the underlying writer.
   297  // See the EncodeToken documentation for details about when it is necessary.
   298  func (enc *Encoder) Flush() error {
   299  	return enc.p.Flush()
   300  }
   301  
   302  type printer struct {
   303  	*bufio.Writer
   304  	encoder    *Encoder
   305  	seq        int
   306  	indent     string
   307  	prefix     string
   308  	depth      int
   309  	indentedIn bool
   310  	putNewline bool
   311  	defaultNS  string
   312  	attrNS     map[string]string // map prefix -> name space
   313  	attrPrefix map[string]string // map name space -> prefix
   314  	prefixes   []printerPrefix
   315  	tags       []Name
   316  }
   317  
   318  // printerPrefix holds a namespace undo record.
   319  // When an element is popped, the prefix record
   320  // is set back to the recorded URL. The empty
   321  // prefix records the URL for the default name space.
   322  //
   323  // The start of an element is recorded with an element
   324  // that has mark=true.
   325  type printerPrefix struct {
   326  	prefix string
   327  	url    string
   328  	mark   bool
   329  }
   330  
   331  func (p *printer) prefixForNS(url string, isAttr bool) string {
   332  	// The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml"
   333  	// and must be referred to that way.
   334  	// (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns",
   335  	// but users should not be trying to use that one directly - that's our job.)
   336  	if url == xmlURL {
   337  		return "xml"
   338  	}
   339  	if !isAttr && url == p.defaultNS {
   340  		// We can use the default name space.
   341  		return ""
   342  	}
   343  	return p.attrPrefix[url]
   344  }
   345  
   346  // defineNS pushes any namespace definition found in the given attribute.
   347  // If ignoreNonEmptyDefault is true, an xmlns="nonempty"
   348  // attribute will be ignored.
   349  func (p *printer) defineNS(attr Attr, ignoreNonEmptyDefault bool) error {
   350  	var prefix string
   351  	if attr.Name.Local == "xmlns" {
   352  		if attr.Name.Space != "" && attr.Name.Space != "xml" && attr.Name.Space != xmlURL {
   353  			return fmt.Errorf("xml: cannot redefine xmlns attribute prefix")
   354  		}
   355  	} else if attr.Name.Space == "xmlns" && attr.Name.Local != "" {
   356  		prefix = attr.Name.Local
   357  		if attr.Value == "" {
   358  			// Technically, an empty XML namespace is allowed for an attribute.
   359  			// From http://www.w3.org/TR/xml-names11/#scoping-defaulting:
   360  			//
   361  			// 	The attribute value in a namespace declaration for a prefix may be
   362  			//	empty. This has the effect, within the scope of the declaration, of removing
   363  			//	any association of the prefix with a namespace name.
   364  			//
   365  			// However our namespace prefixes here are used only as hints. There's
   366  			// no need to respect the removal of a namespace prefix, so we ignore it.
   367  			return nil
   368  		}
   369  	} else {
   370  		// Ignore: it's not a namespace definition
   371  		return nil
   372  	}
   373  	if prefix == "" {
   374  		if attr.Value == p.defaultNS {
   375  			// No need for redefinition.
   376  			return nil
   377  		}
   378  		if attr.Value != "" && ignoreNonEmptyDefault {
   379  			// We have an xmlns="..." value but
   380  			// it can't define a name space in this context,
   381  			// probably because the element has an empty
   382  			// name space. In this case, we just ignore
   383  			// the name space declaration.
   384  			return nil
   385  		}
   386  	} else if _, ok := p.attrPrefix[attr.Value]; ok {
   387  		// There's already a prefix for the given name space,
   388  		// so use that. This prevents us from
   389  		// having two prefixes for the same name space
   390  		// so attrNS and attrPrefix can remain bijective.
   391  		return nil
   392  	}
   393  	p.pushPrefix(prefix, attr.Value)
   394  	return nil
   395  }
   396  
   397  // createNSPrefix creates a name space prefix attribute
   398  // to use for the given name space, defining a new prefix
   399  // if necessary.
   400  // If isAttr is true, the prefix is to be created for an attribute
   401  // prefix, which means that the default name space cannot
   402  // be used.
   403  func (p *printer) createNSPrefix(url string, isAttr bool) {
   404  	if _, ok := p.attrPrefix[url]; ok {
   405  		// We already have a prefix for the given URL.
   406  		return
   407  	}
   408  	switch {
   409  	case !isAttr && url == p.defaultNS:
   410  		// We can use the default name space.
   411  		return
   412  	case url == "":
   413  		// The only way we can encode names in the empty
   414  		// name space is by using the default name space,
   415  		// so we must use that.
   416  		if p.defaultNS != "" {
   417  			// The default namespace is non-empty, so we
   418  			// need to set it to empty.
   419  			p.pushPrefix("", "")
   420  		}
   421  		return
   422  	case url == xmlURL:
   423  		return
   424  	}
   425  	// TODO If the URL is an existing prefix, we could
   426  	// use it as is. That would enable the
   427  	// marshaling of elements that had been unmarshaled
   428  	// and with a name space prefix that was not found.
   429  	// although technically it would be incorrect.
   430  
   431  	// Pick a name. We try to use the final element of the path
   432  	// but fall back to _.
   433  	prefix := strings.TrimRight(url, "/")
   434  	if i := strings.LastIndex(prefix, "/"); i >= 0 {
   435  		prefix = prefix[i+1:]
   436  	}
   437  	if prefix == "" || !isName([]byte(prefix)) || strings.Contains(prefix, ":") {
   438  		prefix = "_"
   439  	}
   440  	if strings.HasPrefix(prefix, "xml") {
   441  		// xmlanything is reserved.
   442  		prefix = "_" + prefix
   443  	}
   444  	if p.attrNS[prefix] != "" {
   445  		// Name is taken. Find a better one.
   446  		for p.seq++; ; p.seq++ {
   447  			if id := prefix + "_" + strconv.Itoa(p.seq); p.attrNS[id] == "" {
   448  				prefix = id
   449  				break
   450  			}
   451  		}
   452  	}
   453  
   454  	p.pushPrefix(prefix, url)
   455  }
   456  
   457  // writeNamespaces writes xmlns attributes for all the
   458  // namespace prefixes that have been defined in
   459  // the current element.
   460  func (p *printer) writeNamespaces() {
   461  	for i := len(p.prefixes) - 1; i >= 0; i-- {
   462  		prefix := p.prefixes[i]
   463  		if prefix.mark {
   464  			return
   465  		}
   466  		p.WriteString(" ")
   467  		if prefix.prefix == "" {
   468  			// Default name space.
   469  			p.WriteString(`xmlns="`)
   470  		} else {
   471  			p.WriteString("xmlns:")
   472  			p.WriteString(prefix.prefix)
   473  			p.WriteString(`="`)
   474  		}
   475  		EscapeText(p, []byte(p.nsForPrefix(prefix.prefix)))
   476  		p.WriteString(`"`)
   477  	}
   478  }
   479  
   480  // pushPrefix pushes a new prefix on the prefix stack
   481  // without checking to see if it is already defined.
   482  func (p *printer) pushPrefix(prefix, url string) {
   483  	p.prefixes = append(p.prefixes, printerPrefix{
   484  		prefix: prefix,
   485  		url:    p.nsForPrefix(prefix),
   486  	})
   487  	p.setAttrPrefix(prefix, url)
   488  }
   489  
   490  // nsForPrefix returns the name space for the given
   491  // prefix. Note that this is not valid for the
   492  // empty attribute prefix, which always has an empty
   493  // name space.
   494  func (p *printer) nsForPrefix(prefix string) string {
   495  	if prefix == "" {
   496  		return p.defaultNS
   497  	}
   498  	return p.attrNS[prefix]
   499  }
   500  
   501  // markPrefix marks the start of an element on the prefix
   502  // stack.
   503  func (p *printer) markPrefix() {
   504  	p.prefixes = append(p.prefixes, printerPrefix{
   505  		mark: true,
   506  	})
   507  }
   508  
   509  // popPrefix pops all defined prefixes for the current
   510  // element.
   511  func (p *printer) popPrefix() {
   512  	for len(p.prefixes) > 0 {
   513  		prefix := p.prefixes[len(p.prefixes)-1]
   514  		p.prefixes = p.prefixes[:len(p.prefixes)-1]
   515  		if prefix.mark {
   516  			break
   517  		}
   518  		p.setAttrPrefix(prefix.prefix, prefix.url)
   519  	}
   520  }
   521  
   522  // setAttrPrefix sets an attribute name space prefix.
   523  // If url is empty, the attribute is removed.
   524  // If prefix is empty, the default name space is set.
   525  func (p *printer) setAttrPrefix(prefix, url string) {
   526  	if prefix == "" {
   527  		p.defaultNS = url
   528  		return
   529  	}
   530  	if url == "" {
   531  		delete(p.attrPrefix, p.attrNS[prefix])
   532  		delete(p.attrNS, prefix)
   533  		return
   534  	}
   535  	if p.attrPrefix == nil {
   536  		// Need to define a new name space.
   537  		p.attrPrefix = make(map[string]string)
   538  		p.attrNS = make(map[string]string)
   539  	}
   540  	// Remove any old prefix value. This is OK because we maintain a
   541  	// strict one-to-one mapping between prefix and URL (see
   542  	// defineNS)
   543  	delete(p.attrPrefix, p.attrNS[prefix])
   544  	p.attrPrefix[url] = prefix
   545  	p.attrNS[prefix] = url
   546  }
   547  
   548  var (
   549  	marshalerType     = reflect.TypeOf((*Marshaler)(nil)).Elem()
   550  	marshalerAttrType = reflect.TypeOf((*MarshalerAttr)(nil)).Elem()
   551  	textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
   552  )
   553  
   554  // marshalValue writes one or more XML elements representing val.
   555  // If val was obtained from a struct field, finfo must have its details.
   556  func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error {
   557  	if startTemplate != nil && startTemplate.Name.Local == "" {
   558  		return fmt.Errorf("xml: EncodeElement of StartElement with missing name")
   559  	}
   560  
   561  	if !val.IsValid() {
   562  		return nil
   563  	}
   564  	if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) {
   565  		return nil
   566  	}
   567  
   568  	// Drill into interfaces and pointers.
   569  	// This can turn into an infinite loop given a cyclic chain,
   570  	// but it matches the Go 1 behavior.
   571  	for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
   572  		if val.IsNil() {
   573  			return nil
   574  		}
   575  		val = val.Elem()
   576  	}
   577  
   578  	kind := val.Kind()
   579  	typ := val.Type()
   580  
   581  	// Check for marshaler.
   582  	if val.CanInterface() && typ.Implements(marshalerType) {
   583  		return p.marshalInterface(val.Interface().(Marshaler), p.defaultStart(typ, finfo, startTemplate))
   584  	}
   585  	if val.CanAddr() {
   586  		pv := val.Addr()
   587  		if pv.CanInterface() && pv.Type().Implements(marshalerType) {
   588  			return p.marshalInterface(pv.Interface().(Marshaler), p.defaultStart(pv.Type(), finfo, startTemplate))
   589  		}
   590  	}
   591  
   592  	// Check for text marshaler.
   593  	if val.CanInterface() && typ.Implements(textMarshalerType) {
   594  		return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), p.defaultStart(typ, finfo, startTemplate))
   595  	}
   596  	if val.CanAddr() {
   597  		pv := val.Addr()
   598  		if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
   599  			return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), p.defaultStart(pv.Type(), finfo, startTemplate))
   600  		}
   601  	}
   602  
   603  	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
   604  	if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
   605  		for i, n := 0, val.Len(); i < n; i++ {
   606  			if err := p.marshalValue(val.Index(i), finfo, startTemplate); err != nil {
   607  				return err
   608  			}
   609  		}
   610  		return nil
   611  	}
   612  
   613  	tinfo, err := getTypeInfo(typ)
   614  	if err != nil {
   615  		return err
   616  	}
   617  
   618  	// Create start element.
   619  	// Precedence for the XML element name is:
   620  	// 0. startTemplate
   621  	// 1. XMLName field in underlying struct;
   622  	// 2. field name/tag in the struct field; and
   623  	// 3. type name
   624  	var start StartElement
   625  
   626  	// explicitNS records whether the element's name space has been
   627  	// explicitly set (for example an XMLName field).
   628  	explicitNS := false
   629  
   630  	if startTemplate != nil {
   631  		start.Name = startTemplate.Name
   632  		explicitNS = true
   633  		start.Attr = append(start.Attr, startTemplate.Attr...)
   634  	} else if tinfo.xmlname != nil {
   635  		xmlname := tinfo.xmlname
   636  		if xmlname.name != "" {
   637  			start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
   638  		} else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" {
   639  			start.Name = v
   640  		}
   641  		explicitNS = true
   642  	}
   643  	if start.Name.Local == "" && finfo != nil {
   644  		start.Name.Local = finfo.name
   645  		if finfo.xmlns != "" {
   646  			start.Name.Space = finfo.xmlns
   647  			explicitNS = true
   648  		}
   649  	}
   650  	if start.Name.Local == "" {
   651  		name := typ.Name()
   652  		if name == "" {
   653  			return &UnsupportedTypeError{typ}
   654  		}
   655  		start.Name.Local = name
   656  	}
   657  
   658  	// defaultNS records the default name space as set by a xmlns="..."
   659  	// attribute. We don't set p.defaultNS because we want to let
   660  	// the attribute writing code (in p.defineNS) be solely responsible
   661  	// for maintaining that.
   662  	defaultNS := p.defaultNS
   663  
   664  	// Attributes
   665  	for i := range tinfo.fields {
   666  		finfo := &tinfo.fields[i]
   667  		if finfo.flags&fAttr == 0 {
   668  			continue
   669  		}
   670  		attr, err := p.fieldAttr(finfo, val)
   671  		if err != nil {
   672  			return err
   673  		}
   674  		if attr.Name.Local == "" {
   675  			continue
   676  		}
   677  		start.Attr = append(start.Attr, attr)
   678  		if attr.Name.Space == "" && attr.Name.Local == "xmlns" {
   679  			defaultNS = attr.Value
   680  		}
   681  	}
   682  	if !explicitNS {
   683  		// Historic behavior: elements use the default name space
   684  		// they are contained in by default.
   685  		start.Name.Space = defaultNS
   686  	}
   687  	// Historic behaviour: an element that's in a namespace sets
   688  	// the default namespace for all elements contained within it.
   689  	start.setDefaultNamespace()
   690  
   691  	if err := p.writeStart(&start); err != nil {
   692  		return err
   693  	}
   694  
   695  	if val.Kind() == reflect.Struct {
   696  		err = p.marshalStruct(tinfo, val)
   697  	} else {
   698  		s, b, err1 := p.marshalSimple(typ, val)
   699  		if err1 != nil {
   700  			err = err1
   701  		} else if b != nil {
   702  			EscapeText(p, b)
   703  		} else {
   704  			p.EscapeString(s)
   705  		}
   706  	}
   707  	if err != nil {
   708  		return err
   709  	}
   710  
   711  	if err := p.writeEnd(start.Name); err != nil {
   712  		return err
   713  	}
   714  
   715  	return p.cachedWriteError()
   716  }
   717  
   718  // fieldAttr returns the attribute of the given field.
   719  // If the returned attribute has an empty Name.Local,
   720  // it should not be used.
   721  // The given value holds the value containing the field.
   722  func (p *printer) fieldAttr(finfo *fieldInfo, val reflect.Value) (Attr, error) {
   723  	fv := finfo.value(val)
   724  	name := Name{Space: finfo.xmlns, Local: finfo.name}
   725  	if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
   726  		return Attr{}, nil
   727  	}
   728  	if fv.Kind() == reflect.Interface && fv.IsNil() {
   729  		return Attr{}, nil
   730  	}
   731  	if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) {
   732  		attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
   733  		return attr, err
   734  	}
   735  	if fv.CanAddr() {
   736  		pv := fv.Addr()
   737  		if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
   738  			attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
   739  			return attr, err
   740  		}
   741  	}
   742  	if fv.CanInterface() && fv.Type().Implements(textMarshalerType) {
   743  		text, err := fv.Interface().(encoding.TextMarshaler).MarshalText()
   744  		if err != nil {
   745  			return Attr{}, err
   746  		}
   747  		return Attr{name, string(text)}, nil
   748  	}
   749  	if fv.CanAddr() {
   750  		pv := fv.Addr()
   751  		if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
   752  			text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
   753  			if err != nil {
   754  				return Attr{}, err
   755  			}
   756  			return Attr{name, string(text)}, nil
   757  		}
   758  	}
   759  	// Dereference or skip nil pointer, interface values.
   760  	switch fv.Kind() {
   761  	case reflect.Ptr, reflect.Interface:
   762  		if fv.IsNil() {
   763  			return Attr{}, nil
   764  		}
   765  		fv = fv.Elem()
   766  	}
   767  	s, b, err := p.marshalSimple(fv.Type(), fv)
   768  	if err != nil {
   769  		return Attr{}, err
   770  	}
   771  	if b != nil {
   772  		s = string(b)
   773  	}
   774  	return Attr{name, s}, nil
   775  }
   776  
   777  // defaultStart returns the default start element to use,
   778  // given the reflect type, field info, and start template.
   779  func (p *printer) defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement {
   780  	var start StartElement
   781  	// Precedence for the XML element name is as above,
   782  	// except that we do not look inside structs for the first field.
   783  	if startTemplate != nil {
   784  		start.Name = startTemplate.Name
   785  		start.Attr = append(start.Attr, startTemplate.Attr...)
   786  	} else if finfo != nil && finfo.name != "" {
   787  		start.Name.Local = finfo.name
   788  		start.Name.Space = finfo.xmlns
   789  	} else if typ.Name() != "" {
   790  		start.Name.Local = typ.Name()
   791  	} else {
   792  		// Must be a pointer to a named type,
   793  		// since it has the Marshaler methods.
   794  		start.Name.Local = typ.Elem().Name()
   795  	}
   796  	// Historic behaviour: elements use the name space of
   797  	// the element they are contained in by default.
   798  	if start.Name.Space == "" {
   799  		start.Name.Space = p.defaultNS
   800  	}
   801  	start.setDefaultNamespace()
   802  	return start
   803  }
   804  
   805  // marshalInterface marshals a Marshaler interface value.
   806  func (p *printer) marshalInterface(val Marshaler, start StartElement) error {
   807  	// Push a marker onto the tag stack so that MarshalXML
   808  	// cannot close the XML tags that it did not open.
   809  	p.tags = append(p.tags, Name{})
   810  	n := len(p.tags)
   811  
   812  	err := val.MarshalXML(p.encoder, start)
   813  	if err != nil {
   814  		return err
   815  	}
   816  
   817  	// Make sure MarshalXML closed all its tags. p.tags[n-1] is the mark.
   818  	if len(p.tags) > n {
   819  		return fmt.Errorf("xml: %s.MarshalXML wrote invalid XML: <%s> not closed", receiverType(val), p.tags[len(p.tags)-1].Local)
   820  	}
   821  	p.tags = p.tags[:n-1]
   822  	return nil
   823  }
   824  
   825  // marshalTextInterface marshals a TextMarshaler interface value.
   826  func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartElement) error {
   827  	if err := p.writeStart(&start); err != nil {
   828  		return err
   829  	}
   830  	text, err := val.MarshalText()
   831  	if err != nil {
   832  		return err
   833  	}
   834  	EscapeText(p, text)
   835  	return p.writeEnd(start.Name)
   836  }
   837  
   838  // writeStart writes the given start element.
   839  func (p *printer) writeStart(start *StartElement) error {
   840  	if start.Name.Local == "" {
   841  		return fmt.Errorf("xml: start tag with no name")
   842  	}
   843  
   844  	p.tags = append(p.tags, start.Name)
   845  	p.markPrefix()
   846  	// Define any name spaces explicitly declared in the attributes.
   847  	// We do this as a separate pass so that explicitly declared prefixes
   848  	// will take precedence over implicitly declared prefixes
   849  	// regardless of the order of the attributes.
   850  	ignoreNonEmptyDefault := start.Name.Space == ""
   851  	for _, attr := range start.Attr {
   852  		if err := p.defineNS(attr, ignoreNonEmptyDefault); err != nil {
   853  			return err
   854  		}
   855  	}
   856  	// Define any new name spaces implied by the attributes.
   857  	for _, attr := range start.Attr {
   858  		name := attr.Name
   859  		// From http://www.w3.org/TR/xml-names11/#defaulting
   860  		// "Default namespace declarations do not apply directly
   861  		// to attribute names; the interpretation of unprefixed
   862  		// attributes is determined by the element on which they
   863  		// appear."
   864  		// This means we don't need to create a new namespace
   865  		// when an attribute name space is empty.
   866  		if name.Space != "" && !name.isNamespace() {
   867  			p.createNSPrefix(name.Space, true)
   868  		}
   869  	}
   870  	p.createNSPrefix(start.Name.Space, false)
   871  
   872  	p.writeIndent(1)
   873  	p.WriteByte('<')
   874  	p.writeName(start.Name, false)
   875  	p.writeNamespaces()
   876  	for _, attr := range start.Attr {
   877  		name := attr.Name
   878  		if name.Local == "" || name.isNamespace() {
   879  			// Namespaces have already been written by writeNamespaces above.
   880  			continue
   881  		}
   882  		p.WriteByte(' ')
   883  		p.writeName(name, true)
   884  		p.WriteString(`="`)
   885  		p.EscapeString(attr.Value)
   886  		p.WriteByte('"')
   887  	}
   888  	p.WriteByte('>')
   889  	return nil
   890  }
   891  
   892  // writeName writes the given name. It assumes
   893  // that p.createNSPrefix(name) has already been called.
   894  func (p *printer) writeName(name Name, isAttr bool) {
   895  	if prefix := p.prefixForNS(name.Space, isAttr); prefix != "" {
   896  		p.WriteString(prefix)
   897  		p.WriteByte(':')
   898  	}
   899  	p.WriteString(name.Local)
   900  }
   901  
   902  func (p *printer) writeEnd(name Name) error {
   903  	if name.Local == "" {
   904  		return fmt.Errorf("xml: end tag with no name")
   905  	}
   906  	if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" {
   907  		return fmt.Errorf("xml: end tag </%s> without start tag", name.Local)
   908  	}
   909  	if top := p.tags[len(p.tags)-1]; top != name {
   910  		if top.Local != name.Local {
   911  			return fmt.Errorf("xml: end tag </%s> does not match start tag <%s>", name.Local, top.Local)
   912  		}
   913  		return fmt.Errorf("xml: end tag </%s> in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space)
   914  	}
   915  	p.tags = p.tags[:len(p.tags)-1]
   916  
   917  	p.writeIndent(-1)
   918  	p.WriteByte('<')
   919  	p.WriteByte('/')
   920  	p.writeName(name, false)
   921  	p.WriteByte('>')
   922  	p.popPrefix()
   923  	return nil
   924  }
   925  
   926  func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) {
   927  	switch val.Kind() {
   928  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   929  		return strconv.FormatInt(val.Int(), 10), nil, nil
   930  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   931  		return strconv.FormatUint(val.Uint(), 10), nil, nil
   932  	case reflect.Float32, reflect.Float64:
   933  		return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil
   934  	case reflect.String:
   935  		return val.String(), nil, nil
   936  	case reflect.Bool:
   937  		return strconv.FormatBool(val.Bool()), nil, nil
   938  	case reflect.Array:
   939  		if typ.Elem().Kind() != reflect.Uint8 {
   940  			break
   941  		}
   942  		// [...]byte
   943  		var bytes []byte
   944  		if val.CanAddr() {
   945  			bytes = val.Slice(0, val.Len()).Bytes()
   946  		} else {
   947  			bytes = make([]byte, val.Len())
   948  			reflect.Copy(reflect.ValueOf(bytes), val)
   949  		}
   950  		return "", bytes, nil
   951  	case reflect.Slice:
   952  		if typ.Elem().Kind() != reflect.Uint8 {
   953  			break
   954  		}
   955  		// []byte
   956  		return "", val.Bytes(), nil
   957  	}
   958  	return "", nil, &UnsupportedTypeError{typ}
   959  }
   960  
   961  var ddBytes = []byte("--")
   962  
   963  func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
   964  	s := parentStack{p: p}
   965  	for i := range tinfo.fields {
   966  		finfo := &tinfo.fields[i]
   967  		if finfo.flags&fAttr != 0 {
   968  			continue
   969  		}
   970  		vf := finfo.value(val)
   971  
   972  		// Dereference or skip nil pointer, interface values.
   973  		switch vf.Kind() {
   974  		case reflect.Ptr, reflect.Interface:
   975  			if !vf.IsNil() {
   976  				vf = vf.Elem()
   977  			}
   978  		}
   979  
   980  		switch finfo.flags & fMode {
   981  		case fCharData:
   982  			if err := s.setParents(&noField, reflect.Value{}); err != nil {
   983  				return err
   984  			}
   985  			if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
   986  				data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
   987  				if err != nil {
   988  					return err
   989  				}
   990  				Escape(p, data)
   991  				continue
   992  			}
   993  			if vf.CanAddr() {
   994  				pv := vf.Addr()
   995  				if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
   996  					data, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
   997  					if err != nil {
   998  						return err
   999  					}
  1000  					Escape(p, data)
  1001  					continue
  1002  				}
  1003  			}
  1004  			var scratch [64]byte
  1005  			switch vf.Kind() {
  1006  			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1007  				Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10))
  1008  			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1009  				Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10))
  1010  			case reflect.Float32, reflect.Float64:
  1011  				Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits()))
  1012  			case reflect.Bool:
  1013  				Escape(p, strconv.AppendBool(scratch[:0], vf.Bool()))
  1014  			case reflect.String:
  1015  				if err := EscapeText(p, []byte(vf.String())); err != nil {
  1016  					return err
  1017  				}
  1018  			case reflect.Slice:
  1019  				if elem, ok := vf.Interface().([]byte); ok {
  1020  					if err := EscapeText(p, elem); err != nil {
  1021  						return err
  1022  					}
  1023  				}
  1024  			}
  1025  			continue
  1026  
  1027  		case fComment:
  1028  			if err := s.setParents(&noField, reflect.Value{}); err != nil {
  1029  				return err
  1030  			}
  1031  			k := vf.Kind()
  1032  			if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
  1033  				return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
  1034  			}
  1035  			if vf.Len() == 0 {
  1036  				continue
  1037  			}
  1038  			p.writeIndent(0)
  1039  			p.WriteString("<!--")
  1040  			dashDash := false
  1041  			dashLast := false
  1042  			switch k {
  1043  			case reflect.String:
  1044  				s := vf.String()
  1045  				dashDash = strings.Index(s, "--") >= 0
  1046  				dashLast = s[len(s)-1] == '-'
  1047  				if !dashDash {
  1048  					p.WriteString(s)
  1049  				}
  1050  			case reflect.Slice:
  1051  				b := vf.Bytes()
  1052  				dashDash = bytes.Index(b, ddBytes) >= 0
  1053  				dashLast = b[len(b)-1] == '-'
  1054  				if !dashDash {
  1055  					p.Write(b)
  1056  				}
  1057  			default:
  1058  				panic("can't happen")
  1059  			}
  1060  			if dashDash {
  1061  				return fmt.Errorf(`xml: comments must not contain "--"`)
  1062  			}
  1063  			if dashLast {
  1064  				// "--->" is invalid grammar. Make it "- -->"
  1065  				p.WriteByte(' ')
  1066  			}
  1067  			p.WriteString("-->")
  1068  			continue
  1069  
  1070  		case fInnerXml:
  1071  			iface := vf.Interface()
  1072  			switch raw := iface.(type) {
  1073  			case []byte:
  1074  				p.Write(raw)
  1075  				continue
  1076  			case string:
  1077  				p.WriteString(raw)
  1078  				continue
  1079  			}
  1080  
  1081  		case fElement, fElement | fAny:
  1082  			if err := s.setParents(finfo, vf); err != nil {
  1083  				return err
  1084  			}
  1085  		}
  1086  		if err := p.marshalValue(vf, finfo, nil); err != nil {
  1087  			return err
  1088  		}
  1089  	}
  1090  	if err := s.setParents(&noField, reflect.Value{}); err != nil {
  1091  		return err
  1092  	}
  1093  	return p.cachedWriteError()
  1094  }
  1095  
  1096  var noField fieldInfo
  1097  
  1098  // return the bufio Writer's cached write error
  1099  func (p *printer) cachedWriteError() error {
  1100  	_, err := p.Write(nil)
  1101  	return err
  1102  }
  1103  
  1104  func (p *printer) writeIndent(depthDelta int) {
  1105  	if len(p.prefix) == 0 && len(p.indent) == 0 {
  1106  		return
  1107  	}
  1108  	if depthDelta < 0 {
  1109  		p.depth--
  1110  		if p.indentedIn {
  1111  			p.indentedIn = false
  1112  			return
  1113  		}
  1114  		p.indentedIn = false
  1115  	}
  1116  	if p.putNewline {
  1117  		p.WriteByte('\n')
  1118  	} else {
  1119  		p.putNewline = true
  1120  	}
  1121  	if len(p.prefix) > 0 {
  1122  		p.WriteString(p.prefix)
  1123  	}
  1124  	if len(p.indent) > 0 {
  1125  		for i := 0; i < p.depth; i++ {
  1126  			p.WriteString(p.indent)
  1127  		}
  1128  	}
  1129  	if depthDelta > 0 {
  1130  		p.depth++
  1131  		p.indentedIn = true
  1132  	}
  1133  }
  1134  
  1135  type parentStack struct {
  1136  	p       *printer
  1137  	xmlns   string
  1138  	parents []string
  1139  }
  1140  
  1141  // setParents sets the stack of current parents to those found in finfo.
  1142  // It only writes the start elements if vf holds a non-nil value.
  1143  // If finfo is &noField, it pops all elements.
  1144  func (s *parentStack) setParents(finfo *fieldInfo, vf reflect.Value) error {
  1145  	xmlns := s.p.defaultNS
  1146  	if finfo.xmlns != "" {
  1147  		xmlns = finfo.xmlns
  1148  	}
  1149  	commonParents := 0
  1150  	if xmlns == s.xmlns {
  1151  		for ; commonParents < len(finfo.parents) && commonParents < len(s.parents); commonParents++ {
  1152  			if finfo.parents[commonParents] != s.parents[commonParents] {
  1153  				break
  1154  			}
  1155  		}
  1156  	}
  1157  	// Pop off any parents that aren't in common with the previous field.
  1158  	for i := len(s.parents) - 1; i >= commonParents; i-- {
  1159  		if err := s.p.writeEnd(Name{
  1160  			Space: s.xmlns,
  1161  			Local: s.parents[i],
  1162  		}); err != nil {
  1163  			return err
  1164  		}
  1165  	}
  1166  	s.parents = finfo.parents
  1167  	s.xmlns = xmlns
  1168  	if commonParents >= len(s.parents) {
  1169  		// No new elements to push.
  1170  		return nil
  1171  	}
  1172  	if (vf.Kind() == reflect.Ptr || vf.Kind() == reflect.Interface) && vf.IsNil() {
  1173  		// The element is nil, so no need for the start elements.
  1174  		s.parents = s.parents[:commonParents]
  1175  		return nil
  1176  	}
  1177  	// Push any new parents required.
  1178  	for _, name := range s.parents[commonParents:] {
  1179  		start := &StartElement{
  1180  			Name: Name{
  1181  				Space: s.xmlns,
  1182  				Local: name,
  1183  			},
  1184  		}
  1185  		// Set the default name space for parent elements
  1186  		// to match what we do with other elements.
  1187  		if s.xmlns != s.p.defaultNS {
  1188  			start.setDefaultNamespace()
  1189  		}
  1190  		if err := s.p.writeStart(start); err != nil {
  1191  			return err
  1192  		}
  1193  	}
  1194  	return nil
  1195  }
  1196  
  1197  // A MarshalXMLError is returned when Marshal encounters a type
  1198  // that cannot be converted into XML.
  1199  type UnsupportedTypeError struct {
  1200  	Type reflect.Type
  1201  }
  1202  
  1203  func (e *UnsupportedTypeError) Error() string {
  1204  	return "xml: unsupported type: " + e.Type.String()
  1205  }
  1206  
  1207  func isEmptyValue(v reflect.Value) bool {
  1208  	switch v.Kind() {
  1209  	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
  1210  		return v.Len() == 0
  1211  	case reflect.Bool:
  1212  		return !v.Bool()
  1213  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1214  		return v.Int() == 0
  1215  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1216  		return v.Uint() == 0
  1217  	case reflect.Float32, reflect.Float64:
  1218  		return v.Float() == 0
  1219  	case reflect.Interface, reflect.Ptr:
  1220  		return v.IsNil()
  1221  	}
  1222  	return false
  1223  }