首页 > 解决方案 > 如何在golang中解组一个未确定的xml?

问题描述

输入数据样本:

<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 制作为地图,如何制作到我的protobufcan unmarshal ?

标签: xmlgoprotocol-buffers

解决方案


推荐阅读