Copyright 2009 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

import (
	
	
	
	
	
	
	
)
BUG(rsc): Mapping between XML elements and data structures is inherently flawed: an XML element is an order-dependent collection of anonymous values, while a data structure is an order-independent collection of named values. See package json for a textual representation more suitable to data structures.
Unmarshal parses the XML-encoded data and stores the result in the value pointed to by v, which must be an arbitrary struct, slice, or string. Well-formed data that does not fit into v is discarded. Because Unmarshal uses the reflect package, it can only assign to exported (upper case) fields. Unmarshal uses a case-sensitive comparison to match XML element names to tag values and struct field names. Unmarshal maps an XML element to a struct using the following rules. In the rules, the tag of a field refers to the value associated with the key 'xml' in the struct field's tag (see the example above). * If the struct has a field of type []byte or string with tag ",innerxml", Unmarshal accumulates the raw XML nested inside the element in that field. The rest of the rules still apply. * If the struct has a field named XMLName of type Name, Unmarshal records the element name in that field. * If the XMLName field has an associated tag of the form "name" or "namespace-URL name", the XML element must have the given name (and, optionally, name space) or else Unmarshal returns an error. * If the XML element has an attribute whose name matches a struct field name with an associated tag containing ",attr" or the explicit name in a struct field tag of the form "name,attr", Unmarshal records the attribute value in that field. * If the XML element has an attribute not handled by the previous rule and the struct has a field with an associated tag containing ",any,attr", Unmarshal records the attribute value in the first such field. * If the XML element contains character data, that data is accumulated in the first struct field that has tag ",chardata". The struct field may have type []byte or string. If there is no such field, the character data is discarded. * If the XML element contains comments, they are accumulated in the first struct field that has tag ",comment". The struct field may have type []byte or string. If there is no such field, the comments are discarded. * If the XML element contains a sub-element whose name matches the prefix of a tag formatted as "a" or "a>b>c", unmarshal will descend into the XML structure looking for elements with the given names, and will map the innermost elements to that struct field. A tag starting with ">" is equivalent to one starting with the field name followed by ">". * If the XML element contains a sub-element whose name matches a struct field's XMLName tag and the struct field has no explicit name tag as per the previous rule, unmarshal maps the sub-element to that struct field. * If the XML element contains a sub-element whose name matches a field without any mode flags (",attr", ",chardata", etc), Unmarshal maps the sub-element to that struct field. * If the XML element contains a sub-element that hasn't matched any of the above rules and the struct has a field with tag ",any", unmarshal maps the sub-element to that struct field. * An anonymous struct field is handled as if the fields of its value were part of the outer struct. * A struct field with tag "-" is never unmarshaled into. If Unmarshal encounters a field type that implements the Unmarshaler interface, Unmarshal calls its UnmarshalXML method to produce the value from the XML element. Otherwise, if the value implements encoding.TextUnmarshaler, Unmarshal calls that value's UnmarshalText method. Unmarshal maps an XML element to a string or []byte by saving the concatenation of that element's character data in the string or []byte. The saved []byte is never nil. Unmarshal maps an attribute value to a string or []byte by saving the value in the string or slice. Unmarshal maps an attribute value to an Attr by saving the attribute, including its name, in the Attr. Unmarshal maps an XML element or attribute value to a slice by extending the length of the slice and mapping the element or attribute to the newly created value. Unmarshal maps an XML element or attribute value to a bool by setting it to the boolean value represented by the string. Whitespace is trimmed and ignored. Unmarshal maps an XML element or attribute value to an integer or floating-point field by setting the field to the result of interpreting the string value in decimal. There is no check for overflow. Whitespace is trimmed and ignored. Unmarshal maps an XML element to a Name by recording the element name. Unmarshal maps an XML element to a pointer by setting the pointer to a freshly allocated value and then mapping the element to that value. A missing element or empty attribute value will be unmarshaled as a zero value. If the field is a slice, a zero value will be appended to the field. Otherwise, the field will be set to its zero value.
func ( []byte,  interface{}) error {
	return NewDecoder(bytes.NewReader()).Decode()
}
Decode works like Unmarshal, except it reads the decoder stream to find the start element.
func ( *Decoder) ( interface{}) error {
	return .DecodeElement(, nil)
}
DecodeElement works like Unmarshal except that it takes a pointer to the start XML element to decode into v. It is useful when a client reads some raw XML tokens itself but also wants to defer to Unmarshal for some elements.
func ( *Decoder) ( interface{},  *StartElement) error {
	 := reflect.ValueOf()
	if .Kind() != reflect.Ptr {
		return errors.New("non-pointer passed to Unmarshal")
	}
	return .unmarshal(.Elem(), )
}
An UnmarshalError represents an error in the unmarshaling process.
type UnmarshalError string

