iedc-go/vendor/github.com/chanxuehong/util/xml.go
2023-03-03 03:12:15 +08:00

259 lines
5.0 KiB
Go

package util
import (
"bufio"
"bytes"
"encoding/xml"
"io"
"strings"
)
// DecodeXMLToMap decodes xml reading from io.Reader and returns the first-level sub-node key-value set,
// if the first-level sub-node contains child nodes, skip it.
func DecodeXMLToMap(r io.Reader) (m map[string]string, err error) {
m = make(map[string]string)
var (
decoder = xml.NewDecoder(r)
depth = 0
token xml.Token
key string
value strings.Builder
)
for {
token, err = decoder.Token()
if err != nil {
if err == io.EOF {
err = nil
}
return
}
switch v := token.(type) {
case xml.StartElement:
depth++
switch depth {
case 2:
key = v.Name.Local
value.Reset()
case 3:
if err = decoder.Skip(); err != nil {
return
}
depth--
key = "" // key == "" indicates that the node with depth==2 has children
}
case xml.CharData:
if depth == 2 && key != "" {
value.Write(v)
}
case xml.EndElement:
if depth == 2 && key != "" {
m[key] = value.String()
}
depth--
}
}
}
// EncodeXMLFromMap encodes map[string]string to io.Writer with xml format.
// NOTE: This function requires the rootname argument and the keys of m (type map[string]string) argument
// are legitimate xml name string that does not contain the required escape character!
func EncodeXMLFromMap(w io.Writer, m map[string]string, rootname string) (err error) {
switch v := w.(type) {
case *bytes.Buffer:
bufw := v
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
for k, v := range m {
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
if err = xml.EscapeText(bufw, []byte(v)); err != nil {
return
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
return nil
case *strings.Builder:
bufw := v
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
for k, v := range m {
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
if err = xml.EscapeText(bufw, []byte(v)); err != nil {
return
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
return nil
case *bufio.Writer:
bufw := v
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
for k, v := range m {
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
if err = xml.EscapeText(bufw, []byte(v)); err != nil {
return
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
return bufw.Flush()
default:
bufw := bufio.NewWriterSize(w, 256)
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
for k, v := range m {
if err = bufw.WriteByte('<'); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
if err = xml.EscapeText(bufw, []byte(v)); err != nil {
return
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(k); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
}
if _, err = bufw.WriteString("</"); err != nil {
return
}
if _, err = bufw.WriteString(rootname); err != nil {
return
}
if err = bufw.WriteByte('>'); err != nil {
return
}
return bufw.Flush()
}
}