解析动态XML

I understand how to unmarshal simple xml data to Go structs but can't figure out how to handle dynamic tags. Here's an example. There can be <image_3><image_4> etc

<?xml version="1.0" encoding="utf-8"?>
<products>
  <product>
    <product_id>11600</product_id>
    <date_created><![CDATA[2018-10-19 15:20:22]]></date_created>
    <price>200</price>
    <stock_status>In Stock</stock_status>
    <images>
      <image_1>1.jpg</image_1>
      <image_2>2.jpg</image_2>
   </images
   </product>
</products>

//update

type Products struct {
        XMLName xml.Name `xml:"products"`
        Text    string   `xml:",chardata"`
        Product struct {
                Text        string `xml:",chardata"`
                ProductID   string `xml:"product_id"`
                DateCreated string `xml:"date_created"`
                Price       string `xml:"price"`
                StockStatus string `xml:"stock_status"`
                Images          map[string]string `xml:"images"`
        } `xml:"product"`
} 

When I run fmt.Println(len(products.Product[0].Images)) I get 0. What I'm missing here?

dongxibo2095
dongxibo2095 您的建议就像一个魅力。请添加为答案,这样我就可以接受
9 个月之前 回复
dongliu1883
dongliu1883 不幸的是,xml文件是第三方
9 个月之前 回复
dqc3469
dqc3469 此XML是否在您的控制之下?因为动态标记是非常糟糕的做法。
9 个月之前 回复
duankan8739
duankan8739 您可以在自定义地图类型上实现xml.Unmarshaler接口,如下所示:play.golang.com/p/gi9Fiv3PS8M
9 个月之前 回复

2个回答

You can implement the xml.Unmarshaler interface on a custom map type like so:

type Images map[string]string

func (i *Images) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    *i = make(Images) // initialize the map
    for {
        tok, err := d.Token()
        if err != nil {
            if err == io.EOF {
                return nil
            }
            return err
        }

        if se, ok := tok.(xml.StartElement); ok {
            tok, err = d.Token()
            if err != nil {
                if err == io.EOF {
                    return nil
                }
                return err
            }
            if data, ok := tok.(xml.CharData); ok {
                (*i)[se.Name.Local] = string(data)
            }
        }
    }
}

https://play.golang.com/p/gi9Fiv3PS8M

展开翻译

译文



您可以在自定义地图类型上实现xml.Unmarshaler接口,如下所示:</ p>

 < 代码>类型图片map [string] string 

func(i * Images)UnmarshalXML(d * xml.Decoder,start xml.StartElement)错误{

  • i = make(Images)//初始化地图
    {
    tok,err:= d.Token()
    if err!= nil {
    if err == io.EOF {
    return nil
    }
    return err
    }

    if se,ok:= tok。(xml.StartElement); ok {
    tok,err = d.Token()
    如果err!= nil {
    如果err == io.EOF {
    返回nil
    }
    返回err
    }
    如果有数据, 好的:= tok。(xml.CharData); 好的{
    (* i)[se.Name.Local] =字符串(数据)
    }
    }
    }
    }
    </ code> </ pre>

    < a href =“ https://play.golang.com/p/gi9Fiv3PS8M” rel =“ nofollow noreferrer”> https://play.golang.com/p/gi9Fiv3PS8M </ p>
    </ DIV>

You can use this library (https://github.com/clbanning/mxj):

var input = []byte(`<?xml version="1.0" encoding="utf-8"?>
    <products>
        <product>
            <name>hello</name>
            <images>
                <image1>one</image1>
                <image2>one</image2>
            </images>
        </product>
    </products>`)

type Products struct {
    XMLName xml.Name `xml:"products"`
    Products []Product `xml:"product"`
}

type Product struct {
    XMLName xml.Name `xml:"product"`
    Name string `xml:"name"`
    Images map[string]interface{}
}


func (p *Product) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {

    var v struct {
        XMLName xml.Name `xml:"product"`
        Name string `xml:"name"`
        Images struct {
            Inner []byte `xml:",innerxml"`
        } `xml:"images"`
    }

    err := d.DecodeElement(&v, &start)
    if err != nil {
        return err
    }

    images := make(map[string]interface{})
    // use mxj here and fill images from v.Images.Inner

    p.Name = v.Name
    p.Images = images

    return nil
}


func main() {

    var data Products
    err := xml.Unmarshal(input, &data)
    if err != nil {
        panic(err)
    }
}
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