func ( UnmarshalError) () string { return string() }
Unmarshaler is the interface implemented by objects that can unmarshal an XML element description of themselves. UnmarshalXML decodes a single XML element beginning with the given start element. If it returns an error, the outer call to Unmarshal stops and returns that error. UnmarshalXML must consume exactly one XML element. One common implementation strategy is to unmarshal into a separate value with a layout matching the expected XML using d.DecodeElement, and then to copy the data from that value into the receiver. Another common strategy is to use d.Token to process the XML object one token at a time. UnmarshalXML may not use d.RawToken.
type Unmarshaler interface {
	UnmarshalXML(d *Decoder, start StartElement) error
}
UnmarshalerAttr is the interface implemented by objects that can unmarshal an XML attribute description of themselves. UnmarshalXMLAttr decodes a single XML attribute. If it returns an error, the outer call to Unmarshal stops and returns that error. UnmarshalXMLAttr is used only for struct fields with the "attr" option in the field tag.
type UnmarshalerAttr interface {
	UnmarshalXMLAttr(attr Attr) error
}
receiverType returns the receiver type to use in an expression like "%s.MethodName".
func ( interface{}) string {
	 := reflect.TypeOf()
	if .Name() != "" {
		return .String()
	}
	return "(" + .String() + ")"
}
unmarshalInterface unmarshals a single XML element into val. start is the opening tag of the element.
Record that decoder must stop at end tag corresponding to start.
	.pushEOF()

	.unmarshalDepth++
	 := .UnmarshalXML(, *)
	.unmarshalDepth--
	if  != nil {
		.popEOF()
		return 
	}

	if !.popEOF() {
		return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(), .Name.Local)
	}

	return nil
}
unmarshalTextInterface unmarshals a single XML element into val. The chardata contained in the element (but not its children) is passed to the text unmarshaler.
func ( *Decoder) ( encoding.TextUnmarshaler) error {
	var  []byte
	 := 1
	for  > 0 {
		,  := .Token()
		if  != nil {
			return 
		}
		switch t := .(type) {
		case CharData:
			if  == 1 {
				 = append(, ...)
			}
		case StartElement:
			++
		case EndElement:
			--
		}
	}
	return .UnmarshalText()
}
unmarshalAttr unmarshals a single XML attribute into val.
func ( *Decoder) ( reflect.Value,  Attr) error {
	if .Kind() == reflect.Ptr {
		if .IsNil() {
			.Set(reflect.New(.Type().Elem()))
		}
		 = .Elem()
	}
This is an unmarshaler with a non-pointer receiver, so it's likely to be incorrect, but we do what we're told.
		return .Interface().(UnmarshalerAttr).UnmarshalXMLAttr()
	}
	if .CanAddr() {
		 := .Addr()
		if .CanInterface() && .Type().Implements(unmarshalerAttrType) {
			return .Interface().(UnmarshalerAttr).UnmarshalXMLAttr()
		}
	}
Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
This is an unmarshaler with a non-pointer receiver, so it's likely to be incorrect, but we do what we're told.
		return .Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(.Value))
	}
	if .CanAddr() {
		 := .Addr()
		if .CanInterface() && .Type().Implements(textUnmarshalerType) {
			return .Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(.Value))
		}
	}

Slice of element values. Grow slice.
		 := .Len()
		.Set(reflect.Append(, reflect.Zero(.Type().Elem())))
Recur to read element into slice.
		if  := .(.Index(), );  != nil {
			.SetLen()
			return 
		}
		return nil
	}

	if .Type() == attrType {
		.Set(reflect.ValueOf())
		return nil
	}

	return copyValue(, []byte(.Value))
}

