Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解析动态XML_Xml_Parsing_Go_Struct - Fatal编程技术网

解析动态XML

解析动态XML,xml,parsing,go,struct,Xml,Parsing,Go,Struct,我知道如何将简单的xml数据解组为Go结构,但不知道如何处理动态标记。这里有一个例子。可以有等 <?xml version="1.0" encoding="utf-8"?> <products> <product> <product_id>11600</product_id> <date_created><![CDATA[2018-10-19 15:20:22]]></date_crea

我知道如何将简单的xml数据解组为Go结构,但不知道如何处理动态标记。这里有一个例子。可以有

<?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>
当我运行
fmt.Println(len(products.Product[0].Images))
时,我得到0。我缺少什么?

您可以使用此库():

var输入=[]字节(`
你好
一
一
`)
类型产品结构{
XMLName xml.Name`xml:“产品”`
产品[]产品`xml:“产品”`
}
类型产品结构{
XMLName xml.Name`xml:“产品”`
名称字符串`xml:“名称”`
图像映射[字符串]接口{}
}
func(p*Product)解组xml(d*xml.Decoder,start xml.StartElement)错误{
var v结构{
XMLName xml.Name`xml:“产品”`
名称字符串`xml:“名称”`
图像结构{
内部[]字节`xml:,内部xml“`
}`xml:“图像”`
}
错误:=d.DecodeElement(&v,&start)
如果错误!=零{
返回错误
}
图像:=make(映射[字符串]接口{})
//在此处使用mxj并从v.images.Inner填充图像
p、 姓名
p、 图像=图像
归零
}
func main(){
var数据产品
错误:=xml.Unmarshal(输入和数据)
如果错误!=零{
恐慌(错误)
}
}

您可以在自定义映射类型上实现xml.Unmarshaler接口,如下所示:

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)
            }
        }
    }
}

您可以在自定义映射类型上实现xml.Unmarshaler接口,如下所示:此xml在您的控制下吗?因为动态标记是一种非常糟糕的做法party@mkopriva你的建议很有魅力。请将其添加为答案,以便我可以接受
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)
    }
}
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)
            }
        }
    }
}