func walkXML()

in lib/xml/xml.go [176:236]


func walkXML(dec *xml.Decoder, attrs []xml.Attr, details map[string]Detail) (cdata string, elems map[string]any, err error) {
	elems = map[string]any{}

	for {
		t, err := dec.Token()
		if err != nil {
			if err == io.EOF {
				return "", elems, nil
			}
			return "", nil, err
		}

		switch elem := t.(type) {
		case xml.StartElement:
			key := elem.Name.Local
			det := details[key]

			var part map[string]any
			cdata, part, err = walkXML(dec, elem.Attr, det.Children)
			if err != nil {
				return "", nil, err
			}

			// Combine sub-elements and cdata.
			var add any = part
			if len(part) == 0 {
				add = cdata
			} else if len(cdata) != 0 {
				part["#text"] = cdata
			}

			// Add the data to the current object while taking into account
			// if the current key already exists (in the case of lists).
			value := elems[key]
			switch v := value.(type) {
			case nil:
				add = entype(add, det.Type)
				if det.Plural {
					elems[key] = []any{add}
				} else {
					elems[key] = add
				}
			case []any:
				add = entype(add, det.Type)
				elems[key] = append(v, add)
			default:
				add = entype(add, det.Type)
				elems[key] = []any{v, add}
			}

		case xml.CharData:
			cdata = string(bytes.TrimSpace(elem.Copy()))

		case xml.EndElement:
			for _, attr := range attrs {
				elems[attr.Name.Local] = attr.Value
			}
			return cdata, elems, nil
		}
	}
}