如何将具有不同命名空间的相同 XML 元素反序列化为结构中的不同元素?

huangapple go评论79阅读模式
英文:

How to deserialize same XML Element with different namespace into different elements in a struct

问题

我正在使用以下类型的XML结构进行工作:

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" 
    xmlns:content="http://purl.org/rss/1.0/modules/content/" 
    xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title>TITLE</title>
        <link>http://something.com</link>
        <description>description</description>
        <lastBuildDate>Mon, 19 Dec 2016 16:48:54 +0000</lastBuildDate>
        <language>en</language>
        <item>
            <title>Title</title>
            <description>description</description>
            <author>
                <name>Name</name>
                <uri></uri>
            </author>
            <pubDate>Mon, 19 Dec 2016 16:42:32 +0000</pubDate>
            <link>http://google.com</link>
            <image>...</image>
            <media:description><![CDATA[Natalie Massenet]]></media:description>
            <media:credit>David Fisher/REX/Shutterstock</media:credit>
            <category>Category1</category>
            <category>Category2</category>
            <guid isPermaLink="false">http://something.com/?p=10730393</guid>
            <media:group></media:group>
            <content:encoded>content</content:encoded>
        </item>
    </channel>
</rss>

我在尝试将<description><media:description>反序列化为结构体中的两个不同元素时遇到了问题。

我尝试了以下类型的结构体来表示<item>,但是media:description的值最终出现在结构体中。

type Item struct {
    // ...其他字段
    Description      string   `xml:"description"`
    MediaDescription string   `xml:"media:description"`
    // ...其他字段
}

有什么最好的方法可以解决这个问题?

英文:

I am working with the following kind of an XML structure

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; 
    xmlns:content=&quot;http://purl.org/rss/1.0/modules/content/&quot; 
    xmlns:media=&quot;http://search.yahoo.com/mrss/&quot;&gt;
    &lt;channel&gt;
        &lt;title&gt;TITLE&lt;/title&gt;
        &lt;link&gt;http://something.com&lt;/link&gt;
        &lt;description&gt;description&lt;/description&gt;
        &lt;lastBuildDate&gt;Mon, 19 Dec 2016 16:48:54 +0000&lt;/lastBuildDate&gt;
        &lt;language&gt;en&lt;/language&gt;
        &lt;item&gt;
            &lt;title&gt;Title&lt;/title&gt;
            &lt;description&gt;description&lt;/description&gt;
            &lt;author&gt;
                &lt;name&gt;Name&lt;/name&gt;
                &lt;uri&gt;&lt;/uri&gt;
            &lt;/author&gt;
            &lt;pubDate&gt;Mon, 19 Dec 2016 16:42:32 +0000&lt;/pubDate&gt;
            &lt;link&gt;http://google.com&lt;/link&gt;
            &lt;image&gt;...&lt;/image&gt;
            &lt;media:description&gt;&lt;![CDATA[Natalie Massenet]]&gt;&lt;/media:description&gt;
            &lt;media:credit&gt;David Fisher/REX/Shutterstock&lt;/media:credit&gt;
            &lt;category&gt;Category1&lt;/category&gt;
            &lt;category&gt;Category2&lt;/category&gt;
            &lt;guid isPermaLink=&quot;false&quot;&gt;http://something.com/?p=10730393&lt;/guid&gt;
            &lt;media:group&gt;&lt;/media:group&gt;
            &lt;content:encoded&gt;content&lt;/content:encoded&gt;
        &lt;/item&gt;
    &lt;/channel&gt;
&lt;/rss&gt;

I am having trouble figuring out how to deserialize &lt;description&gt; and &lt;media:description&gt; into two different element in a struct.

I've tried a following kind of a struct to represent an &lt;item&gt;, but the value of media:description ends up in the struct.

type Item struct {
    // ...other fields
	Description           string   `xml:&quot;description&quot;`
	MediaDescription      string   `xml:&quot;media:description&quot;`
    // ...other fields
}

What would be the best way to do this?

答案1

得分: 0

所以目前Go无法支持这一点(正如@JimB所指出的),但您仍然可以使用一些内置功能来提取正确的元素。首先,定义一个新的结构体XMLElement

type XMLElement struct {
    XMLName xml.Name
    Data    string `xml:",chardata"`
}

这个结构体可以捕获XML数据以及命名空间和元素名称。接下来,将xml:"description"映射到XMLElement数组。这将捕获所有<*:description>元素并存储在列表中。然后,您可以定义函数来提取正确的元素。

type Item struct {
    // ...其他字段
    Descriptions []XMLElement `xml:"description"`
    // ...其他字段
}

// GetDescription返回<description>标签中的描述
func (i *Item) GetDescription() string {
    for _, elem := range i.Descriptions {
        if elem.XMLName.Space == "" {
            return elem.Data
        }
    }
    return ""
}

// GetMediaDescription返回<media:description>标签中的描述
func (i *Item) GetMediaDescription() string {
    for _, elem := range i.Descriptions {
        if elem.XMLName.Space == "http://search.yahoo.com/mrss/" {
            return elem.Data
        }
    }
    return ""
}

以上是代码的翻译部分。

英文:

So Go currently is not able to support this (as pointed out by @JimB), but you can still use some built in capabilities to pull out the right element. Start off by defining a new struct XMLElement

type XMLElement struct {
	XMLName xml.Name
	Data    string `xml:&quot;,chardata&quot;`
}

This struct can capture the xml data along with the namespace and element name. Next map xml:&quot;description&quot; to an array of XMLElement. This will end up capturing all &lt;*:description&gt; elements in a list. You can then define functions to pull out the right one.

type Item struct {
    // ...other fields
    Descriptions           []XMLElement   `xml:&quot;description&quot;`
    // ...other fields
}

// GetDescription returns the description in the &lt;description&gt; tag
func (i *Item) GetDescription() string {
	for _, elem := range i.Descriptions {
		if elem.XMLName.Space == &quot;&quot; {
			return elem.Data
		}
	}
	return &quot;&quot;
}

// GetMediaDescription returns the description in the &lt;media:description&gt; tag
func (i *Item) GetMediaDescription() string {
	for _, elem := range i.Descriptions {
		if elem.XMLName.Space == &quot;http://search.yahoo.com/mrss/&quot; {
			return elem.Data
		}
	}
	return &quot;&quot;
}

huangapple
  • 本文由 发表于 2017年1月5日 06:57:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/41474638.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定