Golang XML解组问题:本地名称冲突失败

I am getting incorrect behaviour (or I am doing something wrong). The golang XML demarshalling does not appear to handle a specific case of local name collisions. That is, where you have one element that has 2 child elements, both with the same local name ("book") but one with no namespace (or default or empty), and the other with an explicit namespace.

For (a contrived) example:

<library
   xmlns:lib="http://foobar.com/ns/library">
   <lib:book>
     AAA
   </lib:book>
   <book>
     ZZZ
   </book>
<library>

If I use the following struct to represent this:

type Library_Type struct {
   Book string `xml:"book,omitempty" json:",omitempty"`
   Book_lib string `xml:"http://foobar.com/ns/library book,omitempty" json:",omitempty"`
   Lib string `xml:"xmlns lib,attr"`
}

And try to demarshal, it does not work at all: Source: http://play.golang.org/p/YW2XpTVRs5

Output:

{"Lib":""}
{"Lib":""}

However, if I comment out the 'Book string' in the struct: http://play.golang.org/p/BRv6tUNreM

Output:

{"Book_lib":"
 AAA
 ","Lib":"http://foobar.com/ns/library"}

If I comment out the 'Book_lib'...: http://play.golang.org/p/u_Up9X9YMp

Output:

{"Book":"
 ZZZ
 ","Lib":"http://foobar.com/ns/library"}

If I add a space in front of 'Book': From:

    Book string `xml:"book,omitempty" json:",omitempty"`

To:

    Book string `xml:" book,omitempty" json:",omitempty"`

However, adding 2 spaces (which could be interpreted as the first space being the namespace, and the second space whitespace separation; when there is no namespace, calling xml.StartElement.Name.Space equals ""):

To:

    Book string `xml:"  book,omitempty" json:",omitempty"`

http://play.golang.org/p/Br_WBR3U8K

Output:

{"Book_lib":"
     AAA
   ","Lib":"http://foobar.com/ns/library"}

If I have two exlicit name spaces, the problem goes away (the output is the expected output): http://play.golang.org/p/llpMuC0SV8

Output:

{"Book_bin":"
 ZZZ
 ","Book_lib":"
 AAA
 ","Lib":"http://foobar.com/ns/library","Bin":"http://foobar.com/ns/bin"}

So, unless I am doing something wrong here, the use case where XML has a mix of default (empty) namespace and explicit namespaces with local name collisions appears to not work and this is a bug.

But if you could find me a way around this I would appreciate it.

This question is very interesting, and I actually had to do some research to get it.

  1. You will have to use a separate struct for the books

  2. You will need to use ,chardata for the actual value.

playground

type Library struct {
    XMLName xml.Name `xml:"library"`
    Entry []Book `xml:"book"`
}

type Book struct {
    XMLName xml.Name `xml:"book"`
    Name   string   `xml:",chardata"`
}