英文:
How to let golang distinguish XML elements with and without namespaces?
问题
假设我有以下的XML数据:
<image>
<url>http://sampleUrl.com</url>
</image>
<itunes:image url="http://sampleItunesUrl.com" /> //xmlData
我使用以下结构体对其进行解码:
type Response struct {
XMLName xml.Name `xml:"resp"`
Image []struct {
URL string `xml:"url"`
} `xml:"image"`
ItunesImage struct {
URL string `xml:"url,attr"`
} `xml:"http://www.itunes.com/dtds/podcast-1.0.dtd image"`
}
我有如下代码:
var resp Response
err := xml.Unmarshal([]byte(xmlData), &resp)
if err != nil {
fmt.Printf("Error decoding XML: %s\n", err)
return
}
for _, img := range resp.Image{
if img.URL != "" {
//<image>,而不是<itunes:image>
}
}
来处理解码。
我遇到的问题是,Image []struct
似乎将<image>
和<itunes:image>
都视为<image>
元素,因为它们都有"image"。为了过滤掉<itunes:image>
,我使用的方法是让Image []struct
中的每个元素检查它们的url
是否为空字符串(因为对于<itunes:image>
,它的url
是属性)。
另一种方法是编写自己的Unmarshal
函数来区分带有和不带有itunes
命名空间的XML元素。基本上,我希望Image []struct
只包含<image>
元素。
我想知道Go语言是否有一些内置的功能可以区分它们?还是我必须编写代码来过滤掉<itunes:image>
?
英文:
suppose I have the following XML data:
<image>
<url> http://sampleUrl.com
</url>
</image>
<itunes:image url="http://sampleItunesUrl.com" /> //xmlData
I use this struct to decode it:
type Response struct {
XMLName xml.Name `xml:"resp"`
Image []struct {
URL string `xml:"url"`
} `xml:"image"`
ItunesImage struct {
URL string `xml:"url,attr"`
} `xml:"http://www.itunes.com/dtds/podcast-1.0.dtd image"`
}
and I have codes like:
var resp Response
err := xml.Unmarshal([]byte(xmlData), &resp)
if err != nil {
fmt.Printf("Error decoding XML: %s\n", err)
return
}
for _, img := range resp.Image{
if img.URL != "" {
//<image>, not <itunes:image>
}
}
to process decoding
The problem I am having is that looks like Image []struct
considers both <image>
and <itunes:image
to be <image>
element, since they both have "image". To filter out <itunes:image
, the approach I am using is to let each one in Image []struct
examine if their url
are empty strings (because for <itunes:image
its url
is attribute).
Another approach is to write my own Unmarshal
function to distinguish between XML elements with and without itunes
namespace. Basically I want Image []struct
to only hold elements <image>
I am wondering if go has some built-in functionalities to distinguish? Or I have to write my codes to filter out <itunes:image>
?
答案1
得分: 2
请注意,字段的顺序很重要。ItunesImage
具有更具体的标签,因此应该在Image
之前。
package main
import (
"encoding/xml"
"fmt"
)
func main() {
type Response struct {
XMLName xml.Name `xml:"resp"`
ItunesImage struct {
URL string `xml:"url,attr"`
} `xml:"http://www.itunes.com/dtds/podcast-1.0.dtd image"`
Image []struct {
URL string `xml:"url"`
} `xml:"image"`
}
xmlData := `
<resp xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<image>
<url>http://sampleUrl.com</url>
</image>
<itunes:image url="http://sampleItunesUrl.com/" />
</resp>
`
var resp Response
err := xml.Unmarshal([]byte(xmlData), &resp)
if err != nil {
fmt.Printf("解码XML时出错:%s\n", err)
return
}
fmt.Printf("ItunesImage:%v\n", resp.ItunesImage)
fmt.Printf("Images:%v\n", resp.Image)
}
如果你只需要从<image>
标签中获取image/url
,你可以像这样定义Response
结构体:
type Response struct {
XMLName xml.Name `xml:"resp"`
Image []string `xml:"image>url"`
}
关于标题中的一般问题(如何让golang区分带有命名空间和不带命名空间的XML元素),你可以使用名为XMLName
的字段捕获元素名称,并检查该字段的Space
成员。请参考下面的示例:
package main
import (
"encoding/xml"
"fmt"
)
func main() {
type Response struct {
XMLName xml.Name `xml:"resp"`
Image []struct {
XMLName xml.Name
URL string `xml:"url"`
} `xml:"image"`
}
xmlData := `
<resp xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<image>
<url>http://sampleUrl.com</url>
</image>
<itunes:image>
<url>http://sampleItunesUrl.com/</url>
</itunes:image>
</resp>
`
var resp Response
err := xml.Unmarshal([]byte(xmlData), &resp)
if err != nil {
fmt.Printf("解码XML时出错:%s\n", err)
return
}
for _, img := range resp.Image {
fmt.Printf("命名空间:%q, URL:%s\n", img.XMLName.Space, img.URL)
}
}
上述示例的输出结果为:
命名空间:"", URL:http://sampleUrl.com
命名空间:"http://www.itunes.com/dtds/podcast-1.0.dtd", URL:http://sampleItunesUrl.com/
英文:
Please note that the field order matters. ItunesImage
has a more specific tag, so it should go before Image
.
package main
import (
"encoding/xml"
"fmt"
)
func main() {
type Response struct {
XMLName xml.Name `xml:"resp"`
ItunesImage struct {
URL string `xml:"url,attr"`
} `xml:"http://www.itunes.com/dtds/podcast-1.0.dtd image"`
Image []struct {
URL string `xml:"url"`
} `xml:"image"`
}
xmlData := `
<resp xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<image>
<url>http://sampleUrl.com</url>
</image>
<itunes:image url="http://sampleItunesUrl.com/" />
</resp>
`
var resp Response
err := xml.Unmarshal([]byte(xmlData), &resp)
if err != nil {
fmt.Printf("Error decoding XML: %s\n", err)
return
}
fmt.Printf("ItunesImage: %v\n", resp.ItunesImage)
fmt.Printf("Images: %v\n", resp.Image)
}
And if you only need image/url
from the <image>
tag, you could define the Response
struct like this:
type Response struct {
XMLName xml.Name `xml:"resp"`
Image []string `xml:"image>url"`
}
Regarding the general question in the title (How to let golang distinguish XML elements with and without namespaces?), you can capture the element name with a field named XMLName
and examine the Space
member of this field. See the demo below:
package main
import (
"encoding/xml"
"fmt"
)
func main() {
type Response struct {
XMLName xml.Name `xml:"resp"`
Image []struct {
XMLName xml.Name
URL string `xml:"url"`
} `xml:"image"`
}
xmlData := `
<resp xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<image>
<url>http://sampleUrl.com</url>
</image>
<itunes:image>
<url>http://sampleItunesUrl.com/</url>
</itunes:image>
</resp>
`
var resp Response
err := xml.Unmarshal([]byte(xmlData), &resp)
if err != nil {
fmt.Printf("Error decoding XML: %s\n", err)
return
}
for _, img := range resp.Image {
fmt.Printf("namespace: %q, url: %s\n", img.XMLName.Space, img.URL)
}
}
The output of the above demo is:
namespace: "", url: http://sampleUrl.com
namespace: "http://www.itunes.com/dtds/podcast-1.0.dtd", url: http://sampleItunesUrl.com/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论