xml - 如何编码和解码具有不规则属性的 XML

标签 xml go attributes marshalling unmarshalling

我有一个 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。

最佳答案

我可以想到几种方法可以实现这一点:您可以尝试已经描述的方法,使用包含所有可能属性的结构。这会很乏味但很容易。您也可以尝试为 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的哪个元素实例是非空的,并使用它。

关于xml - 如何编码和解码具有不规则属性的 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59717510/

相关文章:

variables - 在 angularjs 的 src 属性中使用 ng-repeat 变量?

php - 可配置产品中的 Magento 属性排序顺序

SQL Server 2008 查询使用参数从 XML 中选择数据

java - 创建 ImageButton 时出现 NullPointerException

go - 覆盖 printf 方法

dynamic - 转到接口(interface) : static vs dynamic binding

json.Marshal 如何处理 http.newRequest 的主体

php - 将 div 位置和大小属性插入 MySQL 数据库。如何使用 PHP 收集信息?

php - 在 tinymce 编辑器中显示时将 css 应用于文本

java - 单击监听器上的单选按钮仅在选择切换按钮后才起作用