dqnqpqv3841
2016-09-26 10:47
浏览 36

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?

图片转代码服务由CSDN问答提供 功能建议

我有一个客户端-服务器连接。 它们通过xml进行通信,并且在一个会话期间传输多个xml文档。 xml.Unmarshal 想要一个字节的切片,但是我不能只是从套接字 ReadAll 读取所有字节(它将尝试读取更多的单个xml,因此会阻塞)。

是否有标准的xml解析器或库,可以从字节流中进行解析并且不读取超出实际需要的数据?

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

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)
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题