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
}
}
}