我需要生成一个复杂的 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: %v\n", err)
}
os.Stdout.Write(output)
return
}
下面是我需要生成的 XML 文件的示例:
Color
BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU0NvbG9yAISECE5TT2Jq
ZWN0AIWEAWMChARmZmZmg7oehT2DZmYmP4NmZiY/AYY=
Curve
Interpolation
5
Points
{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}
Line Width
0.0040000001899898052
Points Diameter
0.014999999664723873
Precision
9.9999997473787516e-05
所以,我的问题:1)有没有一种简单的方法来解决这个问题,仍然使用构建数据然后生成 XML 的结构方法,2)有没有更好的方法来构建和生成这个文件比使用 Stuts 或 3)我只是做错了什么吗?
编辑:下面是所请求的输入文件:
"File created by Curve"
LGOROWLENGTH 3
#
# Curve4 Run Information
#
# Run: Run 1 - Calibration
# Based On:
#
# 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 自定义封送拆收器来实现此目的;这是我的尝试。
首先,在你的根
中,它似乎总是这样的项目“列表”:
a-string
a-value
another-string
another-value
为了表示其中的每一个,我们可以定义一个 KeyValue
结构,其中 Value
只是一个接口来表示它可以容纳的任何内容(data
,integer
,...)
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
}
这将允许生成如下项目:
Line Width
0.004000000189989805
标签的名称(此处为 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: %v\n", err)
}
os.Stdout.Write(output)
这将准确打印您问题中提供的示例 XML 中的内容。
您可以在 Go Playground 中测试完整代码:https://go.dev/play/p /k8cEIywx3UB。
该解决方案的主要优点是:
- 我们只需要实现一个自定义 XML 封送拆收器
- 如果您的 XML 文档中有其他结构(假设是一个布尔值,我们可以创建一个
ValueBool
实现Value
),则可以轻松扩展它
以上就是Golang xml 键名称冲突的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756