为了账号安全,请及时绑定邮箱和手机立即绑定

如何编组和解组具有不规则属性的 XML

如何编组和解组具有不规则属性的 XML

Go
30秒到达战场 2022-05-05 16:08:54
我有一个 XML,其中不同的实体用相同的标签表示但具有不同的属性。像这样的东西:<xml>    <body>        <Packet type="clients">            <Row id="123" name="bill"/>            <Row id="456" name="sasha"/>        </Packet>        <Packet type="orders">            <Row sum="90" status="DONE" />            <Row sum="190" status="DONE" />       </Packet>   </body></xml>保证每种类型只有一个数据包。不幸的是,改变 XML 的结构不是我的责任,我必须照原样处理它。在 Go 中处理这种结构的最佳方法是什么?我是否应该拥有一个具有所有可能属性的结构,并为每个“数据包”填充正确的结构?type XML struct {    XMLName xml.Name `xml:"xml"`    Body    struct {        Packet []struct {            Type string `xml:"type,attr"`            Row  []struct {                ID     string `xml:"id,attr"`                Name   string `xml:"name,attr"`                Sum    string `xml:"sum,attr"`                Status string `xml:"status,attr"`            } `xml:"Row"`        } `xml:"Packet"`    } `xml:"body"`} 这似乎可行,但很不方便,因为实际上我有许多不同类型的数据包,它们具有不同的属性。或者也许有办法将数据包映射到不同的 Go 结构?像这样的东西:type XML struct {    XMLName xml.Name `xml:"xml"`    Body    struct {        ClientPacket struct {            Type string `xml:"type,attr"`            Row  []struct {                ID   string `xml:"id,attr"`                Name string `xml:"name,attr"`            } `xml:"Row"`         } `xml:"Packet"` // ???        OrderPacket struct {            Type string `xml:"type,attr"`            Row  []struct {                Sum   string `xml:"sum,attr"`                Status string `xml:"status,attr"`            } `xml:"Row"`         } `xml:"Packet"` // ???    } `xml:"body"`} 后者似乎更聪明,更易读的例子,但我不明白如何用它来编组和解组 xml。
查看完整描述

2 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

在编组之前先转换文件(例如使用 XSLT)。



查看完整回答
反对 回复 2022-05-05
?
烙印99

TA贡献1829条经验 获得超13个赞

我可以想到几种方法可以实现这一点:您可以尝试已经描述的方法,使用包含所有可能属性的结构。这会很乏味但很容易。您还可以尝试为以下内容编写自定义解组器Packet:


type PacketXML struct {

   A *PacketTypeA

   B *PacketTypeB

   ...

}


func (x *PacketXML)  UnmarshalXML(d *Decoder, start StartElement) error {

    // Look at start attributes, find out what type of packet it has

    packetType:=findAttr(start,"type")

    switch packetType {

      case "typeA":

         x.A=&PacketTypeA{}

         return d.Decode(x.A)

      case "typeB":

         x.B=&PacketTypeB{}

         return d.Decode(x.B)

      ...

    }

  return nil

}

一切完成后,您可以检查PacketXML实例的哪些元素是非空的,并使用它。


查看完整回答
反对 回复 2022-05-05
  • 2 回答
  • 0 关注
  • 126 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信