Search code examples
xmlgo

How to remove/delete/modify XML elements from an XML document using Golang without using structs


I am using Golang for an API gateway and we need to remove certain XML elements from documents.

We are unable to use structs/marshalling as the XML structures are huge and variable - but we consistently need to remove a few XML elements based on their name/path

I have tried to "walk" the XML document and "skip" certain elements based on their name.

My example is here, but I am getting errors: https://go.dev/play/p/LJtlYXWvJ_d

panic: xml: end tag </age> does not match start tag <person>

I must be doing something wrong, and most examples I can find use Structs to do this.


Solution

  • If you look at this output:

    End Tag of  age  parent name is  age
    

    It gives a good clue. Then look right here:

            case xml.EndElement:
                println("End Tag of ", t.Name.Local, " parent name is ", parent.Name.Local)
                if skip && t.Name == parent.Name {
                    skip = false
                    parent = xml.StartElement{}
                }
                if !skip {
                    println("Encoding End Element ", t.Name.Local, " buffer is ", buf.String())
                    err := encoder.EncodeToken(token)
                    if err != nil {
                        panic(err)
                    }
                }
                encoder.Flush()
    

    From the output we can see that skip && t.Name == parent.Name will be true. We toggle skip to be false and reset parent. Then we proceed to check if !skip . We just set skip to false, so we attempt to encode the token. But we were supposed to skip that token!

    The fix is simple: just add a break to that case condition.

                if skip && t.Name == parent.Name {
    
                    skip = false
                    parent = xml.StartElement{}
                    break
                }
    

    gives (debugging output removed):

    &#x9;&#x9;<people>
    &#x9;&#x9;&#x9;<person>
    &#x9;&#x9;&#x9;&#x9;<name>John</name>
    &#x9;&#x9;&#x9;&#x9;
    &#x9;&#x9;&#x9;</person>
    &#x9;&#x9;&#x9;<person>
    &#x9;&#x9;&#x9;&#x9;<name>Jane</name>
    &#x9;&#x9;&#x9;&#x9;
    &#x9;&#x9;&#x9;</person>
    &#x9;&#x9;</people>