首页 文章

Golang将XML属性解组为接口

提问于
浏览
1

我正在尝试将一些XML解组为具有接口{}类型的结构 . 但是每当我尝试运行它时,代码根本不会提取任何东西 . 所有其他元素似乎工作正常,如果我将类型设置为字符串或[]字节它将工作,但我需要它比这更灵活 .

我感兴趣的元素是 line 32 - FloorRefID

https://play.golang.org/p/Ehr8qx1aWf

<?xml version="1.0" encoding="UTF-8"?>
    <Locations totalPages="1" currentPage="1" pageSize="25">
       <WirelessClientLocation macAddress="00:00:00:00:00:00">
          <MapInfo mapHierarchyString="Head office&gt;Ground floor&gt;Store" floorRefId="-1122334455667789">
             <Image imageName="floorPlan1.png" />
          </MapInfo>
          <MapCoordinate x="2850" y="3000" unit="FEET" />
       </WirelessClientLocation>
       <WirelessClientLocation macAddress="11:11:11:11:11:11">
          <MapInfo mapHierarchyString="Head office&gt;Ground floor&gt;Store" floorRefId="-1122334455667789">
            <Image imageName="floorPlan1.png" />
          </MapInfo>
          <MapCoordinate x="10.72" y="76.49" unit="FEET" />
       </WirelessClientLocation>
       <WirelessClientLocation macAddress="26:cd:96:46:0b:2b">
          <MapInfo floorRefId="0" />
          <MapCoordinate x="51.52" y="4.2" unit="FEET" />
       </WirelessClientLocation>
    </Locations>

给出一些背景;我正在开发一个与供应商集成的项目,有时我们会以XML格式接收数据,有时也会以JSON格式接收数据 . 我想构建一些可以解组两者结构的东西,而不是复制结构集 . 它有许多子结构,这意味着除了这一个属性之外,保留两个几乎相同的结构需要做更多的工作 .

当我们收到JSON数据时,该字段可以作为字符串或数字给出 .

我已经读过你不能解组到一个界面,但有没有人知道我的方案解决这个问题的方法?

1 回答

  • 2

    始终检查返回的错误很重要 .

    if err := xml.Unmarshal([]byte(xmlRawData), &xmlData); err != nil {
        fmt.Println(err)
    }
    

    你得到的错误是

    cannot unmarshal into interface {}
    

    空接口无法解组,因为空接口没有任何导出字段来映射xml键/值 .

    但是有办法绕行 . 在 VendorMapInfo 结构上实现xml.Unmarshaler接口 .

    示例:您更新的代码

    type VendorMapInfo struct {
        MapHierarchyString string      `xml:"mapHierarchyString,attr"`
        FloorRefID         interface{} `xml:"floorRefId,attr"`
        Image              Image       `xml:"Image"`
        FloorDimension     VendorFloorDimension
    }
    
    type Image struct {
        Name string `xml:"imageName,attr"`
    }
    
    func (mf *VendorMapInfo) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
        // Attributes
        for _, attr := range start.Attr {
            switch attr.Name.Local {
            case "mapHierarchyString":
                mf.MapHierarchyString = attr.Value
            case "floorRefId":
                mf.FloorRefID = findFloorRefIDType(attr.Value)
            }
        }
    
        for {
            token, err := d.Token()
            if err != nil {
                return err
            }
    
            switch el := token.(type) {
            case xml.StartElement:
                if el.Name.Local == "Image" {
                    item := new(Image)
                    if err = d.DecodeElement(item, &el); err != nil {
                        return err
                    }
                    mf.Image = *item
                }
            case xml.EndElement:
                if el == start.End() {
                    return nil
                }
            }
        }
    
        return nil
    }
    

    完整代码,播放链接:https://play.golang.org/p/wZQOsQv0Nq

    输出:

    {Locations:{Space: Local:} WirelessClientLocation:[{MacAddress:00:00:00:00:00:00 MapInfo:{MapHierarchyString:Head office>Ground floor>Store FloorRefID:-1122334455667789 Image:{Name:floorPlan1.png} FloorDimension:{Length:0 Width:0 Height:0 OffsetX:0 OffsetY:0 Unit:}}} {MacAddress:11:11:11:11:11:11 MapInfo:{MapHierarchyString:Head office>Ground floor>Store FloorRefID:-1122334455667789 Image:{Name:floorPlan1.png} FloorDimension:{Length:0 Width:0 Height:0 OffsetX:0 OffsetY:0 Unit:}}} {MacAddress:26:cd:96:46:0b:2b MapInfo:{MapHierarchyString: FloorRefID:0 Image:{Name:} FloorDimension:{Length:0 Width:0 Height:0 OffsetX:0 OffsetY:0 Unit:}}}]}
    

相关问题