Можно ли объединить дочерние узлы XML без выделенного корневого элемента при разборе? - PullRequest
0 голосов
/ 19 марта 2019

У меня есть XML-структура для работы, где часть выглядит как

   <Rights>
      <Name>NAS</Name>
      <Access>2</Access>
      <Name>App</Name>
      <Access>1</Access>
   </Rights>

Это (очевидно) список, и он гарантированно содержит пары Name, Access (и всегда в этомопределенный порядок).Мой вопрос: можно ли использовать функцию Unmarshal пакета encoding/xml для демаршалирования Name и Access в одной структуре?

Рассмотрим следующий пример:

package main

import (
    "encoding/xml"
    "fmt"
)

var XML = []string{`
?xml version="1.0" encoding="UTF-8"?>
<SessionInfo>
   <SID>abc123</SID>
   <Rights>
      <Name>NAS</Name>
      <Access>2</Access>
      <Name>App</Name>
      <Access>1</Access>
   </Rights>
</SessionInfo>
`,`
<SessionInfo>
   <SID>def456</SID>
   <Rights />
</SessionInfo>
`}

type Right struct {
    Name string
    Access int
}

type SessionInfo struct {
    XMLName   xml.Name `xml:"SessionInfo"`
    SID       string
    Rights    []Right
}

func main() {
    for _,entry := range XML {
        info := SessionInfo{}
        if err := xml.Unmarshal([]byte(entry), &info); err != nil {
            fmt.Println("Marshal failed", err.Error())
            continue
        }
        fmt.Printf("%+v\n", info)
    }
}

Thisне работает должным образом:

// Only the first value is found
{SID:abc123 Rights:[{Name:App Access:1}]} 
// One (not existing) value was found and the struct's zero value was used
{SID:def456 Rights:[{Name: Access:0}]}

Я мог (и это работает) определять свойства, независимые друг от друга, как

Names []string `xml:"Rights>Name"`
Accesses []int `xml:"Rights>Access"`

Но я бы предпочел формат структурыПервая версия без преобразования их вручную.

Есть ли способ получить ожидаемый результат?

1 Ответ

1 голос
/ 27 марта 2019

Я использую XPath библиотеку xmlquery , а не метод маршала / отмены разбивки.

package main

import (
    "fmt"
    "strings"

    "github.com/antchfx/xmlquery"
)

func main() {
    s := `
?xml version="1.0" encoding="UTF-8"?>
<SessionInfo>
   <SID>abc123</SID>
   <Rights>
      <Name>NAS</Name>
      <Access>2</Access>
      <Name>App</Name>
      <Access>1</Access>
   </Rights>
</SessionInfo>
`
    doc, err := xmlquery.Parse(strings.NewReader(s))
    if err != nil {
        panic(err)
    }
    for _, elem := range xmlquery.Find(doc, "//SessionInfo") {
        sid := xmlquery.FindOne(elem, "SID")
        fmt.Printf("sid: %s\n", sid.InnerText())
        for _, name := range xmlquery.Find(elem, "Rights/Name") {
            fmt.Printf("name: %s\n", name.InnerText())
        }
    }
}

выход

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