@Toster100

Go, как парсить XML?

Допустим, есть XML, которфй надо десериализовать
<stream:features>
    <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
    <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
        <mechanism>PLAIN</mechanism>
        <mechanism>DIGEST-MD5</mechanism>
        <mechanism>SCRAM-SHA-1</mechanism>
    </mechanisms>
    <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://www.process-one.net/en/ejabberd/' ver='NUUMEO3rKA30XLGO1FbA9EZT1rY='/>
    <register xmlns='http://jabber.org/features/iq-register'/>
</stream:features>

(как нетрудно догадаться, решил написать в качестве упражнения свою реализацию XMPP-клиента, чтобы разобраться с темой работы с XML в Go).

И, честно говоря, очень много вопросов, но, если кратко, то вообще не понимаю, как это сделать. Допустим, я хочу десериализовать список механизмов, для этого я объевил следующие структуры:
type Mechanism struct {
	XMLName   xml.Name `xml:"mechanism"`
	Mechanism string
}
type Features struct {
	XMLName    xml.Name    `xml:"features"`
	Mechanisms []Mechanism `xml:mechanisms`
}
Скажем так, я и сам понимаю, что это не будет работать и действительно, при попытки унмаршалинга получается nil-структура типа Features.

Как получить содержимое тегов mechanism (оно задается не атрибутами, а просто внутри тега)?
Мне нужно описать всю структуру или можно описывать только те поля, которые меня интересуют?

Еще вопрос: допустим, есть тег < sometag/ >, который работает как флаг. Как можно отразить его наличие/отсутствие в структуре?

Вполне вероятно, что эта тема уже описана где-то, если так, буду рад ссылке с конкретными примерами (можно на eng языке).

И еще вопрос, допустим, у меня может быть два варианта объекта, приходящих в ответ от сервера и я заранее не знаю, какой именно придет, а в xml.Unmarshal надо передать указатель на структуру определенного типа. Как быть в такой ситуации?
  • Вопрос задан
  • 6040 просмотров
Пригласить эксперта
Ответы на вопрос 1
Примерно так: https://play.golang.org/p/yiKGZY4GZL

package main

import (
	"encoding/xml"
	"fmt"
	"log"
)

type CNode struct {
	Hash string `xml:"hash,attr"`
	Node string `xml:"node,attr"`
}

type Features struct {
	XMLName    xml.Name `xml:"stream features"`
	Mechanisms []string `xml:"mechanisms>mechanism"`
	C          CNode    `xml:"c"`
}

func main() {
	raw_data := []byte(`
        <stream:features>
            <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
            <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
                <mechanism>PLAIN</mechanism>
                <mechanism>DIGEST-MD5</mechanism>
                <mechanism>SCRAM-SHA-1</mechanism>
            </mechanisms>
            <c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://www.process-one.net/en/ejabberd/' ver='NUUMEO3rKA30XLGO1FbA9EZT1rY='/>
            <register xmlns='http://jabber.org/features/iq-register'/>
        </stream:features>
    `)

	var v Features
	err := xml.Unmarshal(raw_data, &v)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%+v\n", v)
}


В принципе, спецификация и пара примеров есть здесь https://golang.org/pkg/encoding/xml
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы