dqnqpqv3841 2016-09-26 10:47
浏览 45
已采纳

Golang:从net.Conn中读取单个XML文档

I have a client-server connection. They communicate through xml and multiple xml documents are transmitted during one session. xml.Unmarshal wants a slice of bytes, but I can't just ReadAll all bytes from socket (it will try to read more then a single xml and therefore block).

Is there a standard xml parser or a library, that can parse from a stream of bytes and read no more data than it actually needs?

  • 写回答

1条回答 默认 最新

  • duan19750503 2016-09-26 12:05
    关注

    You may use xml.Decoder from the standard library for this purpose. You may use xml.NewDecoder() to create a new xml.Decoder which expects an io.Reader to read the data from. net.Conn qualifies as it implements io.Reader. The Decoder.Decode() method will read and process 1 XML document.

    Let's see an example. The source will contain 2 XML documents concatenated, and we call Decoder.Decode() twice to read and parse those 2 documents.

    The XML source: 2 XML documents (2 <Person>):

    const data = `<Person>
        <Name>Bob</Name>
        <Age>23</Age>
    </Person>
    <Person>
        <Name>Alice</Name>
        <Age>21</Age>
    </Person>
    `
    

    Go struct to model the XML documents:

    type Person struct {
        Name string
        Age  int
    }
    

    Code to read those 2 XML documents:

    buf := bytes.NewBuffer([]byte(data))
    d := xml.NewDecoder(buf)
    
    for i := 0; i < 2; i++ {
        p := Person{}
        if err := d.Decode(&p); err != nil {
            fmt.Println(err)
        } else {
            fmt.Printf("%+v
    ", p)
        }
    }
    

    Output (try it on the Go Playground):

    {Name:Bob Age:23}
    {Name:Alice Age:21}
    

    Note that Decoder.Decode() will return io.EOF if no more data is available. To read all XML documents from the input, you may do it like this:

    for {
        p := Person{}
        if err := d.Decode(&p); err != nil {
            if err == io.EOF {
                fmt.Println("EOF, breaking")
                break
            }
            fmt.Println(err)
        } else {
            fmt.Printf("%+v
    ", p)
        }
    }
    

    Back to your example

    If you want to read XML documents transmitted over a TCP connection, you may simply pass the net.Conn value (which implements io.Reader) to xml.NewDecoder():

    var con net.Conn
    // Initialize / obtain connection
    
    d := xml.NewDecoder(con)
    var doc YourDocType
    if err := d.Decode(&doc); err != nil {
        // Handle error
        return
    }
    // No error, use doc:
    fmt.Printf("%+v", doc)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥15 键盘指令混乱情况下的启动盘系统重装
  • ¥40 复杂的限制性的商函数处理