我需要產生一個複雜的 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 檔案的範例:
<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
只是一個介面來表示它可以容納的任何內容(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 }
這將允許產生以下項目:
<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: %v\n", err) } os.Stdout.Write(output)
這將準確列印您問題中提供的範例 XML 中的內容。
您可以在 Go Playground 中測試完整程式碼:https://go.dev/play/p /k8cEIywx3UB。
此解決方案的主要優點是:
ValueBool
實作 Value
),則可以輕鬆擴展它以上是Golang xml 鍵名稱衝突的詳細內容。更多資訊請關注PHP中文網其他相關文章!