golang/go

encoding/xml: missing nested namespace not handled

anacrolix opened this issue · 21 comments

Nested XML namespaces aren't marshalled correctly. Setting an element namespace at the
default level as Go does, implicitly sets nested elements to the same namespace if they
don't override it.

<a xmlns="b"><c/></a>

The namespace of c, is b. However marshalling from Go data structures in which the
object corresponding to c above has no namespace set should give

<a xmlns="b"><c xmlns=""/></a>

The usual way to deal with this is to use namespace prefixes, but I don't think that's a
requirement.

Comment 1:

@anacrolix could you please include a short code sample or a test that demonstrates the
issue.

Status changed to WaitingForReply.

Comment 2:

Will do.

Comment 3:

I've created an example: http://play.golang.org/p/5zDgqtC3ra
The output is currently:
2009/11/10 23:00:00 "b" == "b"
2009/11/10 23:00:00 "" == ""
2009/11/10 23:00:00 "<A xmlns=\"b\"><C></C></A>" != "<A
xmlns=\"b\"><C xmlns=\"\"></C></A>"
2009/11/10 23:00:00 "b" == "b"
2009/11/10 23:00:00 "b" != ""
If you read the play source, you'll observe that the namespace of "" on element C has
been lost when marshalling. When unmarshalling what Go currently produces, it no longer
has "" for C's namespace as a result.
This is incorrect, see:
http://stackoverflow.com/questions/2193220/xml-namespace-defaulting-inheritance
http://www.w3.org/TR/REC-xml-names/#scoping-defaulting
http://www.w3.org/TR/xml-names/#defaulting
The impact this has on programs using XML, is that they don't reset the default
namespace for nested elements when marshalling.
Here's some downstream bugs that result from this:
https://bitbucket.org/anacrolix/dms/issue/25/get-soap-responses-to-work-with-upnp
https://bitbucket.org/anacrolix/dms/issue/19/samsung-doesnt-like-response-to
rsc commented

Comment 5:

Labels changed: added release-go1.3maybe.

Status changed to Accepted.

Comment 6:

CL https://golang.org/cl/66850043 references this issue.
rsc commented

Comment 7:

Alternate CL at https://golang.org/cl/93320043. Leaving final decision for 1.4.

Labels changed: added release-go1.4, removed release-go1.3maybe.

Comment 8 by glen.newton:

Is this related to or the same bug as: 'Golang XML unmarshalling issue: local name
collisions fail'
https://stackoverflow.com/questions/24870309/golang-xml-unmarshalling-issue-local-name-collisions-fail/
I am asking as I am trying to figure out if I should submit a bug for my issue.

Comment 9:

I don't believe it is the same bug. It could be related, but I recommend you create a
new issue for it.

Comment 10:

Labels changed: added repo-main.

rsc commented

Comment 11:

We didn't get to this in time. My apologies.

Labels changed: added release-go1.5, removed release-go1.4.

Please see my example and scenario on issue #9527 as well. Also, there is another issue with prefixes that is going to be highly related to this #9519 / #6800. I would love to see both of these fixed in 1.5 if I can beg enough.

I'm writing an RPM manager using GO and I ended up with this problem too. The XML file primary.xml provided by any RPM repository uses "rpm:entry" and others tags with the "rpm" as namespace prefix. It took me two days until I figured out It's a bug. Well, I did some string.replace and it works, but not as good as xml.Marshal.

rsc commented

See #11841.

CL https://golang.org/cl/12570 mentions this issue.

rsc commented

Blocked on #13400.

Can I help with issue ?

Change https://golang.org/cl/108796 mentions this issue: encoding/xml fix overriding by empty namespace

iwdgo commented

The namespace defined by xmlns="value" can be overridden in every included tag including by the empty namespace xmlns="". Empty namespace is not authorized with a prefix (xmlns:ns="") and a related fix has been submitted (#8068) .

Method to calculate indent of XML handles depth of tag and its associated namespace. The fix leaves the method active even when no indent is required.

An XMLName field in a struct means that namespace must be enforced even if empty. This occurs only on an inner tag as an overwrite of any non-empty namespace of its outer tag.
To obtain the xmlns="" required, an attribute is added.

A typo was also fixed as the attribute was writing the tag space and not the attribute space. If no namespace is active, nothing is written.

A specific test is added which derives from the submitted example.

Change https://golang.org/cl/109855 mentions this issue: encoding/xml : Fixes to enforce XML namespace standard

Change https://go.dev/cl/466295 mentions this issue: encoding/xml: only overriding by empty namespace when no new name dec…