使用冲突的元素名称在 Go 中解组 XML
Unmarshaling XML in Go with Conflicting Element Names
我有以下 XML,外部定义且不受我的组织控制:
<foo>
<bar>
<zip>zip</zip>
</bar>
<bar>
<zap>zap</zap>
</bar>
</foo>
我正在使用这些结构:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Bar1 Bar1
Bar2 Bar2
}
type Bar1 struct {
XMLName xml.Name `xml:"bar"`
Zip string `xml:"zip"`
}
type Bar2 struct {
XMLName xml.Name `xml:"bar"`
Zap string `xml:"zap"`
}
由于 'bar' 名称冲突,没有任何内容被解组。如何填充 Bar1 和 Bar2 结构?
这是我的:https://play.golang.org/p/D2IRLojcTB
这是我想要的结果:https://play.golang.org/p/Ytrbzzy9Ok
在第二个中,我将第二个 'bar' 更新为 'bar1,' 并且一切正常。我宁愿想出一个更简洁的解决方案来修改传入的 XML.
encoding/xml
包将无法完全满足您的要求,因为它会在遇到 <bar>
时决定解码到 Foo
的哪个字段元素,而不是在处理该元素的子元素时。您的结构定义使这个决定变得模棱两可,因为来自 xml.Unmarshal
的错误表明:
main.Foo field "Bar1" with tag "" conflicts with field "Bar2" with tag ""
这里有两个可行的备选方案:
1.使用一个 Bar
结构来覆盖两个分支
如果您将类型修改为:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Bars []Bar `xml:"bar"`
}
type Bar struct {
Zip string `xml:"zip"`
Zap string `xml:"zap"`
}
您现在将获得代表所有 <bar>
元素的切片。您可以通过检查相应字段是否为非空来判断该元素是否具有 <zip>
或 <zap>
元素。
您可以在此处试用此版本:https://play.golang.org/p/kguPCYmKX0
2。使用子选择器
如果您只对每个分支中 <bar>
的单个子元素感兴趣,那么您可能根本不需要结构来表示该元素。例如,您可以解码为以下类型:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Zip string `xml:"bar>zip"`
Zap string `xml:"bar>zap"`
}
现在 <bar>
元素的子元素将直接解码为 Foo
结构的成员。请注意,使用此选项您将无法将您选择的输入与例如
区分开来
<foo>
<bar>
<zip>zip</zip>
<zap>zap</zap>
</bar>
</foo>
如果这会导致问题,那么您应该选择第一个解决方案。
您可以在这里试用这个版本:https://play.golang.org/p/fAE_HSrv4y
我有以下 XML,外部定义且不受我的组织控制:
<foo>
<bar>
<zip>zip</zip>
</bar>
<bar>
<zap>zap</zap>
</bar>
</foo>
我正在使用这些结构:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Bar1 Bar1
Bar2 Bar2
}
type Bar1 struct {
XMLName xml.Name `xml:"bar"`
Zip string `xml:"zip"`
}
type Bar2 struct {
XMLName xml.Name `xml:"bar"`
Zap string `xml:"zap"`
}
由于 'bar' 名称冲突,没有任何内容被解组。如何填充 Bar1 和 Bar2 结构?
这是我的:https://play.golang.org/p/D2IRLojcTB
这是我想要的结果:https://play.golang.org/p/Ytrbzzy9Ok
在第二个中,我将第二个 'bar' 更新为 'bar1,' 并且一切正常。我宁愿想出一个更简洁的解决方案来修改传入的 XML.
encoding/xml
包将无法完全满足您的要求,因为它会在遇到 <bar>
时决定解码到 Foo
的哪个字段元素,而不是在处理该元素的子元素时。您的结构定义使这个决定变得模棱两可,因为来自 xml.Unmarshal
的错误表明:
main.Foo field "Bar1" with tag "" conflicts with field "Bar2" with tag ""
这里有两个可行的备选方案:
1.使用一个 Bar
结构来覆盖两个分支
如果您将类型修改为:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Bars []Bar `xml:"bar"`
}
type Bar struct {
Zip string `xml:"zip"`
Zap string `xml:"zap"`
}
您现在将获得代表所有 <bar>
元素的切片。您可以通过检查相应字段是否为非空来判断该元素是否具有 <zip>
或 <zap>
元素。
您可以在此处试用此版本:https://play.golang.org/p/kguPCYmKX0
2。使用子选择器
如果您只对每个分支中 <bar>
的单个子元素感兴趣,那么您可能根本不需要结构来表示该元素。例如,您可以解码为以下类型:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Zip string `xml:"bar>zip"`
Zap string `xml:"bar>zap"`
}
现在 <bar>
元素的子元素将直接解码为 Foo
结构的成员。请注意,使用此选项您将无法将您选择的输入与例如
<foo>
<bar>
<zip>zip</zip>
<zap>zap</zap>
</bar>
</foo>
如果这会导致问题,那么您应该选择第一个解决方案。
您可以在这里试用这个版本:https://play.golang.org/p/fAE_HSrv4y