欢迎光临
我们一直在努力

Golang xml 键名称冲突

golang xml 键名称冲突

问题内容

我需要生成一个复杂的 xml 文件才能将其加载到另一个系统中。因此,标签和标签顺序无法更改,因为它们必须遵循精确的格式才能正确加载。我目前正在 golang 中使用编码/xml 包来尝试完成此任务。

我遇到的问题是我不能有两个具有相同名称的标签。我收到以下错误: main.XMLDict 带有标签“key”的字段“Key1”与带有标签“key”的字段“Key2”冲突。下面是我的简化代码:

import (
    "fmt"
    "encoding/xml"
    "os"
)

type XMLDict struct {
    XMLName xml.Name    `xml:"dict"`
    Key1    string      `xml:"key"`
    Data1   string      `xml:"data"`
    Key2    string      `xml:"key"`
    StringArray XMLStringArray
}

type XMLStringArray struct {
    XMLName  xml.Name    `xml:"array"̀`
    XMLString   []string `xml:"string"`
}

func main() {

    sa := make([]string, 3)
    sa[0] = "g"
    sa[1] = "h"
    sa[2] = "i"

    arr := XMLStringArray{
        XMLString: sa,
    }

    master := XMLDict{
        Key1: "Color",
        Data1: "Random data",
        Key2: "Curve",
        StringArray: arr,
    }

    output, err := xml.MarshalIndent(master, "  ", "    ")
    if err != nil {
        fmt.Printf("error: %vn", err)
    }

    os.Stdout.Write(output)

    return 
}

下面是我需要生成的 XML 文件的示例:

<dict>
            <key>Color</key>
            <data>
            BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU0NvbG9yAISECE5TT2Jq
            ZWN0AIWEAWMChARmZmZmg7oehT2DZmYmP4NmZiY/AYY=
            </data>
            <key>Curve</key>
            <dict>
                <key>Interpolation</key>
                <integer>5</integer>
                <key>Points</key>
                <array>
                    <string>{0, 0}</string>
                    <string>{0.05, 0.053871}</string>
                    <string>{0.1, 0.110555}</string>
                    <string>{0.15, 0.166793}</string>
                    <string>{0.2, 0.216919}</string>
                    <string>{0.3, 0.327703}</string>
                    <string>{0.4, 0.440897}</string>
                    <string>{0.5, 0.539322}</string>
                    <string>{0.6, 0.657477}</string>
                    <string>{0.7, 0.763339}</string>
                    <string>{0.75, 0.814082}</string>
                    <string>{0.8, 0.861097}</string>
                    <string>{0.85, 0.904147}</string>
                    <string>{0.9, 0.944079}</string>
                    <string>{0.95, 0.974036}</string>
                    <string>{0.98, 0.990085}</string>
                    <string>{1, 1}</string>
                </array>
            </dict>
            <key>Line Width</key>
            <real>0.0040000001899898052</real>
            <key>Points Diameter</key>
            <real>0.014999999664723873</real>
            <key>Precision</key>
            <real>9.9999997473787516e-05</real>
        </dict>

所以,我的问题:1)有没有一种简单的方法来解决这个问题,仍然使用构建数据然后生成 XML 的结构方法,2)有没有更好的方法来构建和生成这个文件比使用 Stuts 或 3)我只是做错了什么吗?

编辑:下面是所请求的输入文件:

"File created by Curve"
LGOROWLENGTH 3
#
# Curve4 Run Information
#
# Run: Run 1 - Calibration
# Based On: <none>
#
# Values in this file are 'Wanted'
#
# Gray Balance: On
#    reduced after 100%
#    until 100%
#    media white values: Measured
#    media aim points: -0.17 / 0.96
#
NUMBER_OF_FIELDS    6
BEGIN_DATA_FORMAT
SampleID    SAMPLE_NAME CMYK_C  CMYK_M  CMYK_Y  CMYK_K
END_DATA_FORMAT
NUMBER_OF_SETS 17
BEGIN_DATA
A0  "0.00"  0.0000  0.0000  0.0000  0.0000
A1  "5.00"  5.3871  5.1408  5.2761  5.5775
A2  "10.00" 11.0555 10.7418 10.6026 11.0702
A3  "15.00" 16.6793 16.3894 15.8763 16.7064
A4  "20.00" 21.6919 21.7968 21.0234 22.3956
A5  "30.00" 32.7703 32.7458 31.1841 33.6738
A6  "40.00" 44.0897 42.4801 40.0887 44.2966
A7  "50.00" 53.9322 54.2364 49.1680 54.8968
A8  "60.00" 65.7477 64.9423 59.1719 66.4696
A9  "70.00" 76.3339 75.4398 69.4943 77.1661
A10 "75.00" 81.4082 80.5957 75.1423 82.0637
A11 "80.00" 86.1097 84.9296 81.1298 86.7399
A12 "85.00" 90.4147 88.8039 86.7945 90.8142
A13 "90.00" 94.4079 92.6783 92.1110 94.2426
A14 "95.00" 97.4036 96.2097 96.6019 97.2088
A15 "98.00" 99.0085 98.5775 98.7747 98.9000
A16 "100.00"    100.0000    100.0000    100.0000    100.0000
END_DATA