var (
	attrType            = reflect.TypeOf(Attr{})
	unmarshalerType     = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
	unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
	textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
Unmarshal a single XML element into val.
Find start element if we need it.
	if  == nil {
		for {
			,  := .Token()
			if  != nil {
				return 
			}
			if ,  := .(StartElement);  {
				 = &
				break
			}
		}
	}
Load value from interface, but only if the result will be usefully addressable.
	if .Kind() == reflect.Interface && !.IsNil() {
		 := .Elem()
		if .Kind() == reflect.Ptr && !.IsNil() {
			 = 
		}
	}

	if .Kind() == reflect.Ptr {
		if .IsNil() {
			.Set(reflect.New(.Type().Elem()))
		}
		 = .Elem()
	}

This is an unmarshaler with a non-pointer receiver, so it's likely to be incorrect, but we do what we're told.
		return .unmarshalInterface(.Interface().(Unmarshaler), )
	}

	if .CanAddr() {
		 := .Addr()
		if .CanInterface() && .Type().Implements(unmarshalerType) {
			return .unmarshalInterface(.Interface().(Unmarshaler), )
		}
	}

	if .CanInterface() && .Type().Implements(textUnmarshalerType) {
		return .unmarshalTextInterface(.Interface().(encoding.TextUnmarshaler))
	}

	if .CanAddr() {
		 := .Addr()
		if .CanInterface() && .Type().Implements(textUnmarshalerType) {
			return .unmarshalTextInterface(.Interface().(encoding.TextUnmarshaler))
		}
	}

	var (
		         []byte
		     reflect.Value
		      []byte
		  reflect.Value
		      reflect.Value
		 int
		  []byte
		      reflect.Value
		           reflect.Value
		        *typeInfo
		          error
	)

	switch  := ; .Kind() {
	default:
		return errors.New("unknown type " + .Type().String())

TODO: For now, simply ignore the field. In the near future we may choose to unmarshal the start element on it, if not nil.
		return .Skip()

	case reflect.Slice:
		 := .Type()
[]byte
			 = 
			break
		}
Slice of element values. Grow slice.
		 := .Len()
		.Set(reflect.Append(, reflect.Zero(.Type().Elem())))
Recur to read element into slice.
		if  := .(.Index(), );  != nil {
			.SetLen()
			return 
		}
		return nil

	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
		 = 

	case reflect.Struct:
		 := .Type()
		if  == nameType {
			.Set(reflect.ValueOf(.Name))
			break
		}

		 = 
		,  = getTypeInfo()
		if  != nil {
			return 
		}
Validate and assign element name.
		if .xmlname != nil {
			 := .xmlname
			if .name != "" && .name != .Name.Local {
				return UnmarshalError("expected element type <" + .name + "> but have <" + .Name.Local + ">")
			}
			if .xmlns != "" && .xmlns != .Name.Space {
				 := "expected element <" + .name + "> in name space " + .xmlns + " but have "
				if .Name.Space == "" {
					 += "no name space"
				} else {
					 += .Name.Space
				}
				return UnmarshalError()
			}
			 := .value(, initNilPointers)
			if ,  := .Interface().(Name);  {
				.Set(reflect.ValueOf(.Name))
			}
		}
Assign attributes.
		for ,  := range .Attr {
			 := false
			 := -1
			for  := range .fields {
				 := &.fields[]
				switch .flags & fMode {
				case fAttr:
					 := .value(, initNilPointers)
					if .Name.Local == .name && (.xmlns == "" || .xmlns == .Name.Space) {
						if  := .unmarshalAttr(, );  != nil {
							return 
						}
						 = true
					}

				case fAny | fAttr:
					if  == -1 {
						 = 
					}
				}
			}
			if ! &&  >= 0 {
				 := &.fields[]
				 := .value(, initNilPointers)
				if  := .unmarshalAttr(, );  != nil {
					return 
				}
			}
		}
Determine whether we need to save character data or comments.
		for  := range .fields {
			 := &.fields[]
			switch .flags & fMode {
			case fCDATA, fCharData:
				if !.IsValid() {
					 = .value(, initNilPointers)
				}

			case fComment:
				if !.IsValid() {
					 = .value(, initNilPointers)
				}

			case fAny, fAny | fElement:
				if !.IsValid() {
					 = .value(, initNilPointers)
				}

			case fInnerXML:
				if !.IsValid() {
					 = .value(, initNilPointers)
					if .saved == nil {
						 = 0
						.saved = new(bytes.Buffer)
					} else {
						 = .savedOffset()
					}
				}
			}
		}
	}
