go语言xml处理

/ go / 没有评论 / 1591浏览

go语言xml处理

XML解析

设置要解析的对象

设置要解析的xml文件对象

type Result struct {
    XMLName xml.Name `xml:"persons"`//标签上的标签名
    Persons []Person `xml:"person"`
}
type Person struct {
    Name string `xml:"name,attr"`//persion标签属性名为name的属性值
    Age int `xml:"age,attr"`
    Career string `xml:"career"`//persion中标签名为career的值
    Interests []string `xml:"interests>interest"`//标签interests下的interest数组
    //不写>当子标签为一个的时候回把它当做对象解析
}

对应的xml文件
<?xml version="1.0" encoding="UTF-8"?>
<persons>
    <person name="polaris" age="28">
        <career>无业游民</career>
        <interests>
            <interest>编程</interest>
            <interest>下棋</interest>
        </interests>
    </person>
    <person name="studygolang" age="27">
        <career>码农</career>
        <interests>
            <interest>编程</interest>
            <interest>下棋</interest>
        </interests>
    </person>
</persons>

XML字符串读取

方法一:转对象
input := `<Person><FirstName>Xu</FirstName><LastName>Xinhua</LastName></Person>`
err := xml.Unmarshal([]byte(input), &v)//将文件转化成对象
方法二:遍历
package main

import (
    "encoding/xml"
    "strings"
    "fmt"
)

func main() {
    var t xml.Token
    var err error

    input := `<Person><FirstName>Xu</FirstName><LastName>Xinhua</LastName></Person>`
    inputReader := strings.NewReader(input)

    // 从文件读取,如可以如下:
    // content, err := ioutil.ReadFile("studygolang.xml")
    // decoder := xml.NewDecoder(bytes.NewBuffer(content))

    decoder := xml.NewDecoder(inputReader)
    for t, err = decoder.Token(); err == nil; t, err = decoder.Token() {
        switch token := t.(type) {
        // 处理元素开始(标签)
        case xml.StartElement:
            name := token.Name.Local
            fmt.Printf("Token name: %s\n", name)
            for _, attr := range token.Attr {
                attrName := attr.Name.Local
                attrValue := attr.Value
                fmt.Printf("An attribute is: %s %s\n", attrName, attrValue)
            }
        // 处理元素结束(标签)
        case xml.EndElement:
            fmt.Printf("Token of '%s' end\n", token.Name.Local)
        // 处理字符数据(这里就是元素的文本)
        case xml.CharData:
            content := string([]byte(token))
            fmt.Printf("This is the content: %v\n", content)
        default:
            // ...
        }
    }
}

XML文件读取

//从文件读取,如可以如下:
content, err := ioutil.ReadFile("studygolang.xml")
decoder := xml.NewDecoder(bytes.NewBuffer(content))
xml.Unmarshal(content, &result)//将文件转化成对象

生成xml

对象转换为xml

package main

import (
    "encoding/xml"
    "fmt"
    // "os"
)

type Servers struct {
    XMLName xml.Name `xml:"servers"`
    Version string   `xml:"version,attr"`
    Svs     []server `xml:"server"`
}

type server struct {
    ServerName string `xml:"serverName"`
    ServerIP   string `xml:"serverIP"`
}

func main() {
    v := &Servers{Version: "1"}
    v.Svs = append(v.Svs, server{"Shanghai_VPN", "127.0.0.1"})
    v.Svs = append(v.Svs, server{"Beijing_VPN", "127.0.0.2"})
    output, err := xml.MarshalIndent(v, "  ", "    ")
    if err != nil {
        fmt.Printf("error: %v\n", err)
    }
    // os.Stdout.Write([]byte(xml.Header))

    // os.Stdout.Write(output)
    //将字节流转换成string输出
    fmt.Println("<?xml version="1.0" encoding="UTF-8"?>\n"+string(output))
}

map与XML相互转换(只能解决简单的的xml)

package main

import (
    "encoding/xml"
    "fmt"
    "io"
)

type Map map[string]string

type xmlMapEntry struct {
    XMLName xml.Name
    Value   string `xml:",chardata"`
}

// MarshalXML marshals the map to XML, with each key in the map being a
// tag and it's corresponding value being it's contents.
func (m Map) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    if len(m) == 0 {
        return nil
    }

    err := e.EncodeToken(start)
    if err != nil {
        return err
    }

    for k, v := range m {
        e.Encode(xmlMapEntry{XMLName: xml.Name{Local: k}, Value: v})
    }

    return e.EncodeToken(start.End())
}

// UnmarshalXML unmarshals the XML into a map of string to strings,
// creating a key in the map for each tag and setting it's value to the
// tags contents.
//
// The fact this function is on the pointer of Map is important, so that
// if m is nil it can be initialized, which is often the case if m is
// nested in another xml structurel. This is also why the first thing done
// on the first line is initialize it.
func (m *Map) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    *m = Map{}
    for {
        var e xmlMapEntry

        err := d.Decode(&e)
        if err == io.EOF {
            break
        } else if err != nil {
            return err
        }

        (*m)[e.XMLName.Local] = e.Value
    }
    return nil
}

func main() {
    // The Map
    m := map[string]string{
        "key_1": "Value One",
        "key_2": "Value Two",
    }
    fmt.Println(m)

    // Encode to XML
    x, _ := xml.MarshalIndent(Map(m), "", "  ")
    fmt.Println(string(x))

    // Decode back from XML
    var rm map[string]string
    xml.Unmarshal(x, (*Map)(&rm))
    fmt.Println(rm)
}