使用全局命名空间解组

时间:2014-04-11 04:26:49

标签: go unmarshalling

我有以下XML:

<rss version="2.0">
  <channel>
    ...
    <item>
      <link>http://stackoverflow.com</link>
      <atom:link xmlns:atom="http://www.w3.org/2005/Atom" href="http://stackoverflow.com"/>
      ...
    </item>
  </channel>
</rss>

我想提取link属性,我有以下结构:

type Item struct {
  Link string `xml:"http://www.w3.org/2005/Atom link"`
}

我知道,我需要一个前缀来获取链接,但因为没有给出命名空间(以xmls - 属性的形式,但我不知道,如何。

当然,我可以将所有:*link - 属性保存到切片中,但我确信有更好的解决方案。

提前致谢!

1 个答案:

答案 0 :(得分:1)

标准库encoding/xml包中的命名空间处理似乎是一个很大的临时性,并且具有相同名称的不同命名空间中的元素似乎是一个触发器。

理想情况下,您可以将给定的XML解码为以下结构:

type Rss struct {
    Items []Item `xml:"channel>item"`
}

type Item struct {
    Link     string   `xml:"link"`
    AtomLink AtomLink `xml:"http://www.w3.org/2005/Atom link"`
}

type AtomLink struct {
    Href string `xml:"href,attr"`
}

但这会导致错误main.Item field "Link" with tag "link" conflicts with field "AtomLink" with tag "http://www.w3.org/2005/Atom link"(如http://play.golang.org/p/LgW-vm4euL所示)。

但是,如果我们通过注释掉<atom:link>字段来决定忽略Item.AtomLink元素,那么我们最终会解码一个空字符串,因为xml:"link"匹配<link>任何命名空间中的元素,而不仅仅是空命名空间。最终的<atom:link>元素为空,因此不会返回任何内容。

一些可能的解决方法包括:

  1. 仅尝试解码<atom:link>元素,因为它可以唯一选择。如果您还处理没有Atom命名空间元素的RSS源,这可能没用。

  2. 通过修改要使用的<link>结构来收集所有Item元素的内容:

    Links []string `xml:"link"`
    

    然后丢弃切片中的任何空字符串。

  3. 在一天结束时,程序包需要某种方式来引用空白名称空间。这可能需要新的语法,以保持现有程序正常运行。