Home > Enterprise >  How to get xml prefix in golang in dynamic xml without struct
How to get xml prefix in golang in dynamic xml without struct

Time:10-05

Suppose I have an XML like this

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.opentravel.org/OTA/2003/05">
    <soap:Header/>
    <soap:Body>
        <contents>
            <article>
                <category>Server</category>
                <title>Connect to Oracle Server using Golang and Go-OCI8 on Ubuntu</title>
                <url>/go-oci8-oracle-linux/</url>
            </article>
            <!-- ... -->
        </contents>
    </soap:Body>
</soap:Envelope>

I also have common struct like this

type envelope struct {
    XMLName xml.Name
    Attrs   []xml.Attr `xml:",any,attr"`
    Body    struct {
        InnerXML []byte `xml:",innerxml"`
    }
}

The problem is how to get the word soap (from soap:Envelope)in the most outer wrapper

CodePudding user response:

I'm not sure of the limitations of this solution; please kindly point them out in the comments.

  1. You can use your struct as is to capture the root node's prefix URI
  2. get the slice of attributes, each of which has a struct that maps a URI to a name for the prefix
  3. iterate the attributes and try to match each attribute's value to the node's prefix URI, then
  4. save the attribute's local name, the name of the prefix

(I think that all makes sense, I called the right things by the right names)

Here's what it looks like:

var e envelope
xml.Unmarshal(data, &e)

var rootURI, rootPrefix string

rootURI = e.XMLName.Space
for _, attr := range e.Attrs {
    if attr.Name.Space == "xmlns" && attr.Value == rootURI {
        rootPrefix = attr.Name.Local
        break
    }
}

fmt.Println(rootPrefix, rootURI)

When I run that with your sample XML, it prints:

soap http://schemas.xmlsoap.org/soap/envelope/

Here's the complete demo, https://go.dev/play/p/x3FKfkCW64x.

CodePudding user response:

I found a golang library that is called https://github.com/beevik/etree so my code will be like this

func getPrefix(xmlbytes []byte) string {
    doc := etree.NewDocument()

    if err := doc.ReadFromBytes(xmlbytes); err != nil {
        log.Fatal(err.Error())
    }

    return doc.Root().Space
}

  • Related