Ich muss eine komplexe XML-Datei generieren, um sie in ein anderes System zu laden. Daher können Tags und Tag-Reihenfolge nicht geändert werden, da sie einem genauen Format folgen müssen, um korrekt geladen zu werden. Ich verwende derzeit das Paket „encoding/xml“ in Golang, um dies zu erreichen.
Das Problem, das ich habe, ist, dass ich nicht zwei Tags mit demselben Namen haben kann. Ich erhalte die folgende Fehlermeldung: main.XMLDict Das Feld „Key1“ mit der Bezeichnung „key“ steht in Konflikt mit dem Feld „Key2“ mit der Bezeichnung „key“. Hier ist mein vereinfachter Code:
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 }
Hier ist ein Beispiel der XML-Datei, die ich generieren muss:
<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>
Also, meine Fragen: 1) Gibt es eine einfache Möglichkeit, dieses Problem zu lösen, indem man immer noch den strukturellen Ansatz verwendet, die Daten zu erstellen und dann das XML zu generieren? 2) Gibt es eine bessere Möglichkeit, diese Datei zu erstellen und zu generieren, als Stuts oder zu verwenden? 3) Mache ich einfach etwas falsch?
EDIT: Unten ist die angeforderte Eingabedatei:
"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
Ich denke, es gibt viele Lösungen, um dies mit dem benutzerdefinierten XML-Marshaller zu erreichen. Hier ist mein Versuch. Zuallererst scheint es in Ihrem Stammverzeichnis
immer eine „Liste“ von Elementen wie dieser zu geben:
<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>
<dict>
Um jeden von ihnen darzustellen, können wir ein ,...)definieren
type KeyValue struct { Key string Value Value } type Value interface { getXMLName() string // this will return data, integer, array, etc, depending on the implementation }
KeyValue
结构,其中 Value
只是一个接口来表示它可以容纳的任何内容(data
,integer
Wir können dies dann mithilfe der verschiedenen im Beispiel bereitgestellten Typen implementieren :
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" }
Value
Innerhalb eines XML-Tags, denn so heißt Ihr Projekt.
chardata
用于避免在我们的 XML 文档中包含额外的级别;对于 ValueStringArray
,我们使用 string
Um eine Rekursion (
type ValueDict struct { XMLName xml.Name `xml:"dict"` KeysValues []KeyValue } func (v ValueDict) getXMLName() string { return "dict" }
dict
内部 dict
Nachdem alle Vorgänge abgeschlossen sind, können wir einen benutzerdefinierten Marshaller implementieren:
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 }
Dadurch können Projekte generiert werden wie:
<key>Line Width</key> <real>0.004000000189989805</real>
Der Name des Tags (hier ist, was die
-Methode zurückgibt.
real
)基于 getXMLName()
Schließlich können Sie Go-Strukturen und Marshalls wie folgt definieren:
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)
Hierdurch wird genau das gedruckt, was im Beispiel-XML in Ihrer Frage enthalten ist.
Sie können den vollständigen Code im Go Playground testen:
https://go.dev/play/p /k8cEIywx3UB. Die Hauptvorteile dieser Lösung sind:
Wir müssen lediglich einen benutzerdefinierten XML-Marshaler implementieren
ValueBool
-Implementierung erstellen ValueBool
实现 Value
Das obige ist der detaillierte Inhalt vonKonflikt mit dem Namen des Golang-XML-Schlüssels. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!