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

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


30秒到达战场
浏览 127回答 2
2回答

幕布斯6054654

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

烙印99

我可以想到几种方法可以实现这一点:您可以尝试已经描述的方法,使用包含所有可能属性的结构。这会很乏味但很容易。您还可以尝试为以下内容编写自定义解组器Packet:type PacketXML struct {&nbsp; &nbsp;A *PacketTypeA&nbsp; &nbsp;B *PacketTypeB&nbsp; &nbsp;...}func (x *PacketXML)&nbsp; UnmarshalXML(d *Decoder, start StartElement) error {&nbsp; &nbsp; // Look at start attributes, find out what type of packet it has&nbsp; &nbsp; packetType:=findAttr(start,"type")&nbsp; &nbsp; switch packetType {&nbsp; &nbsp; &nbsp; case "typeA":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x.A=&PacketTypeA{}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return d.Decode(x.A)&nbsp; &nbsp; &nbsp; case "typeB":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x.B=&PacketTypeB{}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return d.Decode(x.B)&nbsp; &nbsp; &nbsp; ...&nbsp; &nbsp; }&nbsp; return nil}一切完成后,您可以检查PacketXML实例的哪些元素是非空的,并使用它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go