Rumah >pembangunan bahagian belakang >Golang >Konflik nama kunci xml Golang

Konflik nama kunci xml Golang

WBOY
WBOYke hadapan
2024-02-05 22:03:04737semak imbas

Golang xml 键名称冲突

Kandungan soalan

Saya perlu menjana fail xml yang kompleks untuk memuatkannya ke dalam sistem lain. Oleh itu, teg dan susunan teg tidak boleh diubah kerana ia mesti mengikut format yang tepat untuk dimuatkan dengan betul. Saya sedang menggunakan pakej pengekodan/xml dalam golang untuk cuba mencapai ini.

Masalah yang saya hadapi ialah saya tidak boleh mempunyai dua tag dengan nama yang sama. Saya mendapat ralat berikut: main.XMLDict Field "Key1" dengan label "key" bercanggah dengan medan "Key2" dengan label "key". Berikut ialah kod ringkas saya:

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 
}

Berikut ialah contoh fail XML yang perlu saya hasilkan:

<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>

Jadi, soalan saya: 1) Adakah terdapat cara mudah untuk menyelesaikan masalah ini, masih menggunakan pendekatan struktur membina data dan kemudian menjana XML, 2) Adakah terdapat cara yang lebih baik untuk membina dan menjana fail ini daripada menggunakan Stuts atau 3) Adakah saya hanya melakukan sesuatu yang salah?

EDIT: Di bawah ialah fail input yang diminta:

"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

Jawapan betul


Saya rasa terdapat banyak penyelesaian untuk mencapai ini menggunakan tersuai XML marshaller; inilah percubaan saya.

Pertama sekali, dalam akar anda 009c9cf71eed486d4d9be08f8b55d0a7 ia kelihatan sentiasa menjadi "senarai" item seperti ini:

<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>

Untuk mewakili setiap daripada mereka, kita boleh menentukan KeyValue 结构,其中 Value 只是一个接口来表示它可以容纳的任何内容(datainteger,...)

type KeyValue struct {
    Key   string
    Value Value
}

type Value interface {
    getXMLName() string // this will return data, integer, array, etc, depending on the implementation
}

Kami kemudiannya boleh melaksanakan ini menggunakan pelbagai jenis yang disediakan dalam contoh 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" }

Di dalam teg XML, chardata 用于避免在我们的 XML 文档中包含额外的级别;对于 ValueStringArray,我们使用 string kerana itulah cara projek anda dinamakan.

Akhir sekali, untuk membenarkan rekursi (dict 内部 dict), kita juga boleh mentakrifkan struktur ini:

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

func (v ValueDict) getXMLName() string { return "dict" }

Selepas semua operasi selesai, kami boleh melaksanakan marshaler tersuai:

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
}

Ini akan membolehkan untuk menjana projek seperti:

<key>Line Width</key>
<real>0.004000000189989805</real>

Nama tag (inilah kaedah real)基于 getXMLName() dikembalikan.

Akhir sekali, anda boleh menentukan struct Go dan marshal seperti ini:

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)

Ini akan mencetak dengan tepat apa yang terdapat dalam contoh XML yang disediakan dalam soalan anda.

Anda boleh menguji kod lengkap di Go Playground: https://go.dev/play/p /k8cEIywx3UB.

Kelebihan utama penyelesaian ini ialah:

  • Kami hanya perlu melaksanakan marshaler XML tersuai
  • Jika anda mempunyai struktur lain dalam dokumen XML anda (katakan nilai boolean, kami boleh mencipta pelaksanaan ValueBool ValueBool 实现 Value), anda boleh melanjutkannya dengan mudah

Atas ialah kandungan terperinci Konflik nama kunci xml Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam
Artikel sebelumnya:Cara menggunakan kepingan GoArtikel seterusnya:Cara menggunakan kepingan Go