英文:
How to decode flexible xml in GO?
问题
我有以下的 XML:
...
<solution>
<ContainerBlockElement>
<Paragraph>
<Paragraph>
Foo
</Paragraph>
<Paragraph>
bar
</Paragraph>
</Paragraph>
</ContainerBlockElement>
</solution>
...
我想提取 <Paragraph>
的内容,但问题是:服务器可能会发送给我第二种结构:
...
<solution>
<ContainerBlockElement>
<Paragraph>
baz
</Paragraph>
</ContainerBlockElement>
</solution>
...
我尝试在 Go 中使用以下结构进行解码,但不起作用:
type Blah struct {
...
Solutions []string `xml:"solution>ContainerBlockElement>Paragraph"`
Solutions2Paragraph []string `xml:"solution>ContainerBlockElement>Paragraph>Paragraph"`
}
如何解码这个 XML?
英文:
I have the following xml:
...
<solution>
<ContainerBlockElement>
<Paragraph>
<Paragraph>
Foo
</Paragraph>
<Paragraph>
bar
</Paragraph>
</Paragraph>
</ContainerBlockElement>
</solution>
...
I want to extract the <Paragraph> content but the problem is: The server can send me the second structure:
...
<solution>
<ContainerBlockElement>
<Paragraph>
baz
</Paragraph>
</ContainerBlockElement>
</solution>
...
I've tried to use this struct in go to decode but it doesn't work:
type Blah struct {
...
Solutions []string `xml:"solution>ContainerBlockElement>Paragraph"`
Solutions2Paragraph []string `xml:"solution>ContainerBlockElement>Paragraph>Paragraph"`
}
How can I decode this?
答案1
得分: 4
由于结构不可预测,将其反序列化为结构体是行不通的。相反,最好使用XML解析器的流模式,使用xml.Decoder.Token
按顺序解析元素并根据需要处理它们。
decoder := xml.NewDecoder(xmlFile)
solutions := make([]string,0,0)
for {
t, _ := decoder.Token()
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "Paragraph" {
// 获取段落开始元素之后的下一个标记,即标记内容
innerText,ok := decoder.Token().(xml.CharData)
if !ok {
continue
}
solutions = append(solutions, string(innerText))
}
}
}
这段代码未经测试,但应该提供一个不错的起点。
英文:
With unpredictable structures, deserializing into a struct is not going to work. Instead, you'll be better off using the streaming mode of the XML parser using xml.Decoder.Token
to parse elements in order and handle them as necessary.
decoder := xml.NewDecoder(xmlFile)
solutions := make([]string,0,0)
for {
t, _ := decoder.Token()
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "Paragraph" {
// Get the next token after the Paragraph start element, which will be the tag contents
innerText,ok := decoder.Token().(xml.CharData)
if !ok {
continue
}
solutions = append(solutions, string(innerText))
}
}
}
This code is untested but should provide a decent starting point.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论