J'ai besoin de générer un fichier XML complexe afin de le charger dans un autre système. Par conséquent, les balises et l’ordre des balises ne peuvent pas être modifiés car ils doivent suivre un format précis pour se charger correctement. J'utilise actuellement le package encoding/xml dans Golang pour essayer d'accomplir cela.
Le problème que j'ai est que je ne peux pas avoir deux tags portant le même nom. J'obtiens l'erreur suivante : Le champ main.XMLDict "Key1" avec l'étiquette "key" est en conflit avec le champ "Key2" avec l'étiquette "key". Voici mon code simplifié :
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 }
Voici un exemple du fichier XML que je dois générer :
<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>
Donc, mes questions : 1) Existe-t-il un moyen simple de résoudre ce problème, toujours en utilisant l'approche structurelle consistant à créer les données puis à générer le XML, 2) Existe-t-il un meilleur moyen de créer et de générer ce fichier que d'utiliser Stuts ou 3) Est-ce que je fais juste quelque chose de mal ?
EDIT : Vous trouverez ci-dessous le fichier d'entrée demandé :
"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
Je pense qu'il existe de nombreuses solutions pour y parvenir en utilisant le XML personnalisé marshaller, voici ma tentative.
Tout d'abord, dans votre racine <dict>
, il semble toujours y avoir une "liste" d'éléments comme ceci :
<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>
Pour représenter chacun d'eux, on peut définir un 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 }
Nous pouvons ensuite implémenter cela en utilisant les différents types fournis dans l'exemple 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" }
À l'intérieur d'une balise XML, chardata
用于避免在我们的 XML 文档中包含额外的级别;对于 ValueStringArray
,我们使用 string
car c'est ainsi que votre projet est nommé.
Enfin, pour permettre la récursivité (dict
内部 dict
), on peut aussi définir cette structure :
type ValueDict struct { XMLName xml.Name `xml:"dict"` KeysValues []KeyValue } func (v ValueDict) getXMLName() string { return "dict" }
Une fois toutes les opérations terminées, nous pouvons implémenter un marshaleur personnalisé :
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 }
Cela permettra de générer des projets comme :
<key>Line Width</key> <real>0.004000000189989805</real>
Le nom de la balise (voici ce que renvoie la méthode real
)基于 getXMLName()
.
Enfin, vous pouvez définir les structures Go et les marshals comme ceci :
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)
Cela imprimera exactement ce qui se trouve dans l'exemple XML fourni dans votre question.
Vous pouvez tester le code complet dans Go Playground : https://go.dev/play/p /k8cEIywx3UB.
Les principaux avantages de cette solution sont :
ValueBool
ValueBool
实现 Value
), vous pouvez facilement l'étendre Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!