Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to traverse through XML data in Golang?

Tags:

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:

<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

While(Content.nextnode())
{
   switch(type of node)
   {
      //Process the node or traverse the child node deeper
   }
}
like image 990
Prashant Avatar asked May 15 '15 10:05

Prashant


People also ask

How to read XML file in golang?

xml file is read with the ioutil. ReadFile() function and a byte slice is returned, which is then decoded into a struct instance with the xml. Unmarshal() function. The struct instance member values are used to print the decoded data.


1 Answers

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:",any,attr"`
    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.

like image 182
Ainar-G Avatar answered Sep 18 '22 13:09

Ainar-G