Как разобрать неопределенный xml в golang?

avatar
Frank AK
1 июля 2021 в 15:58
82
0
0

образец входных данных:

<xml>
    <hello>world</hello>
    <name>frank</name>
    <item_01></item_01>
    <item_02></item_02>
    <item_03></item_03>
</xml>

простой способ:

message Product {
    string hello = 1[(trpc.go_tag) = 'xml:"hello"'];
    string name = 2[(trpc.go_tag) = 'xml:"name"'];
    string item_01 = 3[(trpc.go_tag) = 'xml:"item_01"'];
    string item_02 = 4[(trpc.go_tag) = 'xml:"item_02"'];
    string item_03 = 5[(trpc.go_tag) = 'xml:"item_03"'];
}

Но после изменения данных xml, например:

<xml>
    <hello>world</hello>
    <name>frank</name>
    <item_01></item_01>
    <item_02></item_02>
    <item_03></item_03>
    <item_04></item_04>
    <item_05></item_05>
    <item_06></item_06>
</xml>

Мне нужно снова изменить protobuf. поэтому меня попробовали следующим образом.

  1. создайте функцию предварительной обработки XML, которая может группировать его по префиксу поля, например:
<xml>
    <hello>world</hello>
    <name>frank</name>
    <item_list>
        <item>a</item>
        <item>b</item>
        <item>c</item>
        <item>d</item>
    </item_list>
</xml>

  1. так что мой protobuf может быть
message Product {
    string hello = 1[(trpc.go_tag) = 'xml:"hello"'];
    string name = 2[(trpc.go_tag) = 'xml:"name"'];
    ItemListType item_list = 3[(trpc.go_tag) = 'xml:"item_list"'];
}

message ItemListType {
    repeated string item = 1[(trpc.go_tag) = 'xml:"item"'];
}

Моя функция предварительной обработки, например, может группировать xml, которые уже скрыты, для сопоставления с новой картой:

func GroupSubTag(content map[string]string, prefixMap map[string]string) (map[string]interface{}, error){
    newMap := make(map[string]interface{})
    markDelete := make(map[string]bool)
    for prefix, newCol := range prefixMap {
        for k, v := range content {
            if isMarkDelete, ok := markDelete[k]; ok {
                if isMarkDelete {
                    continue
                }
            }
            if strings.HasPrefix(k, prefix) && endWithDigit(k){
                markDelete[k] = true
                existValue, ok := newMap[newCol]
                if !ok {
                    newMap[newCol] = []string{
                        v,
                    }
                    continue
                }
                switch item := existValue.(type) {
                case []string:
                    item = append(item, v)
                    newMap[newCol] = item
                default:
                    log.Fatalf("should never be here")
                }
            }else{
                // add rest of data
                newMap[k] = v
            }
        }
    }

    for k, _ := range markDelete {
        delete(newMap, k)
    }
    return newMap, nil
}

func endWithDigit(s string)bool{
    r := []rune(s)
    lengthOfRune := len(r)
    lastOne := r[lengthOfRune-1]
    if unicode.IsDigit(lastOne) {
        return true
    }else{
        return false
    }
}

на данный момент я могу сделать только XML для карты, как мне сделать это для моего protobuf можно ли распаковать ?

Источник
Xander Bielby
2 июля 2021 в 13:35
0

Вы должны использовать библиотеку сортировки XML, прочитать структуру XML, отредактировать ее, а затем повторно сгенерировать текстовый файл XML.

Ответы (0)