Как проанализировать XML с вложенными узлами с тем же именем? - PullRequest
0 голосов
/ 29 января 2019

Я новичок в Golang, и синтаксический анализ XML с вложенными узлами с тем же именем слишком сложен для меня.Это XML, извлеченный из стороннего API:

<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time="2019-01-28">
            <Cube currency="USD" rate="1.1418"/>
            <Cube currency="JPY" rate="124.94"/>
            <Cube currency="BGN" rate="1.9558"/>
        </Cube>
        <Cube time="2019-01-25">
            <Cube currency="USD" rate="1.1346"/>
            <Cube currency="JPY" rate="124.72"/>
            <Cube currency="BGN" rate="1.9558"/>
        </Cube>
    </Cube>
</gesmes:Envelope>

Мне нужно разобрать его, поэтому у меня есть вывод, подобный этому:

&{Rates:[{Currency:USD Rate:1.1418 Date:2019-01-28} {Currency:JPY Rate:124.94 Date:2019-01-28} {Currency:BGN Rate:1.9558 Date:2019-01-28} {Currency:USD Rate:1.1346 Date:2019-01-25} {Currency:JPY Rate:124.72 Date:2019-01-25} {Currency:BGN Rate:1.9558 Date:2019-01-25}]}

И вот мой код:

package main

import (
    "encoding/xml"
    "fmt"
)


type Rate struct {
    Currency  string `xml:"currency,attr"`
    Rate      string `xml:"rate,attr"`
    Date    string `xml:"time,attr"`
}

type Rates struct {
    Rates []Rate `xml:"Cube>Cube>Cube"`
}

func main() {
    v := &Rates{}
    if err := xml.Unmarshal([]byte(src), v); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n\n", v)
}

const src = `<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time="2019-01-28">
            <Cube currency="USD" rate="1.1418"/>
            <Cube currency="JPY" rate="124.94"/>
            <Cube currency="BGN" rate="1.9558"/>
        </Cube>
        <Cube time="2019-01-25">
            <Cube currency="USD" rate="1.1346"/>
            <Cube currency="JPY" rate="124.72"/>
            <Cube currency="BGN" rate="1.9558"/>
        </Cube>
    </Cube>
</gesmes:Envelope>`

У меня нет идей, как вставить атрибут time в объект Rates.Любая помощь будет оценена.

Вот она, на Голанге Детская площадка

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Я согласен с ответом mkopriva, но не могу комментировать, поэтому я добавляю ответ.

Убедитесь, что вы либо доверяете XML, либо предварительно проверяете / дезинфицируете его, что-то вроде XSD .Это должно быть сделано как по соображениям безопасности, так и для того, чтобы иметь возможность оглянуться назад и посмотреть, верны ли данные, которые вы «распаковали», потому что, когда вы обрабатываете огромные объемы XML, некоторые из них обязательно будут повреждены.

0 голосов
/ 30 января 2019

Вы можете реализовать пользовательский xml.Unmarshaler для получения желаемых результатов.

type Rate struct {
    Currency string `xml:"currency,attr"`
    Rate     string `xml:"rate,attr"`
    Date     string `xml:"time,attr"`
}

type Rates struct {
    Rates RateList `xml:"Cube>Cube"`
}

type RateList []Rate

func (ls *RateList) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    date := start.Attr[0].Value

    for {
        tok, err := d.Token()
        if err != nil {
            if err == io.EOF {
                return nil
            }
            return err
        }

        if se, ok := tok.(xml.StartElement); ok {
            rate := Rate{Date: date}
            if err := d.DecodeElement(&rate, &se); err != nil {
                return err
            }

            *ls = append(*ls, rate)
        }
    }
}

Go Playground

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...