如何在Golang中遍历XML数据?

时间:2022-03-20 14:31:10

I have used xml.UnMarshal method to get a struct object but it has it's own limitations. I need a way where I can get all the descendants of a particular type inside a node without specifying the exact xpath.

我使用xml.UnMarshal方法来获取struct对象,但它有自己的局限性。我需要一种方法,我可以在节点内获取特定类型的所有后代,而无需指定确切的xpath。

For example, I have an xml data of the following format:

例如,我有一个以下格式的xml数据:

<content>
    <p>this is content area</p>
    <animal>
        <p>This id dog</p>
        <dog>
           <p>tommy</p>
        </dog>
    </animal>
    <birds>
        <p>this is birds</p>
        <p>this is birds</p>
    </birds>
    <animal>
        <p>this is animals</p>
    </animal>
</content>

Now I want to traverse through the above xml and process each node and it's children in that order. The problem is that this structure is not fixed and order of elements may change. So I need a way so that I can traverse like

现在我想遍历上面的xml并按顺序处理每个节点及其子节点。问题是这种结构不固定,元素的顺序可能会改变。所以我需要一种方法让我可以穿越

While(Content.nextnode())
{
   switch(type of node)
   {
      //Process the node or traverse the child node deeper
   }
}

4 个解决方案

#1


14  

You can do it with a vanilla encoding/xml by using a recursive struct and a simple walk function:

您可以使用递归结构和简单的walk函数使用vanilla encoding / xml来完成它:

type Node struct {
    XMLName xml.Name
    Content []byte `xml:",innerxml"`
    Nodes   []Node `xml:",any"`
}

func walk(nodes []Node, f func(Node) bool) {
    for _, n := range nodes {
        if f(n) {
            walk(n.Nodes, f)
        }
    }
}

Playground example: http://play.golang.org/p/rv1LlxaHvK.

游乐场示例:http://play.golang.org/p/rv1LlxaHvK。


EDIT: Here's a version with attrs:

编辑:这是一个带attrs的版本:

type Node struct {
    XMLName xml.Name
    Attrs   []xml.Attr `xml:"-"`
    Content []byte     `xml:",innerxml"`
    Nodes   []Node     `xml:",any"`
}

func (n *Node) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    n.Attrs = start.Attr
    type node Node

    return d.DecodeElement((*node)(n), &start)
}

Playground: https://play.golang.org/p/d9BkGclp-1.

游乐场:https://play.golang.org/p/d9BkGclp-1。

#2


0  

Since you are asking for a library and since it seems you would like to traverse the XML tree, i can recommend XMLDom-Go, i've used it on some past projects.

因为你要求一个库,因为你似乎想要遍历XML树,我可以推荐XMLDom-Go,我已经在过去的一些项目中使用过它。

#3


0  

I did a bit of search on how to deal with generic XML DOM and the closest you can do is use decoder.Token() or decoder.RawToken().

我做了一些关于如何处理通用XML DOM的搜索,你可以做的最接近的是使用decoder.Token()或decoder.RawToken()。

However if you're willing to consider a library I found this one to be very easy to pick up: https://github.com/beevik/etree

但是,如果你愿意考虑一个库我发现这个很容易上手:https://github.com/beevik/etree

doc := etree.NewDocument()
if err := doc.ReadFromFile("bookstore.xml"); err != nil {
    panic(err)
}

root := doc.SelectElement("bookstore")
fmt.Println("ROOT element:", root.Tag)

for _, book := range root.SelectElements("book") {
    fmt.Println("CHILD element:", book.Tag)
    if title := book.SelectElement("title"); title != nil {
        lang := title.SelectAttrValue("lang", "unknown")
        fmt.Printf("  TITLE: %s (%s)\n", title.Text(), lang)
    }
    for _, attr := range book.Attr {
        fmt.Printf("  ATTR: %s=%s\n", attr.Key, attr.Value)
    }
}

It uses the built-in xml parser with in the manner described above.

它以上述方式使用内置的xml解析器。

#4


0  

xmlquery supports parse an XML document as DOM tree to traverse all nodes, like Go's html package.

xmlquery支持将XML文档解析为DOM树来遍历所有节点,例如Go的html包。

#1


14  

You can do it with a vanilla encoding/xml by using a recursive struct and a simple walk function:

您可以使用递归结构和简单的walk函数使用vanilla encoding / xml来完成它:

type Node struct {
    XMLName xml.Name
    Content []byte `xml:",innerxml"`
    Nodes   []Node `xml:",any"`
}

func walk(nodes []Node, f func(Node) bool) {
    for _, n := range nodes {
        if f(n) {
            walk(n.Nodes, f)
        }
    }
}

Playground example: http://play.golang.org/p/rv1LlxaHvK.

游乐场示例:http://play.golang.org/p/rv1LlxaHvK。


EDIT: Here's a version with attrs:

编辑:这是一个带attrs的版本:

type Node struct {
    XMLName xml.Name
    Attrs   []xml.Attr `xml:"-"`
    Content []byte     `xml:",innerxml"`
    Nodes   []Node     `xml:",any"`
}

func (n *Node) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    n.Attrs = start.Attr
    type node Node

    return d.DecodeElement((*node)(n), &start)
}

Playground: https://play.golang.org/p/d9BkGclp-1.

游乐场:https://play.golang.org/p/d9BkGclp-1。

#2


0  

Since you are asking for a library and since it seems you would like to traverse the XML tree, i can recommend XMLDom-Go, i've used it on some past projects.

因为你要求一个库,因为你似乎想要遍历XML树,我可以推荐XMLDom-Go,我已经在过去的一些项目中使用过它。

#3


0  

I did a bit of search on how to deal with generic XML DOM and the closest you can do is use decoder.Token() or decoder.RawToken().

我做了一些关于如何处理通用XML DOM的搜索,你可以做的最接近的是使用decoder.Token()或decoder.RawToken()。

However if you're willing to consider a library I found this one to be very easy to pick up: https://github.com/beevik/etree

但是,如果你愿意考虑一个库我发现这个很容易上手:https://github.com/beevik/etree

doc := etree.NewDocument()
if err := doc.ReadFromFile("bookstore.xml"); err != nil {
    panic(err)
}

root := doc.SelectElement("bookstore")
fmt.Println("ROOT element:", root.Tag)

for _, book := range root.SelectElements("book") {
    fmt.Println("CHILD element:", book.Tag)
    if title := book.SelectElement("title"); title != nil {
        lang := title.SelectAttrValue("lang", "unknown")
        fmt.Printf("  TITLE: %s (%s)\n", title.Text(), lang)
    }
    for _, attr := range book.Attr {
        fmt.Printf("  ATTR: %s=%s\n", attr.Key, attr.Value)
    }
}

It uses the built-in xml parser with in the manner described above.

它以上述方式使用内置的xml解析器。

#4


0  

xmlquery supports parse an XML document as DOM tree to traverse all nodes, like Go's html package.

xmlquery支持将XML文档解析为DOM树来遍历所有节点,例如Go的html包。