英文:
How to skip elements when unmarshalling?
问题
如何在解组 XML 时删除 <Text Language="de">...</Text>
(如下所示)?
我尝试使用 UnmarshalXML
方法跳过元素,但是这样做会跳过整个元素。
package main
import (
"encoding/xml"
"fmt"
)
type Root struct {
Translation []Text `xml:"Texts>Text>Text"`
}
type Text struct {
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}
func main() {
foo := `
<Root>
<Texts>
<Text>
<Text Language="EN">
<Value>One</Value>
</Text>
<Text Language="de">
<Value>Eins</Value>
</Text>
</Text>
</Texts>
</Root>
`
var root Root
e := xml.Unmarshal([]byte(foo), &root)
if e != nil {
panic(e)
}
fmt.Printf("%+v\n", root)
}
func (t *Text) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
tx := struct{ Language, Value string }{}
if start.Attr[0].Value == "EN" {
d.DecodeElement(&tx, &start)
// 在这里无法获取 Language 属性
*t = Text{tx.Language, tx.Value}
// fmt.Printf("hey: %+v %s\n", tx, start.Attr[0].Value)
} else {
// 它输出了带有空字段的 DE 元素
d.Skip()
}
return nil
}
当前输出:
{Translation:[{Language: Value:One} {Language: Value:}]}
我想要的输出:
{Translation:[{Language:EN Value:One}]}
英文:
How can I remove <Text Language="de">...</Text>
(as shown below) when unmarshaling XML?
I tried to skip the element with UnmarshalXML
method, however, it's skipping the whole element when I do that.
package main
import (
"encoding/xml"
"fmt"
)
type Root struct {
Translation []Text `xml:"Texts>Text>Text"`
}
type Text struct {
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}
func main() {
foo := `
<Root>
<Texts>
<Text>
<Text Language="EN">
<Value>One</Value>
</Text>
<Text Language="de">
<Value>Eins</Value>
</Text>
</Text>
</Texts>
</Root>
`
var root Root
e := xml.Unmarshal([]byte(foo), &root)
if e != nil {
panic(e)
}
fmt.Printf("%+v\n", root)
}
func (t *Text) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
tx := struct{ Language, Value string }{}
if start.Attr[0].Value == "EN" {
d.DecodeElement(&tx, &start)
// I couldn't got Language attr here
*t = Text{tx.Language, tx.Value}
// fmt.Printf("hey: %+v %s\n", tx, start.Attr[0].Value)
} else {
// It outputs DE element with empty fields
d.Skip()
}
return nil
}
Current Output:
{Translation:[{Language: Value:One} {Language: Value:}]}
What I Want:
{Translation:[{Language:EN Value:One}]}
答案1
得分: 2
你的代码中存在问题,导致第二个元素为空。你可以尝试以下修改:
package main
import (
"encoding/xml"
"fmt"
)
type Root struct {
Translation Text `xml:"Texts>Text>Text"`
}
type Text []struct {
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}
func main() {
foo := `
<Root>
<Texts>
<Text>
<Text Language="EN">
<Value>One</Value>
</Text>
<Text Language="de">
<Value>Eins</Value>
</Text>
</Text>
</Texts>
</Root>
`
var root Root
e := xml.Unmarshal([]byte(foo), &root)
if e != nil {
panic(e)
}
fmt.Printf("%+v\n", root)
}
func (t *Text) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
tx := []struct {
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}{}
d.DecodeElement(&tx, &start)
tSl := *t
for _, elem := range tx {
switch elem.Language {
case "EN":
tSl = append(tSl, struct {
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}{elem.Language, elem.Value})
default:
d.Skip()
}
}
*t = tSl
return nil
}
输出结果应为:
{Translation:[{Language:EN Value:One}]}
英文:
You're operating too low by unmarshalling at the Text Level - you're still Unmarshalling 2 Texts elements which is why you are seeing an empty second element. You could try something like this:
package main
import (
"encoding/xml"
"fmt"
)
type Root struct {
Translation Text `xml:"Texts>Text>Text"`
}
type Text []struct {
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}
func main() {
foo := `
<Root>
<Texts>
<Text>
<Text Language="EN">
<Value>One</Value>
</Text>
<Text Language="de">
<Value>Eins</Value>
</Text>
</Text>
</Texts>
</Root>
`
var root Root
e := xml.Unmarshal([]byte(foo), &root)
if e != nil {
panic(e)
}
fmt.Printf("%+v\n", root)
}
func (t *Text) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
tx := []struct{
Language string `xml:"Language,attr"`
Value string `xml:"Value"`
}{}
d.DecodeElement(&tx, &start)
tSl := *t
for _, elem := range tx {
switch elem.Language {
case "EN":
tSl = append(tSl, struct{
Language string `xml:"Language,attr"`
Value string `xml:"Value"`}{elem.Language, elem.Value})
default:
d.Skip()
}
}
*t = tSl
return nil
}
Output:
{Translation:[{Language:EN Value:One}]}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论