Find end element. Process sub-elements along the way.
:
	for {
		var  int
		if .IsValid() {
			 = .savedOffset()
		}
		,  := .Token()
		if  != nil {
			return 
		}
		switch t := .(type) {
		case StartElement:
			 := false
			if .IsValid() {
				,  = .unmarshalPath(, , nil, &)
				if  != nil {
					return 
				}
				if ! && .IsValid() {
					 = true
					if  := .(, &);  != nil {
						return 
					}
				}
			}
			if ! {
				if  := .Skip();  != nil {
					return 
				}
			}

		case EndElement:
			if .IsValid() {
				 = .saved.Bytes()[:]
				if  == 0 {
					.saved = nil
				}
			}
			break 

		case CharData:
			if .IsValid() {
				 = append(, ...)
			}

		case Comment:
			if .IsValid() {
				 = append(, ...)
			}
		}
	}

	if .IsValid() && .CanInterface() && .Type().Implements(textUnmarshalerType) {
		if  := .Interface().(encoding.TextUnmarshaler).UnmarshalText();  != nil {
			return 
		}
		 = reflect.Value{}
	}

	if .IsValid() && .CanAddr() {
		 := .Addr()
		if .CanInterface() && .Type().Implements(textUnmarshalerType) {
			if  := .Interface().(encoding.TextUnmarshaler).UnmarshalText();  != nil {
				return 
			}
			 = reflect.Value{}
		}
	}

	if  := copyValue(, );  != nil {
		return 
	}

	switch  := ; .Kind() {
	case reflect.String:
		.SetString(string())
	case reflect.Slice:
		.Set(reflect.ValueOf())
	}

	switch  := ; .Kind() {
	case reflect.String:
		.SetString(string())
	case reflect.Slice:
		if .Type().Elem().Kind() == reflect.Uint8 {
			.Set(reflect.ValueOf())
		}
	}

	return nil
}

func ( reflect.Value,  []byte) ( error) {
	 := 

	if .Kind() == reflect.Ptr {
		if .IsNil() {
			.Set(reflect.New(.Type().Elem()))
		}
		 = .Elem()
	}
Save accumulated data.
	switch .Kind() {
Probably a comment.
	default:
		return errors.New("cannot unmarshal into " + .Type().String())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if len() == 0 {
			.SetInt(0)
			return nil
		}
		,  := strconv.ParseInt(strings.TrimSpace(string()), 10, .Type().Bits())
		if  != nil {
			return 
		}
		.SetInt()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if len() == 0 {
			.SetUint(0)
			return nil
		}
		,  := strconv.ParseUint(strings.TrimSpace(string()), 10, .Type().Bits())
		if  != nil {
			return 
		}
		.SetUint()
	case reflect.Float32, reflect.Float64:
		if len() == 0 {
			.SetFloat(0)
			return nil
		}
		,  := strconv.ParseFloat(strings.TrimSpace(string()), .Type().Bits())
		if  != nil {
			return 
		}
		.SetFloat()
	case reflect.Bool:
		if len() == 0 {
			.SetBool(false)
			return nil
		}
		,  := strconv.ParseBool(strings.TrimSpace(string()))
		if  != nil {
			return 
		}
		.SetBool()
	case reflect.String:
		.SetString(string())
	case reflect.Slice:
non-nil to flag presence
			 = []byte{}
		}
		.SetBytes()
	}
	return nil
}
unmarshalPath walks down an XML structure looking for wanted paths, and calls unmarshal on them. The consumed result tells whether XML elements have been consumed from the Decoder until start's matching end element, or if it's still untouched because start is uninteresting for sv's fields.
func ( *Decoder) ( *typeInfo,  reflect.Value,  []string,  *StartElement) ( bool,  error) {
	 := false
:
	for  := range .fields {
		 := &.fields[]
		if .flags&fElement == 0 || len(.parents) < len() || .xmlns != "" && .xmlns != .Name.Space {
			continue
		}
		for  := range  {
			if [] != .parents[] {
				continue 
			}
		}
It's a perfect match, unmarshal the field.
			return true, .unmarshal(.value(, initNilPointers), )
		}
It's a prefix for the field. Break and recurse since it's not ok for one field path to be itself the prefix for another field path.
			 = true
We can reuse the same slice as long as we don't try to append to it.
			 = .parents[:len()+1]
			break
		}
	}
We have no business with this element.
		return false, nil
The element is not a perfect match for any field, but one or more fields have the path to this element as a parent prefix. Recurse and attempt to match these.
	for {
		var  Token
		,  = .Token()
		if  != nil {
			return true, 
		}
		switch t := .(type) {
		case StartElement:
			,  := .(, , , &)
			if  != nil {
				return true, 
			}
			if ! {
				if  := .Skip();  != nil {
					return true, 
				}
			}
		case EndElement:
			return true, nil
		}
	}
}
Skip reads tokens until it has consumed the end element matching the most recent start element already consumed. It recurs if it encounters a start element, so it can be used to skip nested structures. It returns nil if it finds an end element matching the start element; otherwise it returns an error describing the problem.
func ( *Decoder) () error {
	for {
		,  := .Token()
		if  != nil {
			return 
		}
		switch .(type) {
		case StartElement:
			if  := .();  != nil {
				return 
			}
		case EndElement:
			return nil
		}
	}