gpt4 book ai didi

xml - 具有相同标签的 Golang XML 创建

转载 作者:IT王子 更新时间:2023-10-29 01:45:05 46 4
gpt4 key购买 nike

所以我得到了 xml(行业标准)的这种特定格式,我正在尝试创建一个简单的程序来允许我们制作这种 xml 的样本来测试我们的服务。我正在使用标准的 Go XML 库。

问题是 XML 的格式很烦人。这是它的简化版本:

<Document>
<SubDocument>
{other fields}
<component>
<section>
<id value="0" valueType="num"/> //This is the part that differentiates the type of the section
<title>Foo-Type Section</title>
{other fields you lot don't need to care about}
</section>
</component>
<component>
<section>
<id value="1" valueType="num"/>
<title>Bar-Type Section</title>
{more fields you don't need to care about, but most are different than above}
</section>
</component>
{more sections}
</SubDocument>
</Document>

我遇到的问题是,在 Go 中,如果每个部分的标签是不同的结构类型,则它们必须是唯一的。

我有以下 Go 代码:

type HasID struct{
ID string `xml:"value,attr,omitempty"`
IDType string `xml:"valueType,attr,omitempty"`
}
type FooSection struct{
ID HasID `xml:"id,omitempty"`
Title string `xml:"title,omitempty"`
//Foo fields
}
type BarSection struct{
ID HasID `xml:"id,omitempty"`
Title string `xml:"title,omitempty"`
//Bar fields
}
type Document struct{
XMLName struct{} `xml:"Document,omitempty"`
//Other fields
Sections []interface{} `xml:"SubDocument>component>section,omitempty"`
}

我还尝试让 Sections 字段没有标签,并且 FooSection 和 BarSection 都有

XMLName  struct{} `xml:"component>section,omitempty"`

标签,无济于事。此外,我已经尝试让 Sections 成为一个字符串数组,然后对每个部分类型进行编码,将它们转储并使用“,innerxml”标签,但随后它转义了 innerxml 的“<”等。

有谁知道在 Go 中执行此操作的方法吗?这些结构由我编写,如果需要,完全可以更改。

可能只是因为我对 OO 太过执着,并且很难像 Go 一样。

谢谢!

最佳答案

我不知道这是否是一个完美的答案,但它是可行的。要点是实现encoding/xml.UnmarshalerComponent 类型上,然后在该 UnmarshalXML 方法中,您将该部分的原始数据解码为一个临时值并检查其 ID,然后再决定是否要将其解码为 FooSectionBarSection

这些是我正在使用的类型

type ID struct {
Value int `xml:"value,attr,omitempty"`
Type string `xml:"valueType,attr,omitempty"`
}

type Document struct {
Components []Component `xml:"SubDocument>component"`
}

type Component struct {
Section interface{} `xml:"section"`
}

type FooSection struct {
ID ID `xml:"id"`
Title string `xml:"title"`
Foo string `xml:"foo"`
}

type BarSection struct {
ID ID `xml:"id"`
Title string `xml:"title"`
Bar string `xml:"bar"`
}

请注意,Component 将其 Section 存储为一个 interface{}。这有点烦人,因为无论何时你想使用它,你都必须输入 switch 它,这样你就可以用它做一些更好的事情。

那么UnmarshalXML方法就在这里

func (c *Component) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {

// tmp holds the data for this Component. We can only call d.DecodeElement
// once so we have to put it somewhere so it can be reused.
tmp := struct {
Data []byte `xml:",innerxml"`
}{}
if err := d.DecodeElement(&tmp, &start); err != nil {
return err
}

// which holds just enough information to tell us what kind of section to
// make. We'll unmarshal tmp.Data into this to inspect it
which := struct {
ID ID `xml:"id"`
}{}
if err := xml.Unmarshal(tmp.Data, &which); err != nil {
return err
}

switch which.ID.Value {
case 0:
var f FooSection
if err := xml.Unmarshal(tmp.Data, &f); err != nil {
return err
}
c.Section = f

case 1:
var b BarSection
if err := xml.Unmarshal(tmp.Data, &b); err != nil {
return err
}
c.Section = b
}

return nil
}

完整的工作代码 on the playground .


编辑:这些类型也应该用于生成您实际要求的 XML 字符串。当您构建每个 Component 时,您应该选择要制作的部分类型并将其粘贴在那里。因为它是一个接口(interface){},所以它可以容纳任何东西。我已将我的 playground 链接更新为一个示例,该示例显示将这些类型重新转换为字符串可以按预期工作。

关于xml - 具有相同标签的 Golang XML 创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39472041/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com