如何使用golang区分xml中的同名兄弟姐妹?

发布于 2025-01-10 06:30:11 字数 1571 浏览 0 评论 0原文

我有以下 xml:

<?xml version='1.0' encoding='UTF-8'?>
<actions>
  <foo>text</foo>
  <foo1>text</foo1>
  <foo2>text</foo2>
  <bar>text</bar>
  <foo>text</foo>
  <foo1>text</foo1>
  <foo2>text</foo2>
</actions>

这里我想解析 xml,这样我就可以批量处理 foo

像这样的事情:

[
{foo: text, foo1: text, foo2: text}
{foo: text, foo1: text, foo2: text}
]

但不知道如何做到这一点。

如果我使用下面的代码,我会以我不想要的不同方式获得输出值。

package main

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "os"
)

type Foo struct {
    Foo string
    Foo1 string
    Foo2 string
}

type MyXml struct {
    XMLName xml.Name `xml:"actions"`
    Foo []string `xml:"foo"`
}

func main() {
    // Open our xmlFile
    xmlFile, err := os.Open("./z.xml")
    // if we os.Open returns an error then handle it
    if err != nil {
        fmt.Println("err", err)
    }

    fmt.Println("Successfully Opened z.xml")
    // defer the closing of our xmlFile so that we can parse it later on
    defer xmlFile.Close()

    // read our opened xmlFile as a byte array.
    byteValue, _ := ioutil.ReadAll(xmlFile)

    var data MyXml

    z := xml.Unmarshal(byteValue, &data)

    if z != nil {
        panic(z)
    }

    fmt.Println(data)
}

输出:

{{ actions} [text text]}

有什么方法可以稍微改变上面的代码,使输出如下:

[
{foo: text, foo1: text, foo2: text}
{foo: text, foo1: text, foo2: text}
]

I have the following xml:

<?xml version='1.0' encoding='UTF-8'?>
<actions>
  <foo>text</foo>
  <foo1>text</foo1>
  <foo2>text</foo2>
  <bar>text</bar>
  <foo>text</foo>
  <foo1>text</foo1>
  <foo2>text</foo2>
</actions>

Here i want to parse the xml so i can have batches of foo.

Something like this:

[
{foo: text, foo1: text, foo2: text}
{foo: text, foo1: text, foo2: text}
]

But not sure how to make it like so.

If i us below code i get output value in a different way which i don't want.

package main

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "os"
)

type Foo struct {
    Foo string
    Foo1 string
    Foo2 string
}

type MyXml struct {
    XMLName xml.Name `xml:"actions"`
    Foo []string `xml:"foo"`
}

func main() {
    // Open our xmlFile
    xmlFile, err := os.Open("./z.xml")
    // if we os.Open returns an error then handle it
    if err != nil {
        fmt.Println("err", err)
    }

    fmt.Println("Successfully Opened z.xml")
    // defer the closing of our xmlFile so that we can parse it later on
    defer xmlFile.Close()

    // read our opened xmlFile as a byte array.
    byteValue, _ := ioutil.ReadAll(xmlFile)

    var data MyXml

    z := xml.Unmarshal(byteValue, &data)

    if z != nil {
        panic(z)
    }

    fmt.Println(data)
}

Output:

{{ actions} [text text]}

Is there any way by which its possible to change the above code a little so the output will be like this:

[
{foo: text, foo1: text, foo2: text}
{foo: text, foo1: text, foo2: text}
]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

感性不性感 2025-01-17 06:30:11

鉴于 XML 结构相对简单,您可以使用 xml.Decoder 以流模式解析它:

func main() {
    // Open our xmlFile ...
    xmlFile := . . .
    decoder := xml.NewDecoder(xmlFile)

    var data MyXml
    inActions := false
    for {
        t, _ := decoder.Token()
        if t == nil {
            break
        }
        switch se := t.(type) {
        case xml.StartElement:
            if inActions {
                switch se.Name.Local {
                case "foo":
                    decoder.DecodeElement(&data.getFoo(true).Foo, &se)
                case "foo1":
                    decoder.DecodeElement(&data.getFoo(false).Foo1, &se)
                case "foo2":
                    decoder.DecodeElement(&data.getFoo(false).Foo2, &se)
                }
            } else if se.Name.Local == "actions" {
                inActions = true
            }
        case xml.EndElement:
            if se.Name.Local == "actions" {
                inActions = false
            }
        }
    }

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

type Foo struct {
    Foo  string
    Foo1 string
    Foo2 string
}

type MyXml struct {
    Actions []Foo
}

func (d *MyXml) getFoo(new bool) *Foo {
    if new || len(d.Actions) == 0 {
        d.Actions = append(d.Actions, Foo{})
    }
    return &d.Actions[len(d.Actions)-1]
}

将打印:(现场演示

[{Foo:text Foo1:text Foo2:text} {Foo:text Foo1:text Foo2:text}]

Given the relatively simple XML structure, you can use xml.Decoder to parse it in streaming mode:

func main() {
    // Open our xmlFile ...
    xmlFile := . . .
    decoder := xml.NewDecoder(xmlFile)

    var data MyXml
    inActions := false
    for {
        t, _ := decoder.Token()
        if t == nil {
            break
        }
        switch se := t.(type) {
        case xml.StartElement:
            if inActions {
                switch se.Name.Local {
                case "foo":
                    decoder.DecodeElement(&data.getFoo(true).Foo, &se)
                case "foo1":
                    decoder.DecodeElement(&data.getFoo(false).Foo1, &se)
                case "foo2":
                    decoder.DecodeElement(&data.getFoo(false).Foo2, &se)
                }
            } else if se.Name.Local == "actions" {
                inActions = true
            }
        case xml.EndElement:
            if se.Name.Local == "actions" {
                inActions = false
            }
        }
    }

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

type Foo struct {
    Foo  string
    Foo1 string
    Foo2 string
}

type MyXml struct {
    Actions []Foo
}

func (d *MyXml) getFoo(new bool) *Foo {
    if new || len(d.Actions) == 0 {
        d.Actions = append(d.Actions, Foo{})
    }
    return &d.Actions[len(d.Actions)-1]
}

Would print: (live demo)

[{Foo:text Foo1:text Foo2:text} {Foo:text Foo1:text Foo2:text}]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文