What version of Go are you using (go version
)?
$ go version go version go1.17.1 darwin/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/ydnar/Library/Caches/go-build" GOENV="/Users/ydnar/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/ydnar/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/ydnar/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/Cellar/go/1.17.1/libexec" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.17.1/libexec/pkg/tool/darwin_amd64" GOVCS="" GOVERSION="go1.17.1" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/ydnar/development/ydnar/go/src/go.mod" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/6g/1gng3zts0t39s_qbtt7p0wsc0000gn/T/go-build2847614851=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
Use xml.Marshal
to marshal namespaced XML, and xml.Unmarshal
to decode that XML.
Example: https://play.golang.org/p/-6Ee8tcLl2L
What did you expect to see?
Namespace prefixes preserved round-trip.
What did you see instead?
Namespace prefixes written, but not recognized as the relevant tag when decoding.
Proposal
Change the encoding/xml
package to allow callers to specify a preferred namespace prefix, and allow decoding of prefixed tags.
The preferred prefix can be specified by prefixing the XML tag name in a struct tag or (xml.Name).Local
.
This should be backwards-compatible with existing Go 1 encoding/xml
clients.
Example
type EPP struct {
XMLName struct{} `xml:"urn:ietf:params:xml:ns:epp-1.0 epp"`
Command *Command `xml:"command,omitempty"`
}
type Command struct {
Check *Check `xml:"urn:ietf:params:xml:ns:epp-1.0 check,omitempty"`
}
type Check struct {
DomainCheck *DomainCheck `xml:"urn:ietf:params:xml:ns:domain-1.0 domain:check,omitempty"`
}
type DomainCheck struct {
DomainNames []string `xml:"urn:ietf:params:xml:ns:domain-1.0 domain:name,omitempty"`
}
This change would allow a structure defined above to correctly round-trip encode and decode with namespace prefixes:
var v = &EPP{Command: &Command{Check: &Check{DomainCheck: &DomainCheck{DomainNames: []string{"golang.org", "go.dev"}}}}}
Would encode to (and decode from):
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"><command><check><domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"><domain:name>golang.org</domain:name><domain:name>go.dev</domain:name></domain:check></check></command></epp>
Implementation
A working implementation can be found at #48641, built on earlier work by @rogpeppe and others.
Related Issues
This would fix #43168 and update #11431 and #8068.
Comment From: tobbee
@rsc
I think it is really important that the standard library gets proper handling of XML namespaces and namespace prefixes. The current implementation is definitely broken as has been raised in multiple issues. I can elaborate on the problems and short comings if needed,
In my view, this PR provides a good solution, or at least a good basis for a solution. I found myself forced to clone the standard xml package together with this patch in my new repo https://github.com/Eyevinn/dash-mpd that handles DASH MPD XMLs and need proper namespaces and prefixes.
In the discussion about previous ticket, Dave Cheney argued that one cannot change the behavior of such an established stdlib package as XML due to the risk of breaking someones code. I think there is some truth in that argument, so I'd like to suggest that we start working on a variant of the xml package that supports namespaces and namespace prefixes. It could be called encoding/xml2
, and this PR could make a good start. It would be nice if it could be done in the 1.21 time frame.
Comment From: ydnar
I’ve rebased #48641 on top of current master: https://go-review.googlesource.com/c/go/+/355353
Comment From: ydnar
Hi there, anything I can do to nudge this along? Thanks!
Comment From: ydnar
Would putting this behind GOEXPERIMENT=xmlns
make it more palatable?
Comment From: kavu
Hi! Would you mind I raise this issue again? What's the consensus regarding this one?
Comment From: ydnar
The proposed change is spiritually similar to the recent change to allow HTTP verbs in http.ServeMux
patterns: https://pkg.go.dev/net/http#ServeMux
Comment From: 3052
this example is not robust:
https://play.golang.org/p/-6Ee8tcLl2L
as it includes no consideration for namespaced attributes, which are also problematic