通过Go来分析和创建XML

一、分析XML

下面有一个xml文件让你分析。

<?xml version="1.0" encoding="utf-8"?>
<post id="1">
    <content>Hello World!</content>
    <author id="2">Sau She</author>
    <comments>
        <comment id="1">
            <content>Have a great day!</content>
            <author id="3">Adam</author>
        </comment>
        <comment id="2">
            <content>How are you today?</content>
            <author id="4">Betty</author>
        </comment>
    </comments>
</post>

怎么样去分析呢?我们要遵循一下原则。


(1)通过创建一个名为XMLName、类型为xml.Name的字段,可以将XML元素的名字存储在这个字段里面。

(2)通过创建一个与XML元素属性同名的字段,并使用xml:",attr"作为该字段的结构标签,可以将元素的属性的值存储到这个字段里面。

(3)通过创建一个与XML元素相同的字段,并使用xml:",chardata"作为该字段的结构标签,可以将XML元素的字符数据存储到这个字段里面。

(4)通过定义一个任意名字字段,并使用XML:",innerxml"作为该字段的结构标签,可以将XML元素中的原始XML存储到这个字段里面。

(5)没有模式标签(如,attr、,chardata或者,innerxml)的结构字段将与同名的XML元素匹配。

(6)使用xml:"a>b>c"这样的结构标签可以在不指定树桩结构的情况下直接获取指定的XML元素,其中a和b为中间元素,而c则是想要获取的节点元素。


解析代码

package main

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

type Post struct {
    XMLName xml.Name `xml:"post"`
    Id string `xml:"id,attr"`
    Author Author `xml:"author"`
    Xml string `xml:",innerxml"`
    Comments []Comment `xml:"comments>comment"`
}

type Author struct {
    Id  string `xml:"id,attr"`
    Name string `xml:",chardata"`
}

type Comment struct {
    Id string `xml:"id,attr"`
    Content string `xml:"content"`
    Author Author `xml:"author"`
}

func main() {
    file, err := os.Open("src/text/xml/post.xml")
    if err != nil {
        log.Fatalf("Error opening XML file %v",err)
        return
    }
    defer file.Close()
    bytes, err := ioutil.ReadAll(file)
    if err != nil {
        log.Fatalf("Error reading XML file %v",err)
        return
    }
    var post Post
    xml.Unmarshal(bytes,&post)
    fmt.Println(post)
}

上面的这种方法可以很好的处理体积较小的XML文件,但是却无法高效地处理以流方式传输的XML文件以及体积较大的XML文件。为了解决这个问题,我们需要使用Decoder结构来替代Unmarshal函数,通过手动解码XML元素的方式来解封XML数据。

package main

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

type Post struct {
    XMLName xml.Name `xml:"post"`
    Id string `xml:"id,attr"`
    Author Author `xml:"author"`
    Xml string `xml:",innerxml"`
    Comments []Comment `xml:"comments>comment"`
}

type Author struct {
    Id  string `xml:"id,attr"`
    Name string `xml:",chardata"`
}

type Comment struct {
    Id string `xml:"id,attr"`
    Content string `xml:"content"`
    Author Author `xml:"author"`
}

func main() {
    file, err := os.Open("src/text/xml/post.xml")
    if err != nil {
        log.Fatalf("Error opening XML file %v",err)
        return
    }
    defer file.Close()
    decoder := xml.NewDecoder(file)  //根据给定的XML数据生成相应的解码器
    for  {
        t, err := decoder.Token()    //每进行一次迭代,就从解码器获取一个token
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatalf("Error decoding XML into tokens %v",err)
        }
        switch se := t.(type) {      //检查token的类型
        case xml.StartElement:
            if se.Name.Local == "comment" {
                var comment Comment
                decoder.DecodeElement(&comment,&se)   //将XML数据解析至结构
                fmt.Println(comment)
            }
        }
    }
}

二、创建XML

package main

import (
    "encoding/xml"
    "io/ioutil"
    "log"
)

type Post struct {
    XMLName xml.Name `xml:"post"`
    Id string `xml:"id,attr"`
    Content string `xml:"content"`
    Author Author `xml:"author"`
    Xml string `xml:",innerxml"`
    Comments []Comment `xml:"comments>comment"`
}

type Author struct {
    Id  string `xml:"id,attr"`
    Name string `xml:",chardata"`
}

type Comment struct {
    Id string `xml:"id,attr"`
    Content string `xml:"content"`
    Author Author `xml:"author"`
}

func main() {
    post := Post{
        Id:"1",
        Content:"Hello World!",
        Author:Author{
            Id:"2",
            Name:"Sau Sheong",
        },
        Comments: []Comment{{
            Id:"1",
            Content:"i love sz",
            Author:Author{
                Id:"3",
                Name:"zhu",
            },
        }},
    }
    output, err := xml.MarshalIndent(&post,"","\t")   //生成段落式的XML
    if err != nil {
        log.Fatalf("Error marshalling to XML %v",err)
        return
    }
    err = ioutil.WriteFile("post2.xml", []byte(xml.Header+string(output)), 0644)  //添加XML声明
    if err != nil {
        log.Fatalf("Error writing XML to file %v",err)
        return
    }
}

我们可以看一下生成的post2.xml文件中的xml数据

<?xml version="1.0" encoding="UTF-8"?>
<post id="1">
    <content>Hello World!</content>
    <author id="2">Sau Sheong</author>
    <comments>
        <comment id="1">
            <content>i love sz</content>
            <author id="3">zhu</author>
        </comment>
    </comments>
</post>

正如我们可以手动将XML解码到Go结构里面一样,我们同样也可以手动将Go结构编码到XML里面。

package main

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

type Post struct {
    XMLName xml.Name `xml:"post"`
    Id string `xml:"id,attr"`
    Content string `xml:"content"`
    Author Author `xml:"author"`
    Xml string `xml:",innerxml"`
    Comments []Comment `xml:"comments>comment"`
}

type Author struct {
    Id  string `xml:"id,attr"`
    Name string `xml:",chardata"`
}

type Comment struct {
    Id string `xml:"id,attr"`
    Content string `xml:"content"`
    Author Author `xml:"author"`
}

func main() {
    post := Post{
        Id:"1",
        Content:"Hello World!",
        Author:Author{
            Id:"2",
            Name:"Sau Sheong",
        },
        Comments: []Comment{{
            Id:"1",
            Content:"i love sz",
            Author:Author{
                Id:"3",
                Name:"zhu",
            },
        }},
    }
    xmlFile, err := os.Create("post3.xml")
    if err != nil {
        log.Fatalf("Error creating XML File %v",err)
        return
    }
    encoder := xml.NewEncoder(xmlFile)
    encoder.Indent("","\t")
    err = encoder.Encode(&post)
    if err != nil {
        log.Fatalf("Error encoding XML to file %v",err)
        return
    }
}

2 个评论

https://www.onlinetool.io/xmltogo/
We all know that whatsapp is the best messenger app in the world. we often upload breakup whatsapp status video and many other type of status in our whatsapp profile. Here https://downloadstatus.xyz/category/sad/ is a well known site where we can download whatsapp status.

要回复文章请先登录注册