猿问

如何在 GO 中解组动态 XML

我尝试使用 Go 解析 XML,它用于与另一个系统交换数据。我知道原则上如何使用 xml.Unmarshal 函数进行解析。但是,在协议中,根元素的子元素<PROTO>有所不同(请参见下面的示例)。对于子元素(REQUEST.DATA、REQUEST.ACL、REQUEST.NAC、 ... - 超过二十种不同的),xml:...到目前为止我已经使用 -syntax 定义了结构 - 这些单个子元素的解析有效。


但是,是否有一种好方法将整个消息解析为结构,其中一个变量类型取决于子元素?例如使用接口?


可能的 XML 消息示例:


<PROTO

   version="1.00">

  <REQUEST.DATA>

    <DATA-L>Some information</DATA-L>

  </REQUEST.DATA>

</PROTO>

<PROTO

   version="1.00">

  <REQUEST.ACK>

    <ACK-ID>1</ACK-ID>

  <REQUEST.ACK>

</PROTO>

我的 Go 应用程序的片段:


// XML: REQUEST.DATA

type DataRequest struct {

    LData string `xml:"DATA-L"`

}


// XML: REQUEST.ACK

type AckRequest struct {

    AckId int `xml:"ACK-ID"`

}


// XML: PROTO  <============= ??

type Request struct {

    Version float32  `xml:"version,attr"`

    RemoteRequest {AckRequest, DataRequest, ...} ????

}


func main() {

    message := `<PROTO version="1.00"><REQUEST.ACK><ACK-ID>1</ACK-ID><REQUEST.ACK></PROTO>`

    data := `<REQUEST.ACK><ACK-ID>1</ACK-ID><REQUEST.ACK>`

    doc := &AckRequest{}

    err := xml.Unmarshal([]byte(data), &doc)

    if err != nil {

        fmt.Printf("error: %v", err)

        return

    }

    fmt.Printf("data %+v", doc)

}

我不想只解析子元素,而是data想解析整个文档message(<PROTO>涉及)。并且想要有一个包含各个子元素信息的结构。


慕容3067478
浏览 144回答 1
1回答

千巷猫影

您可以将DataRequest和AckRequest作为指针嵌入到Request结构中。这样您可以稍后检查它们是否存在nil。// XML: REQUEST.DATAtype DataRequest struct {&nbsp; &nbsp; LData string `xml:"DATA-L"`}// XML: REQUEST.ACKtype AckRequest struct {&nbsp; &nbsp; AckId int `xml:"ACK-ID"`}type Request struct {&nbsp; &nbsp; Version float32&nbsp; &nbsp; &nbsp; `xml:"version,attr"`&nbsp; &nbsp; Ack&nbsp; &nbsp; &nbsp;*AckRequest&nbsp; `xml:"REQUEST.ACK"`&nbsp; &nbsp; Data&nbsp; &nbsp; *DataRequest `xml:"REQUEST.DATA"`}func main() {&nbsp; &nbsp; message := `<PROTO version="1.00"><REQUEST.ACK><ACK-ID>1</ACK-ID></REQUEST.ACK></PROTO>`&nbsp; &nbsp; proto := &Request{}&nbsp; &nbsp; err := xml.Unmarshal([]byte(message), &proto)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("error: %v", err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // if proto.Ack == nil {&nbsp; &nbsp; //&nbsp; &nbsp;fmt.Println("Ack is nil")&nbsp; &nbsp; // }&nbsp; &nbsp; fmt.Printf("data %+v\n", proto)&nbsp; &nbsp; fmt.Printf("data %+v\n", proto.Ack)}数据&{版本:1 确认:0xc0000b6050 数据:}数据 &{AckId:1}
随时随地看视频慕课网APP

相关分类

Go
我要回答