正确答案

我认为,有很多解决方案可以使用 XML 自定义封送拆收器来实现此目的;这是我的尝试。

首先,在你的根 <dict> 中,它似乎总是这样的项目“列表”:

<key>a-string</key>
<data|integer|real|array|dict>a-value</data|integer|real|array|dict>

<key>another-string</key>
<data|integer|real|array|dict>another-value</data|integer|real|array|dict>

为了表示其中的每一个,我们可以定义一个 KeyValue 结构,其中 Value 只是一个接口来表示它可以容纳的任何内容(datainteger,…)

type KeyValue struct {
    Key   string
    Value Value
}

type Value interface {
    getXMLName() string // this will return data, integer, array, etc, depending on the implementation
}

然后,我们可以使用示例中提供的不同类型来实现 Value

type ValueData struct {
    Data string `xml:",chardata"`
}

func (v ValueData) getXMLName() string { return "data" }

type ValueInteger struct {
    Integer int `xml:",chardata"`
}

func (v ValueInteger) getXMLName() string { return "integer" }

type ValueStringArray struct {
    Array []string `xml:"string"`
}

func (v ValueStringArray) getXMLName() string { return "array" }

type ValueReal struct {
    Real float64 `xml:",chardata"`
}

func (v ValueReal) getXMLName() string { return "real" }

在 XML 标签内,chardata 用于避免在我们的 XML 文档中包含额外的级别;对于 ValueStringArray,我们使用 string 因为您的项目是这样命名的。

最后,为了允许递归(dict 内部 dict),我们还可以定义这个结构体:

type ValueDict struct {
    XMLName    xml.Name `xml:"dict"`
    KeysValues []KeyValue
}

func (v ValueDict) getXMLName() string { return "dict" }

完成所有操作后,我们就可以实现一个自定义封送拆收器:

func (kv KeyValue) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
    if err := e.EncodeElement(kv.Key, xml.StartElement{Name: xml.Name{Local: "key"}}); err != nil {
        return err
    }
    if err := e.EncodeElement(kv.Value, xml.StartElement{Name: xml.Name{Local: kv.Value.getXMLName()}}); err != nil {
        return err
    }
    return nil
}

这将允许生成如下项目:

<key>Line Width</key>
<real>0.004000000189989805</real>

标签的名称(此处为 real)基于 getXMLName() 方法返回的内容。

最后,您可以像这样定义 Go 结构体和元帅:

master := ValueDict{
    KeysValues: []KeyValue{
        {
            Key: "Color",
            Value: ValueData{
                Data: "BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU0NvbG9yAISECE5TT2JqZWN0AIWEAWMChARmZmZmg7oehT2DZmYmP4NmZiY/AYY=",
            },
        },
        {
            Key: "Curve",
            Value: ValueDict{
                KeysValues: []KeyValue{
                    {
                        Key: "Interpolation",
                        Value: ValueInteger{
                            Integer: 5,
                        },
                    },
                    {
                        Key: "Points",
                        Value: ValueStringArray{
                            Array: []string{
                                "{0, 0}",
                                "{0.05, 0.053871}",
                                "{0.1, 0.110555}",
                                "{0.15, 0.166793}",
                                "{0.2, 0.216919}",
                                "{0.3, 0.327703}",
                                "{0.4, 0.440897}",
                                "{0.5, 0.539322}",
                                "{0.6, 0.657477}",
                                "{0.7, 0.763339}",
                                "{0.75, 0.814082}",
                                "{0.8, 0.861097}",
                                "{0.85, 0.904147}",
                                "{0.9, 0.944079}",
                                "{0.95, 0.974036}",
                                "{0.98, 0.990085}",
                                "{1, 1}",
                            },
                        },
                    },
                },
            },
        },
        {
            Key: "Line Width",
            Value: ValueReal{
                Real: 0.0040000001899898052,
            },
        },
        {
            Key: "Points Diameter",
            Value: ValueReal{
                Real: 0.014999999664723873,
            },
        },
        {
            Key: "Precision",
            Value: ValueReal{
                Real: 9.9999997473787516e-05,
            },
        },
    },
}

output, err := xml.MarshalIndent(master, "  ", "    ")
if err != nil {
    fmt.Printf("error: %vn", err)
}

os.Stdout.Write(output)

这将准确打印您问题中提供的示例 XML 中的内容。

您可以在 Go Playground 中测试完整代码:https://go.dev/play/p /k8cEIywx3UB

该解决方案的主要优点是:

  • 我们只需要实现一个自定义 XML 封送拆收器
  • 如果您的 XML 文档中有其他结构(假设是一个布尔值,我们可以创建一个 ValueBool 实现 Value),则可以轻松扩展它
赞(0) 打赏
未经允许不得转载:码农资源网 » Golang xml 键名称冲突
分享到

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

登录

找回密码

注册