如何从联机xml文件解组xml数据

时间:2017-01-24 06:05:38

标签: xml go

假设https://www.notre-shop.com/sitemap_products_1.xml我有一个xml文件,我想在我的go代码中解组这个xml所以我这样做了

package main

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

var Product struct {
    Locs []string `xml:"url>loc"`
    Name []string `xml:"url>image:title"`
}

func main() {
    res, err := http.Get("https://www.notre-shop.com/sitemap_products_1.xml")
    if err!=nil{
        log.Fatal(err)
    }

    data, err := ioutil.ReadAll(res.Body)
    if err!=nil{
        log.Fatal(err)
    }
    defer res.Body.Close()

    err = xml.Unmarshal(data, &Product)
    if err!=nil{
        log.Fatal(err)
    }
    for x, _ := range Product.Name {
        fmt.Println(Product.Name[x], Product.Locs[x])
    }
}

但这不会打印任何东西。我做错了什么?

以下是正在播放的完整代码https://play.golang.org/p/pZ6j4-lSEz

2 个答案:

答案 0 :(得分:3)

请尝试以下适用于我的代码(注意:您也可以像以前一样使用ioutil.ReadAllxml.Unmarshal,而不是xml.Decode):

package main

import (
    "encoding/xml"
    "fmt"
    "log"
    "net/http"
)

// <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
//    <url>
//        <loc>
//            https://www.notre-shop.com/products/test-product-releasing-soon-2
//        </loc>
//        <lastmod>2017-01-17T08:04:44Z</lastmod>
//        <changefreq>daily</changefreq>
//        <image:image>
//            <image:loc>
//                https://cdn.shopify.com/s/files/1/0624/0605/products/NOTRE-CHICAGO-QK9C9548_fde37b05-495e-47b0-8dd1-b053c9ed3545.jpg?v=1481853712
//            </image:loc>
//            <image:title>Test Product Releasing Soon 2</image:title>
//        </image:image>
//    </url>
// </urlset>
type URLSet struct {
    XMLName string `xml:"urlset"`

    URLs []URL `xml:"url"`
}

type URL struct {
    Loc   string `xml:"loc"`
    Image Image  `xml:"image"`
}

type Image struct {
    Title string `xml:"title"`
}

func main() {
    resp, err := http.Get("https://www.notre-shop.com/sitemap_products_1.xml")
    if err != nil {
        log.Fatalln(err) // log.Fatal always exits the program, need to check err != nil first
    }
    defer resp.Body.Close()

    var urlSet URLSet
    if err = xml.NewDecoder(resp.Body).Decode(&urlSet); err != nil {
        log.Fatalln(err)
    }

    for _, url := range urlSet.URLs {
        fmt.Println(url.Loc, url.Image.Title)
    }
}

答案 1 :(得分:0)

这就是XML规范所说的

 The Namespaces in XML Recommendation [XML Names] assigns a meaning 
 to names containing colon characters. Therefore, authors should not 
 use the colon in XML names except for namespace purposes, but XML 
 processors must accept the colon as a name character.

这是XML命名空间建议书

  

XML命名空间建议书表达了一个通用名称   与XML 1.0兼容的间接方式。实际上是XML   命名空间建议书定义了从XML 1.0树到其中的映射   元素类型名称和属性名称是树中的本地名称   其中元素类型名称和属性名称可以是通用名称。   映射基于前缀的概念。如果是元素类型名称   或属性名称包含冒号,然后映射处理该部分   冒号前面的名称作为前缀,以及名称的一部分   冒号后作为本地名称。前缀foo是指URI   在xmlns:foo属性的值中指定。

你可能不会使用带冒号(:)的名称来获取内部元素而不是你可以避免修复,这里是你的代码重写

对于性能/内存注意事项,因为您获得io.Reader,可以使用xml.Decoder而不是xml.Unmarshal。

package main

import (
    "encoding/xml"
    "fmt"
    "log"
    "net/http"
)

var Product struct {
    Locs []string `xml:"url>loc"`
    Name []Image  `xml:"url>image"`
}

type Image struct {
    Title string `xml:"title"`
}

func main() {
    res, err := http.Get("https://www.notre-shop.com/sitemap_products_1.xml")
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()
    decoder := xml.NewDecoder(res.Body)
    err = decoder.Decode(&Product)
    if err != nil {
        log.Fatal(err)
    }
    for x, _ := range Product.Name {
        fmt.Println(Product.Name[x].Title, Product.Locs[x])
    }
}

这是播放链接play