在GO

时间:2018-07-31 15:17:53

标签: xml go

我有一个450万行的XML文件,但我想不出一种方法来使用解码器.DecodeElement()函数来解析信息。

XML片段:

<dt
    xmlns:directive="d"
    xmlns:ref="ref">
    <Data>
        <directive:Entry Name='abcd'>
            <list>
                <map>
                    <directive:Entry Name='id'>
                        <Integer>21</Integer>
                    </directive:Entry>
                    <directive:Entry Name='t'>
                        <Date>T14:31:43.823Z</Date>
                    </directive:Entry>
                </map>
            </list>
        </directive:Entry>
    </Data>
</dt>

因此,以上内容构成了XML文件的一行。我的目标是提取“ t”和“ id”。

我当前的尝试涉及创建一个结构:

type DT struct {
    id string `xml:"Data"` // This is my attempt to get the entire Data portion/segment/chunk(?)
}

执行实际解码的代码:

decoder := xml.NewDecoder(readInFile())

for {
    t, _ := decoder.Token()
    if t == nil {
        break
    }

    switch se := t.(type) {
    case xml.StartElement:
        inE := se.Name.Local

        if inE == "dt" {
            var dt DT
            decoder.DecodeElement(&dt, &se)

            fmt.Println(&dt)
        }
    }
}

上面的代码在运行时会输出

&{}

告诉我,没有信息可以解析。当我输出

时也是如此
fmt.Println(&dt.id)

有人可以帮助我吗?我不确定我的输出为空的原因是由于我在结构体中提取的方式还是解码问题。

2 个答案:

答案 0 :(得分:1)

我不建议您使用xml.Unmarshal,而不是使用解码器.decodeElement(),并且为了使xml.Unmarshal能够执行您想要的操作,DT类型的结构必须匹配<dt>元素的结构遵循here中记录的规则。

例如这样的东西:

type DT struct {
    DataEntry struct {
        List []EntryMap `xml:"list"`
    } `xml:"Data>Entry"`
}

type EntryMap struct {
    Entries []Entry `xml:"map>Entry"`
}

type Entry struct {
    Name  string `xml:",attr"`
    Value string `xml:",any"`
}

然后您可以遍历dt.DataEntry.List[N].Entries以获得所需的内容。

https://play.golang.org/p/3XxmYQ4ECza

答案 1 :(得分:0)

我正在使用xmlquery库来解析和提取XML文档中的数据。

package main

import (
"fmt"
"strings"

"github.com/antchfx/xmlquery"
)

func main() {
var s = `<dt
xmlns:directive="d"
xmlns:ref="ref">
<Data>
<directive:Entry Name='abcd'>
<list>
    <map>
            <directive:Entry Name='id'>
                    <Integer>21</Integer>
            </directive:Entry>
            <directive:Entry Name='t'>
                    <Date>T14:31:43.823Z</Date>
            </directive:Entry>
        </map>
    </list>
    </directive:Entry>
</Data>
</dt>`

doc, err := xmlquery.Parse(strings.NewReader(s))
if err != nil {
    panic(err)
}
id := xmlquery.FindOne(doc, "//directive:Entry[@Name='id']/Integer")
fmt.Println(id.InnerText())
t := xmlquery.FindOne(doc, "//directive:Entry[@Name='t']/Date")
fmt.Println(t.InnerText())
}

它非常简单易用。