How to traverse through XML data in Golang?

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

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.

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

     

this is content area

This id dog

tommy

this is birds

this is birds

this is animals

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

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

回答1:

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

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.


EDIT: Here's a version with 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.



回答2:

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.



回答3:

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().

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

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.



回答4:

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



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!