英文:
Golang XML unmarshalling issue: local name collisions fail
问题
我遇到了错误的行为(或者我做错了什么)。
Golang的XML解组似乎无法处理特定情况下的本地名称冲突。
也就是说,当一个元素有两个子元素,它们的本地名称都相同时("book"),一个没有命名空间(默认或空),另一个有显式命名空间。
举个(人为制造的)例子:
<library
xmlns:lib="http://foobar.com/ns/library">
<lib:book>
AAA
</lib:book>
<book>
ZZZ
</book>
</library>
如果我使用以下结构体来表示:
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"`
}
并尝试解组,它根本不起作用:源代码:http://play.golang.org/p/YW2XpTVRs5
输出:
{"Lib":""}
{"Lib":""}
然而,如果我在结构体中注释掉 'Book string':http://play.golang.org/p/BRv6tUNreM
输出:
{"Book_lib":"\n AAA\n ","Lib":"http://foobar.com/ns/library"}
如果我注释掉 'Book_lib'...:http://play.golang.org/p/u_Up9X9YMp
输出:
{"Book":"\n ZZZ\n ","Lib":"http://foobar.com/ns/library"}
如果我在 'Book' 前面加一个空格:
从:
Book string `xml:"book,omitempty" json:",omitempty"`
变为:
Book string `xml:" book,omitempty" json:",omitempty"`
然而,如果添加两个空格(可以解释为第一个空格是命名空间,第二个空格是空白分隔;当没有命名空间时,调用xml.StartElement.Name.Space等于""):
变为:
Book string `xml:" book,omitempty" json:",omitempty"`
http://play.golang.org/p/Br_WBR3U8K
输出:
{"Book_lib":"\n AAA\n ","Lib":"http://foobar.com/ns/library"}
如果我有两个显式命名空间,问题就消失了(输出是预期的输出):http://play.golang.org/p/llpMuC0SV8
输出:
{"Book_bin":"\n ZZZ\n ","Book_lib":"\n AAA\n ","Lib":"http://foobar.com/ns/library","Bin":"http://foobar.com/ns/bin"}
所以,除非我在这里做错了什么,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":"\n AAA\n ","Lib":"http://foobar.com/ns/library"}
If I comment out the 'Book_lib'...: http://play.golang.org/p/u_Up9X9YMp
Output:
{"Book":"\n ZZZ\n ","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":"\n AAA\n ","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":"\n ZZZ\n ","Book_lib":"\n AAA\n ","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.
答案1
得分: 3
这个问题非常有趣,我实际上不得不做一些研究才能理解它。
-
你需要为书籍使用一个单独的结构体。
-
你需要使用
,chardata
来表示实际的值。
type Library struct {
XMLName xml.Name `xml:"library"`
Entry []Book `xml:"book"`
}
type Book struct {
XMLName xml.Name `xml:"book"`
Name string `xml:",chardata"`
}
你可以在这个 playground 上查看示例代码。
英文:
This question is very interesting, and I actually had to do some research to get it.
-
You will have to use a separate struct for the books
-
You will need to use
,chardata
for the actual value.
type Library struct {
XMLName xml.Name `xml:"library"`
Entry []Book `xml:"book"`
}
type Book struct {
XMLName xml.Name `xml:"book"`
Name string `xml:",chardata"`
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论