我正在尝试将存储在 xml 文档中的数据转换为替代数据存储。我尝试了多种技术,但没有一种被证明有效。问题是 xml 没有固定的模式并且具有非常规的结构。 xml示例如下
<?xml version="1.0"?>
<Data>
<f.1 value="field value" />
<f.2 value="other value" />
<f.3 value="field value 2" />
<withchildren>
<f.3.1 value="testvalue" />
<f.3.2 value="test value 3" />
</withchildren>
</Data>
理想情况下,最终结果应将结果存储在 map[string]interface{}
中,以便将值转换为标准的多维 JSON 格式。
最佳答案
当您不确定结构时 goquery可能是你最好的选择。您的标签名称看起来有点奇怪,我认为这只是示例。下面的代码使用标签名称作为键并使用值属性,但您可以为任何结构修改它。
package main
import (
"fmt"
"github.com/PuerkitoBio/goquery"
"strings"
)
func main() {
xml := `
<?xml version="1.0"?>
<Data>
<f1 value="field value"></f1>
<f2 value="other value"></f2>
<f3 value="field value 2"></f3>
<withchildren>
<f31 value="testvalue"></f31>
<f32 value="test value 3"></f32>
</withchildren>
</Data>
`
data := make(map[string]interface{})
reader := strings.NewReader(xml)
doc, _ := goquery.NewDocumentFromReader(reader)
children := doc.Find("Data").Children()
children.Each(func(i int, s *goquery.Selection) {
val, exists := s.Attr("value")
if exists {
data[goquery.NodeName(s)] = val
}
withchildren := s.Children()
if withchildren.Length() > 0 {
withchildren.Each(func(i int, s *goquery.Selection) {
val, exists := s.Attr("value")
if exists {
data[goquery.NodeName(s)] = val
}
})
}
})
fmt.Println(data)
}
如果您真的不知道结构可能是什么或可能有多少嵌套元素,请尝试这个递归版本。
如果您有多个具有相同名称的元素,那么您可以修改代码以添加一个带有键名的数字。所以“tag1”、“tag2”等。
package main
import (
"github.com/PuerkitoBio/goquery"
"strings"
)
func main() {
xml := `
<?xml version="1.0"?>
<Data>
<f1 value="field value"></f1>
<f2 value="other value"></f2>
<f3 value="field value 2"></f3>
<withchildren>
<f31 value="testvalue"></f31>
<f32 value="test value 3"></f32>
</withchildren>
</Data>
`
data := make(map[string]interface{})
reader := strings.NewReader(xml)
doc, _ := goquery.NewDocumentFromReader(reader)
children := doc.Find("Data").Children()
data = getElements(children)
}
func getElements(children *goquery.Selection) map[string]interface{} {
data := make(map[string]interface{})
children.Each(func(i int, s *goquery.Selection) {
val, exists := s.Attr("value")
if exists {
data[goquery.NodeName(s)] = val
}
if s.Children().Length() > 0 {
data[goquery.NodeName(s)] = getElements(s.Children())
}
})
return data
}
还有一些我没用过的Go包。
mxj将 xml 转换为 map[string]interface{}
goxml2json从 xml 转换为 json。
关于xml - 使用属性作为动态节点的值映射 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48432473/