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.
- You can use your struct as is to capture the root node's prefix URI
- get the slice of attributes, each of which has a struct that maps a URI to a name for the prefix
- iterate the attributes and try to match each attribute's value to the node's prefix URI, then
- 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
}