Heim > Backend-Entwicklung > Golang > Konflikt mit dem Namen des Golang-XML-Schlüssels

Konflikt mit dem Namen des Golang-XML-Schlüssels

WBOY
Freigeben: 2024-02-05 22:03:04
nach vorne
695 Leute haben es durchsucht

Golang xml 键名称冲突

Frageninhalt

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 
}
Nach dem Login kopieren

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>
Nach dem Login kopieren

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
Nach dem Login kopieren


Richtige Antwort


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>
Nach dem Login kopieren
<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
}
Nach dem Login kopieren
KeyValue 结构,其中 Value 只是一个接口来表示它可以容纳的任何内容(dataintegerWir 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" }
Nach dem Login kopieren
ValueInnerhalb eines XML-Tags,

denn so heißt Ihr Projekt.

chardata 用于避免在我们的 XML 文档中包含额外的级别;对于 ValueStringArray,我们使用 stringUm eine Rekursion (

) zu ermöglichen, können wir schließlich auch diese Struktur definieren:

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

func (v ValueDict) getXMLName() string { return "dict" }
Nach dem Login kopieren
dict 内部 dictNachdem 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
}
Nach dem Login kopieren

Dadurch können Projekte generiert werden wie:

<key>Line Width</key>
<real>0.004000000189989805</real>
Nach dem Login kopieren

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)
Nach dem Login kopieren

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
  • Wenn Ihr XML-Dokument andere Strukturen enthält (sagen wir, es handelt sich um einen booleschen Wert, wir können eine ValueBool-Implementierung erstellen
  • ), können Sie es problemlos erweitern
  • 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!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage